[TASK] Move publicly accessible files to typo3temp/assets/
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Page / PageGenerator.php
1 <?php
2 namespace TYPO3\CMS\Frontend\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
17 use TYPO3\CMS\Core\Page\PageRenderer;
18 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
19 use TYPO3\CMS\Core\Type\File\ImageInfo;
20 use TYPO3\CMS\Core\Utility\ArrayUtility;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22 use TYPO3\CMS\Core\Utility\MathUtility;
23 use TYPO3\CMS\Core\Utility\PathUtility;
24 use TYPO3\CMS\Extbase\Service\TypoScriptService;
25 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
26 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
27
28 /**
29 * Class for starting TypoScript page generation
30 *
31 * The class is not instantiated as an objects but called directly with the "::" operator.
32 * eg: \TYPO3\CMS\Frontend\Page\PageGenerator::pagegenInit()
33 */
34 class PageGenerator
35 {
36 /**
37 * Do not render title tag
38 * Typoscript setting: [config][noPageTitle]
39 */
40 const NO_PAGE_TITLE = 2;
41
42 /**
43 * Setting some vars in TSFE, primarily based on TypoScript config settings.
44 *
45 * @return void
46 */
47 public static function pagegenInit()
48 {
49 /** @var TypoScriptFrontendController $tsfe */
50 $tsfe = $GLOBALS['TSFE'];
51 if ($tsfe->page['content_from_pid'] > 0) {
52 // make REAL copy of TSFE object - not reference!
53 $temp_copy_TSFE = clone $tsfe;
54 // Set ->id to the content_from_pid value - we are going to evaluate this pid as was it a given id for a page-display!
55 $temp_copy_TSFE->id = $tsfe->page['content_from_pid'];
56 $temp_copy_TSFE->MP = '';
57 $temp_copy_TSFE->getPageAndRootlineWithDomain($tsfe->config['config']['content_from_pid_allowOutsideDomain'] ? 0 : $tsfe->domainStartPage);
58 $tsfe->contentPid = (int)$temp_copy_TSFE->id;
59 unset($temp_copy_TSFE);
60 }
61 if ($tsfe->config['config']['MP_defaults']) {
62 $temp_parts = GeneralUtility::trimExplode('|', $tsfe->config['config']['MP_defaults'], true);
63 foreach ($temp_parts as $temp_p) {
64 list($temp_idP, $temp_MPp) = explode(':', $temp_p, 2);
65 $temp_ids = GeneralUtility::intExplode(',', $temp_idP);
66 foreach ($temp_ids as $temp_id) {
67 $tsfe->MP_defaults[$temp_id] = $temp_MPp;
68 }
69 }
70 }
71 // Global vars...
72 $tsfe->indexedDocTitle = $tsfe->page['title'];
73 $tsfe->debug = '' . $tsfe->config['config']['debug'];
74 // Base url:
75 if (isset($tsfe->config['config']['baseURL'])) {
76 $tsfe->baseUrl = $tsfe->config['config']['baseURL'];
77 }
78 // Internal and External target defaults
79 $tsfe->intTarget = '' . $tsfe->config['config']['intTarget'];
80 $tsfe->extTarget = '' . $tsfe->config['config']['extTarget'];
81 $tsfe->fileTarget = '' . $tsfe->config['config']['fileTarget'];
82 if ($tsfe->config['config']['spamProtectEmailAddresses'] === 'ascii') {
83 $tsfe->spamProtectEmailAddresses = 'ascii';
84 } else {
85 $tsfe->spamProtectEmailAddresses = MathUtility::forceIntegerInRange($tsfe->config['config']['spamProtectEmailAddresses'], -10, 10, 0);
86 }
87 // calculate the absolute path prefix
88 if (!empty($tsfe->config['config']['absRefPrefix'])) {
89 $absRefPrefix = trim($tsfe->config['config']['absRefPrefix']);
90 if ($absRefPrefix === 'auto') {
91 $tsfe->absRefPrefix = GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
92 } else {
93 $tsfe->absRefPrefix = $absRefPrefix;
94 }
95 } else {
96 $tsfe->absRefPrefix = '';
97 }
98 if ($tsfe->type && $tsfe->config['config']['frameReloadIfNotInFrameset']) {
99 $tdlLD = $tsfe->tmpl->linkData($tsfe->page, '_top', $tsfe->no_cache, '');
100 $tsfe->additionalJavaScript['JSCode'] .= 'if(!parent.' . trim($tsfe->sPre) . ' && !parent.view_frame) top.location.href="' . $tsfe->baseUrlWrap($tdlLD['totalURL']) . '"';
101 }
102 $tsfe->compensateFieldWidth = '' . $tsfe->config['config']['compensateFieldWidth'];
103 $tsfe->lockFilePath = '' . $tsfe->config['config']['lockFilePath'];
104 $tsfe->lockFilePath = $tsfe->lockFilePath ?: $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'];
105 $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_noScaleUp'] = isset($tsfe->config['config']['noScaleUp']) ? '' . $tsfe->config['config']['noScaleUp'] : $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_noScaleUp'];
106 $tsfe->TYPO3_CONF_VARS['GFX']['im_noScaleUp'] = $GLOBALS['TYPO3_CONF_VARS']['GFX']['im_noScaleUp'];
107 $tsfe->ATagParams = trim($tsfe->config['config']['ATagParams']) ? ' ' . trim($tsfe->config['config']['ATagParams']) : '';
108 if ($tsfe->config['config']['setJS_mouseOver']) {
109 $tsfe->setJS('mouseOver');
110 }
111 if ($tsfe->config['config']['setJS_openPic']) {
112 $tsfe->setJS('openPic');
113 }
114 static::initializeSearchWordDataInTsfe();
115 // linkVars
116 $tsfe->calculateLinkVars();
117 // dtdAllowsFrames indicates whether to use the target attribute in links
118 $tsfe->dtdAllowsFrames = false;
119 if ($tsfe->config['config']['doctype']) {
120 if (in_array(
121 (string)$tsfe->config['config']['doctype'],
122 array('xhtml_trans', 'xhtml_frames', 'xhtml_basic', 'html5'),
123 true)
124 ) {
125 $tsfe->dtdAllowsFrames = true;
126 }
127 } else {
128 $tsfe->dtdAllowsFrames = true;
129 }
130 // Setting XHTML-doctype from doctype
131 if (!$tsfe->config['config']['xhtmlDoctype']) {
132 $tsfe->config['config']['xhtmlDoctype'] = $tsfe->config['config']['doctype'];
133 }
134 if ($tsfe->config['config']['xhtmlDoctype']) {
135 $tsfe->xhtmlDoctype = $tsfe->config['config']['xhtmlDoctype'];
136 // Checking XHTML-docytpe
137 switch ((string)$tsfe->config['config']['xhtmlDoctype']) {
138 case 'xhtml_trans':
139
140 case 'xhtml_strict':
141
142 case 'xhtml_frames':
143 $tsfe->xhtmlVersion = 100;
144 break;
145 case 'xhtml_basic':
146 $tsfe->xhtmlVersion = 105;
147 break;
148 case 'xhtml_11':
149
150 case 'xhtml+rdfa_10':
151 $tsfe->xhtmlVersion = 110;
152 break;
153 default:
154 static::getPageRenderer()->setRenderXhtml(false);
155 $tsfe->xhtmlDoctype = '';
156 $tsfe->xhtmlVersion = 0;
157 }
158 } else {
159 static::getPageRenderer()->setRenderXhtml(false);
160 }
161 }
162
163 /**
164 * Rendering the page content
165 *
166 * @return void
167 */
168 public static function renderContent()
169 {
170 /** @var TypoScriptFrontendController $tsfe */
171 $tsfe = $GLOBALS['TSFE'];
172
173 /** @var TimeTracker $timeTracker */
174 $timeTracker = $GLOBALS['TT'];
175
176 // PAGE CONTENT
177 $timeTracker->incStackPointer();
178 $timeTracker->push($tsfe->sPre, 'PAGE');
179 $pageContent = $tsfe->cObj->cObjGet($tsfe->pSetup);
180 if ($tsfe->pSetup['wrap']) {
181 $pageContent = $tsfe->cObj->wrap($pageContent, $tsfe->pSetup['wrap']);
182 }
183 if ($tsfe->pSetup['stdWrap.']) {
184 $pageContent = $tsfe->cObj->stdWrap($pageContent, $tsfe->pSetup['stdWrap.']);
185 }
186 // PAGE HEADER (after content - maybe JS is inserted!
187 // if 'disableAllHeaderCode' is set, all the header-code is discarded!
188 if ($tsfe->config['config']['disableAllHeaderCode']) {
189 $tsfe->content = $pageContent;
190 } else {
191 self::renderContentWithHeader($pageContent);
192 }
193 $timeTracker->pull($timeTracker->LR ? $tsfe->content : '');
194 $timeTracker->decStackPointer();
195 }
196
197 /**
198 * Rendering normal HTML-page with header by wrapping the generated content ($pageContent) in body-tags and setting the header accordingly.
199 *
200 * @param string $pageContent The page content which TypoScript objects has generated
201 * @return void
202 */
203 public static function renderContentWithHeader($pageContent)
204 {
205 /** @var TypoScriptFrontendController $tsfe */
206 $tsfe = $GLOBALS['TSFE'];
207
208 /** @var TimeTracker $timeTracker */
209 $timeTracker = $GLOBALS['TT'];
210
211 $pageRenderer = static::getPageRenderer();
212 if ($tsfe->config['config']['moveJsFromHeaderToFooter']) {
213 $pageRenderer->enableMoveJsFromHeaderToFooter();
214 }
215 if ($tsfe->config['config']['pageRendererTemplateFile']) {
216 $file = $tsfe->tmpl->getFileName($tsfe->config['config']['pageRendererTemplateFile']);
217 if ($file) {
218 $pageRenderer->setTemplateFile($file);
219 }
220 }
221 $headerComment = $tsfe->config['config']['headerComment'];
222 if (trim($headerComment)) {
223 $pageRenderer->addInlineComment(TAB . str_replace(LF, (LF . TAB), trim($headerComment)) . LF);
224 }
225 // Setting charset:
226 $theCharset = $tsfe->metaCharset;
227 // Reset the content variables:
228 $tsfe->content = '';
229 $htmlTagAttributes = array();
230 $htmlLang = $tsfe->config['config']['htmlTag_langKey'] ?: ($tsfe->sys_language_isocode ?: 'en');
231 // Set content direction: (More info: http://www.tau.ac.il/~danon/Hebrew/HTML_and_Hebrew.html)
232 if ($tsfe->config['config']['htmlTag_dir']) {
233 $htmlTagAttributes['dir'] = htmlspecialchars($tsfe->config['config']['htmlTag_dir']);
234 }
235 // Setting document type:
236 $docTypeParts = array();
237 $xmlDocument = true;
238 // Part 1: XML prologue
239 switch ((string)$tsfe->config['config']['xmlprologue']) {
240 case 'none':
241 $xmlDocument = false;
242 break;
243 case 'xml_10':
244 $docTypeParts[] = '<?xml version="1.0" encoding="' . $theCharset . '"?>';
245 break;
246 case 'xml_11':
247 $docTypeParts[] = '<?xml version="1.1" encoding="' . $theCharset . '"?>';
248 break;
249 case '':
250 if ($tsfe->xhtmlVersion) {
251 $docTypeParts[] = '<?xml version="1.0" encoding="' . $theCharset . '"?>';
252 } else {
253 $xmlDocument = false;
254 }
255 break;
256 default:
257 $docTypeParts[] = $tsfe->config['config']['xmlprologue'];
258 }
259 // Part 2: DTD
260 $doctype = $tsfe->config['config']['doctype'];
261 if ($doctype) {
262 switch ($doctype) {
263 case 'xhtml_trans':
264 $docTypeParts[] = '<!DOCTYPE html
265 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
266 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
267 break;
268 case 'xhtml_strict':
269 $docTypeParts[] = '<!DOCTYPE html
270 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
271 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
272 break;
273 case 'xhtml_frames':
274 $docTypeParts[] = '<!DOCTYPE html
275 PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
276 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">';
277 break;
278 case 'xhtml_basic':
279 $docTypeParts[] = '<!DOCTYPE html
280 PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
281 "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">';
282 break;
283 case 'xhtml_11':
284 $docTypeParts[] = '<!DOCTYPE html
285 PUBLIC "-//W3C//DTD XHTML 1.1//EN"
286 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
287 break;
288 case 'xhtml+rdfa_10':
289 $docTypeParts[] = '<!DOCTYPE html
290 PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
291 "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">';
292 break;
293 case 'html5':
294 $docTypeParts[] = '<!DOCTYPE html>';
295 if ($xmlDocument) {
296 $pageRenderer->setMetaCharsetTag('<meta charset="|" />');
297 } else {
298 $pageRenderer->setMetaCharsetTag('<meta charset="|">');
299 }
300 break;
301 case 'none':
302 break;
303 default:
304 $docTypeParts[] = $doctype;
305 }
306 } else {
307 $docTypeParts[] = '<!DOCTYPE html>';
308 if ($xmlDocument) {
309 $pageRenderer->setMetaCharsetTag('<meta charset="|" />');
310 } else {
311 $pageRenderer->setMetaCharsetTag('<meta charset="|">');
312 }
313 }
314 if ($tsfe->xhtmlVersion) {
315 $htmlTagAttributes['xml:lang'] = $htmlLang;
316 }
317 if ($tsfe->xhtmlVersion < 110 || $doctype === 'html5') {
318 $htmlTagAttributes['lang'] = $htmlLang;
319 }
320 if ($tsfe->xhtmlVersion || $doctype === 'html5' && $xmlDocument) {
321 // We add this to HTML5 to achieve a slightly better backwards compatibility
322 $htmlTagAttributes['xmlns'] = 'http://www.w3.org/1999/xhtml';
323 if (is_array($tsfe->config['config']['namespaces.'])) {
324 foreach ($tsfe->config['config']['namespaces.'] as $prefix => $uri) {
325 // $uri gets htmlspecialchared later
326 $htmlTagAttributes['xmlns:' . htmlspecialchars($prefix)] = $uri;
327 }
328 }
329 }
330 // Swap XML and doctype order around (for MSIE / Opera standards compliance)
331 if ($tsfe->config['config']['doctypeSwitch']) {
332 $docTypeParts = array_reverse($docTypeParts);
333 }
334 // Adding doctype parts:
335 if (!empty($docTypeParts)) {
336 $pageRenderer->setXmlPrologAndDocType(implode(LF, $docTypeParts));
337 }
338 // Begin header section:
339 if ($tsfe->config['config']['htmlTag_setParams'] !== 'none') {
340 $_attr = $tsfe->config['config']['htmlTag_setParams'] ? $tsfe->config['config']['htmlTag_setParams'] : GeneralUtility::implodeAttributes($htmlTagAttributes);
341 } else {
342 $_attr = '';
343 }
344 $htmlTag = '<html' . ($_attr ? ' ' . $_attr : '') . '>';
345 if (isset($tsfe->config['config']['htmlTag_stdWrap.'])) {
346 $htmlTag = $tsfe->cObj->stdWrap($htmlTag, $tsfe->config['config']['htmlTag_stdWrap.']);
347 }
348 $pageRenderer->setHtmlTag($htmlTag);
349 // Head tag:
350 $headTag = $tsfe->pSetup['headTag'] ?: '<head>';
351 if (isset($tsfe->pSetup['headTag.'])) {
352 $headTag = $tsfe->cObj->stdWrap($headTag, $tsfe->pSetup['headTag.']);
353 }
354 $pageRenderer->setHeadTag($headTag);
355 // Setting charset meta tag:
356 $pageRenderer->setCharSet($theCharset);
357 $pageRenderer->addInlineComment(' This website is powered by TYPO3 - inspiring people to share!
358 TYPO3 is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.
359 TYPO3 is copyright ' . TYPO3_copyright_year . ' of Kasper Skaarhoj. Extensions are copyright of their respective owners.
360 Information and contribution at ' . TYPO3_URL_GENERAL . '
361 ');
362 if ($tsfe->baseUrl) {
363 $pageRenderer->setBaseUrl($tsfe->baseUrl);
364 }
365 if ($tsfe->pSetup['shortcutIcon']) {
366 $favIcon = ltrim($tsfe->tmpl->getFileName($tsfe->pSetup['shortcutIcon']), '/');
367 $iconFileInfo = GeneralUtility::makeInstance(ImageInfo::class, PATH_site . $favIcon);
368 if ($iconFileInfo->isFile()) {
369 $iconMimeType = $iconFileInfo->getMimeType();
370 if ($iconMimeType) {
371 $iconMimeType = ' type="' . $iconMimeType . '"';
372 $pageRenderer->setIconMimeType($iconMimeType);
373 }
374 $pageRenderer->setFavIcon(PathUtility::getAbsoluteWebPath($tsfe->absRefPrefix . $favIcon));
375 }
376 }
377 // Including CSS files
378 if (is_array($tsfe->tmpl->setup['plugin.'])) {
379 $stylesFromPlugins = '';
380 foreach ($tsfe->tmpl->setup['plugin.'] as $key => $iCSScode) {
381 if (is_array($iCSScode)) {
382 if ($iCSScode['_CSS_DEFAULT_STYLE'] && empty($tsfe->config['config']['removeDefaultCss'])) {
383 if (isset($iCSScode['_CSS_DEFAULT_STYLE.'])) {
384 $cssDefaultStyle = $tsfe->cObj->stdWrap($iCSScode['_CSS_DEFAULT_STYLE'], $iCSScode['_CSS_DEFAULT_STYLE.']);
385 } else {
386 $cssDefaultStyle = $iCSScode['_CSS_DEFAULT_STYLE'];
387 }
388 $stylesFromPlugins .= '/* default styles for extension "' . substr($key, 0, -1) . '" */' . LF . $cssDefaultStyle . LF;
389 }
390 if ($iCSScode['_CSS_PAGE_STYLE'] && empty($tsfe->config['config']['removePageCss'])) {
391 $cssPageStyle = implode(LF, $iCSScode['_CSS_PAGE_STYLE']);
392 if (isset($iCSScode['_CSS_PAGE_STYLE.'])) {
393 $cssPageStyle = $tsfe->cObj->stdWrap($cssPageStyle, $iCSScode['_CSS_PAGE_STYLE.']);
394 }
395 $cssPageStyle = '/* specific page styles for extension "' . substr($key, 0, -1) . '" */' . LF . $cssPageStyle;
396 self::addCssToPageRenderer($cssPageStyle, true);
397 }
398 }
399 }
400 if (!empty($stylesFromPlugins)) {
401 self::addCssToPageRenderer($stylesFromPlugins);
402 }
403 }
404 if ($tsfe->pSetup['stylesheet']) {
405 $ss = $tsfe->tmpl->getFileName($tsfe->pSetup['stylesheet']);
406 if ($ss) {
407 $pageRenderer->addCssFile($ss);
408 }
409 }
410 /**********************************************************************/
411 /* config.includeCSS / config.includeCSSLibs
412 /**********************************************************************/
413 if (is_array($tsfe->pSetup['includeCSS.'])) {
414 foreach ($tsfe->pSetup['includeCSS.'] as $key => $CSSfile) {
415 if (!is_array($CSSfile)) {
416 $cssFileConfig = &$tsfe->pSetup['includeCSS.'][$key . '.'];
417 if (isset($cssFileConfig['if.']) && !$tsfe->cObj->checkIf($cssFileConfig['if.'])) {
418 continue;
419 }
420 $ss = $cssFileConfig['external'] ? $CSSfile : $tsfe->tmpl->getFileName($CSSfile);
421 if ($ss) {
422 if ($cssFileConfig['import']) {
423 if (!$cssFileConfig['external'] && $ss[0] !== '/') {
424 // To fix MSIE 6 that cannot handle these as relative paths (according to Ben v Ende)
425 $ss = GeneralUtility::dirname(GeneralUtility::getIndpEnv('SCRIPT_NAME')) . '/' . $ss;
426 }
427 $pageRenderer->addCssInlineBlock('import_' . $key, '@import url("' . htmlspecialchars($ss) . '") ' . htmlspecialchars($cssFileConfig['media']) . ';', empty($cssFileConfig['disableCompression']), (bool)$cssFileConfig['forceOnTop'], '');
428 } else {
429 $pageRenderer->addCssFile(
430 $ss,
431 $cssFileConfig['alternate'] ? 'alternate stylesheet' : 'stylesheet',
432 $cssFileConfig['media'] ?: 'all',
433 $cssFileConfig['title'] ?: '',
434 empty($cssFileConfig['disableCompression']),
435 (bool)$cssFileConfig['forceOnTop'],
436 $cssFileConfig['allWrap'],
437 (bool)$cssFileConfig['excludeFromConcatenation'],
438 $cssFileConfig['allWrap.']['splitChar']
439 );
440 unset($cssFileConfig);
441 }
442 }
443 }
444 }
445 }
446 if (is_array($tsfe->pSetup['includeCSSLibs.'])) {
447 foreach ($tsfe->pSetup['includeCSSLibs.'] as $key => $CSSfile) {
448 if (!is_array($CSSfile)) {
449 $cssFileConfig = &$tsfe->pSetup['includeCSSLibs.'][$key . '.'];
450 if (isset($cssFileConfig['if.']) && !$tsfe->cObj->checkIf($cssFileConfig['if.'])) {
451 continue;
452 }
453 $ss = $cssFileConfig['external'] ? $CSSfile : $tsfe->tmpl->getFileName($CSSfile);
454 if ($ss) {
455 if ($cssFileConfig['import']) {
456 if (!$cssFileConfig['external'] && $ss[0] !== '/') {
457 // To fix MSIE 6 that cannot handle these as relative paths (according to Ben v Ende)
458 $ss = GeneralUtility::dirname(GeneralUtility::getIndpEnv('SCRIPT_NAME')) . '/' . $ss;
459 }
460 $pageRenderer->addCssInlineBlock('import_' . $key, '@import url("' . htmlspecialchars($ss) . '") ' . htmlspecialchars($cssFileConfig['media']) . ';', empty($cssFileConfig['disableCompression']), (bool)$cssFileConfig['forceOnTop'], '');
461 } else {
462 $pageRenderer->addCssLibrary(
463 $ss,
464 $cssFileConfig['alternate'] ? 'alternate stylesheet' : 'stylesheet',
465 $cssFileConfig['media'] ?: 'all',
466 $cssFileConfig['title'] ?: '',
467 empty($cssFileConfig['disableCompression']),
468 (bool)$cssFileConfig['forceOnTop'],
469 $cssFileConfig['allWrap'],
470 (bool)$cssFileConfig['excludeFromConcatenation'],
471 $cssFileConfig['allWrap.']['splitChar']
472 );
473 unset($cssFileConfig);
474 }
475 }
476 }
477 }
478 }
479
480 // Stylesheets
481 $style = '';
482 if ($tsfe->pSetup['insertClassesFromRTE']) {
483 $pageTSConfig = $tsfe->getPagesTSconfig();
484 $RTEclasses = $pageTSConfig['RTE.']['classes.'];
485 if (is_array($RTEclasses)) {
486 foreach ($RTEclasses as $RTEclassName => $RTEvalueArray) {
487 if ($RTEvalueArray['value']) {
488 $style .= '
489 .' . substr($RTEclassName, 0, -1) . ' {' . $RTEvalueArray['value'] . '}';
490 }
491 }
492 }
493 if ($tsfe->pSetup['insertClassesFromRTE.']['add_mainStyleOverrideDefs'] && is_array($pageTSConfig['RTE.']['default.']['mainStyleOverride_add.'])) {
494 $mSOa_tList = GeneralUtility::trimExplode(',', strtoupper($tsfe->pSetup['insertClassesFromRTE.']['add_mainStyleOverrideDefs']), true);
495 foreach ($pageTSConfig['RTE.']['default.']['mainStyleOverride_add.'] as $mSOa_key => $mSOa_value) {
496 if (!is_array($mSOa_value) && (in_array('*', $mSOa_tList) || in_array($mSOa_key, $mSOa_tList))) {
497 $style .= '
498 ' . $mSOa_key . ' {' . $mSOa_value . '}';
499 }
500 }
501 }
502 }
503 // Setting body tag margins in CSS:
504 if (isset($tsfe->pSetup['bodyTagMargins']) && $tsfe->pSetup['bodyTagMargins.']['useCSS']) {
505 $margins = (int)$tsfe->pSetup['bodyTagMargins'];
506 $style .= '
507 BODY {margin: ' . $margins . 'px ' . $margins . 'px ' . $margins . 'px ' . $margins . 'px;}';
508 }
509 // CSS_inlineStyle from TS
510 $style .= trim($tsfe->pSetup['CSS_inlineStyle']);
511 $style .= $tsfe->cObj->cObjGet($tsfe->pSetup['cssInline.'], 'cssInline.');
512 if (trim($style)) {
513 self::addCssToPageRenderer($style, true, 'additionalTSFEInlineStyle');
514 }
515 // Javascript Libraries
516 if (is_array($tsfe->pSetup['javascriptLibs.'])) {
517 // Include jQuery into the page renderer
518 if (!empty($tsfe->pSetup['javascriptLibs.']['jQuery'])) {
519 $jQueryTS = $tsfe->pSetup['javascriptLibs.']['jQuery.'];
520 // Check if version / source is set, if not set variable to "NULL" to use the default of the page renderer
521 $version = isset($jQueryTS['version']) ? $jQueryTS['version'] : null;
522 $source = isset($jQueryTS['source']) ? $jQueryTS['source'] : null;
523 // When "noConflict" is not set or "1" enable the default jQuery noConflict mode, otherwise disable the namespace
524 if (!isset($jQueryTS['noConflict']) || !empty($jQueryTS['noConflict'])) {
525 // Set namespace to the "noConflict.namespace" value if "noConflict.namespace" has a value
526 if (!empty($jQueryTS['noConflict.']['namespace'])) {
527 $namespace = $jQueryTS['noConflict.']['namespace'];
528 } else {
529 $namespace = PageRenderer::JQUERY_NAMESPACE_DEFAULT_NOCONFLICT;
530 }
531 } else {
532 $namespace = PageRenderer::JQUERY_NAMESPACE_NONE;
533 }
534 $pageRenderer->loadJQuery($version, $source, $namespace);
535 }
536 if ($tsfe->pSetup['javascriptLibs.']['ExtJs']) {
537 $css = (bool)$tsfe->pSetup['javascriptLibs.']['ExtJs.']['css'];
538 $theme = (bool)$tsfe->pSetup['javascriptLibs.']['ExtJs.']['theme'];
539 $pageRenderer->loadExtJs($css, $theme);
540 if ($tsfe->pSetup['javascriptLibs.']['ExtJs.']['debug']) {
541 $pageRenderer->enableExtJsDebug();
542 }
543 }
544 }
545 // JavaScript library files
546 if (is_array($tsfe->pSetup['includeJSlibs.']) || is_array($tsfe->pSetup['includeJSLibs.'])) {
547 if (!is_array($tsfe->pSetup['includeJSlibs.'])) {
548 $tsfe->pSetup['includeJSlibs.'] = array();
549 } else {
550 GeneralUtility::deprecationLog('The property page.includeJSlibs is marked for deprecation and will be removed in TYPO3 CMS 8. Please use page.includeJSLibs (with an uppercase L) instead.');
551 }
552 if (!is_array($tsfe->pSetup['includeJSLibs.'])) {
553 $tsfe->pSetup['includeJSLibs.'] = array();
554 }
555 ArrayUtility::mergeRecursiveWithOverrule(
556 $tsfe->pSetup['includeJSLibs.'],
557 $tsfe->pSetup['includeJSlibs.']
558 );
559 unset($tsfe->pSetup['includeJSlibs.']);
560 foreach ($tsfe->pSetup['includeJSLibs.'] as $key => $JSfile) {
561 if (!is_array($JSfile)) {
562 if (isset($tsfe->pSetup['includeJSLibs.'][$key . '.']['if.']) && !$tsfe->cObj->checkIf($tsfe->pSetup['includeJSLibs.'][$key . '.']['if.'])) {
563 continue;
564 }
565 $ss = $tsfe->pSetup['includeJSLibs.'][$key . '.']['external'] ? $JSfile : $tsfe->tmpl->getFileName($JSfile);
566 if ($ss) {
567 $jsFileConfig = &$tsfe->pSetup['includeJSLibs.'][$key . '.'];
568 $type = $jsFileConfig['type'];
569 if (!$type) {
570 $type = 'text/javascript';
571 }
572
573 $pageRenderer->addJsLibrary(
574 $key,
575 $ss,
576 $type,
577 empty($jsFileConfig['disableCompression']),
578 (bool)$jsFileConfig['forceOnTop'],
579 $jsFileConfig['allWrap'],
580 (bool)$jsFileConfig['excludeFromConcatenation'],
581 $jsFileConfig['allWrap.']['splitChar'],
582 (bool)$jsFileConfig['async'],
583 $jsFileConfig['integrity']
584 );
585 unset($jsFileConfig);
586 }
587 }
588 }
589 }
590 if (is_array($tsfe->pSetup['includeJSFooterlibs.'])) {
591 foreach ($tsfe->pSetup['includeJSFooterlibs.'] as $key => $JSfile) {
592 if (!is_array($JSfile)) {
593 if (isset($tsfe->pSetup['includeJSFooterlibs.'][$key . '.']['if.']) && !$tsfe->cObj->checkIf($tsfe->pSetup['includeJSFooterlibs.'][$key . '.']['if.'])) {
594 continue;
595 }
596 $ss = $tsfe->pSetup['includeJSFooterlibs.'][$key . '.']['external'] ? $JSfile : $tsfe->tmpl->getFileName($JSfile);
597 if ($ss) {
598 $jsFileConfig = &$tsfe->pSetup['includeJSFooterlibs.'][$key . '.'];
599 $type = $jsFileConfig['type'];
600 if (!$type) {
601 $type = 'text/javascript';
602 }
603 $pageRenderer->addJsFooterLibrary(
604 $key,
605 $ss,
606 $type,
607 empty($jsFileConfig['disableCompression']),
608 (bool)$jsFileConfig['forceOnTop'],
609 $jsFileConfig['allWrap'],
610 (bool)$jsFileConfig['excludeFromConcatenation'],
611 $jsFileConfig['allWrap.']['splitChar'],
612 (bool)$jsFileConfig['async'],
613 $jsFileConfig['integrity']
614 );
615 unset($jsFileConfig);
616 }
617 }
618 }
619 }
620 // JavaScript files
621 if (is_array($tsfe->pSetup['includeJS.'])) {
622 foreach ($tsfe->pSetup['includeJS.'] as $key => $JSfile) {
623 if (!is_array($JSfile)) {
624 if (isset($tsfe->pSetup['includeJS.'][$key . '.']['if.']) && !$tsfe->cObj->checkIf($tsfe->pSetup['includeJS.'][$key . '.']['if.'])) {
625 continue;
626 }
627 $ss = $tsfe->pSetup['includeJS.'][$key . '.']['external'] ? $JSfile : $tsfe->tmpl->getFileName($JSfile);
628 if ($ss) {
629 $jsConfig = &$tsfe->pSetup['includeJS.'][$key . '.'];
630 $type = $jsConfig['type'];
631 if (!$type) {
632 $type = 'text/javascript';
633 }
634 $pageRenderer->addJsFile(
635 $ss,
636 $type,
637 empty($jsConfig['disableCompression']),
638 (bool)$jsConfig['forceOnTop'],
639 $jsConfig['allWrap'],
640 (bool)$jsConfig['excludeFromConcatenation'],
641 $jsConfig['allWrap.']['splitChar'],
642 (bool)$jsConfig['async'],
643 $jsConfig['integrity']
644 );
645 unset($jsConfig);
646 }
647 }
648 }
649 }
650 if (is_array($tsfe->pSetup['includeJSFooter.'])) {
651 foreach ($tsfe->pSetup['includeJSFooter.'] as $key => $JSfile) {
652 if (!is_array($JSfile)) {
653 if (isset($tsfe->pSetup['includeJSFooter.'][$key . '.']['if.']) && !$tsfe->cObj->checkIf($tsfe->pSetup['includeJSFooter.'][$key . '.']['if.'])) {
654 continue;
655 }
656 $ss = $tsfe->pSetup['includeJSFooter.'][$key . '.']['external'] ? $JSfile : $tsfe->tmpl->getFileName($JSfile);
657 if ($ss) {
658 $jsConfig = &$tsfe->pSetup['includeJSFooter.'][$key . '.'];
659 $type = $jsConfig['type'];
660 if (!$type) {
661 $type = 'text/javascript';
662 }
663 $pageRenderer->addJsFooterFile(
664 $ss,
665 $type,
666 empty($jsConfig['disableCompression']),
667 (bool)$jsConfig['forceOnTop'],
668 $jsConfig['allWrap'],
669 (bool)$jsConfig['excludeFromConcatenation'],
670 $jsConfig['allWrap.']['splitChar'],
671 (bool)$jsConfig['async'],
672 $jsConfig['integrity']
673 );
674 unset($jsConfig);
675 }
676 }
677 }
678 }
679 // Headerdata
680 if (is_array($tsfe->pSetup['headerData.'])) {
681 $pageRenderer->addHeaderData($tsfe->cObj->cObjGet($tsfe->pSetup['headerData.'], 'headerData.'));
682 }
683 // Footerdata
684 if (is_array($tsfe->pSetup['footerData.'])) {
685 $pageRenderer->addFooterData($tsfe->cObj->cObjGet($tsfe->pSetup['footerData.'], 'footerData.'));
686 }
687 static::generatePageTitle();
688
689 $metaTagsHtml = static::generateMetaTagHtml(
690 isset($tsfe->pSetup['meta.']) ? $tsfe->pSetup['meta.'] : array(),
691 $tsfe->xhtmlVersion,
692 $tsfe->cObj
693 );
694 foreach ($metaTagsHtml as $metaTag) {
695 $pageRenderer->addMetaTag($metaTag);
696 }
697
698 unset($tsfe->additionalHeaderData['JSCode']);
699 if (is_array($tsfe->config['INTincScript'])) {
700 $tsfe->additionalHeaderData['JSCode'] = $tsfe->JSCode;
701 // Storing the JSCode vars...
702 $tsfe->config['INTincScript_ext']['divKey'] = $tsfe->uniqueHash();
703 $tsfe->config['INTincScript_ext']['additionalHeaderData'] = $tsfe->additionalHeaderData;
704 // Storing the header-data array
705 $tsfe->config['INTincScript_ext']['additionalFooterData'] = $tsfe->additionalFooterData;
706 // Storing the footer-data array
707 $tsfe->config['INTincScript_ext']['additionalJavaScript'] = $tsfe->additionalJavaScript;
708 // Storing the JS-data array
709 $tsfe->config['INTincScript_ext']['additionalCSS'] = $tsfe->additionalCSS;
710 // Storing the Style-data array
711 $tsfe->additionalHeaderData = array('<!--HD_' . $tsfe->config['INTincScript_ext']['divKey'] . '-->');
712 // Clearing the array
713 $tsfe->additionalFooterData = array('<!--FD_' . $tsfe->config['INTincScript_ext']['divKey'] . '-->');
714 // Clearing the array
715 $tsfe->divSection .= '<!--TDS_' . $tsfe->config['INTincScript_ext']['divKey'] . '-->';
716 } else {
717 $tsfe->INTincScript_loadJSCode();
718 }
719 $scriptJsCode = '';
720
721 if ($tsfe->spamProtectEmailAddresses && $tsfe->spamProtectEmailAddresses !== 'ascii') {
722 $scriptJsCode = '
723 // decrypt helper function
724 function decryptCharcode(n,start,end,offset) {
725 n = n + offset;
726 if (offset > 0 && n > end) {
727 n = start + (n - end - 1);
728 } else if (offset < 0 && n < start) {
729 n = end - (start - n - 1);
730 }
731 return String.fromCharCode(n);
732 }
733 // decrypt string
734 function decryptString(enc,offset) {
735 var dec = "";
736 var len = enc.length;
737 for(var i=0; i < len; i++) {
738 var n = enc.charCodeAt(i);
739 if (n >= 0x2B && n <= 0x3A) {
740 dec += decryptCharcode(n,0x2B,0x3A,offset); // 0-9 . , - + / :
741 } else if (n >= 0x40 && n <= 0x5A) {
742 dec += decryptCharcode(n,0x40,0x5A,offset); // A-Z @
743 } else if (n >= 0x61 && n <= 0x7A) {
744 dec += decryptCharcode(n,0x61,0x7A,offset); // a-z
745 } else {
746 dec += enc.charAt(i);
747 }
748 }
749 return dec;
750 }
751 // decrypt spam-protected emails
752 function linkTo_UnCryptMailto(s) {
753 location.href = decryptString(s,' . $tsfe->spamProtectEmailAddresses * -1 . ');
754 }
755 ';
756 }
757 // Add inline JS
758 $inlineJS = '';
759 // defined in php
760 if (is_array($tsfe->inlineJS)) {
761 foreach ($tsfe->inlineJS as $key => $val) {
762 if (!is_array($val)) {
763 $inlineJS .= LF . $val . LF;
764 }
765 }
766 }
767 // defined in TS with page.inlineJS
768 // Javascript inline code
769 $inline = $tsfe->cObj->cObjGet($tsfe->pSetup['jsInline.'], 'jsInline.');
770 if ($inline) {
771 $inlineJS .= LF . $inline . LF;
772 }
773 // Javascript inline code for Footer
774 $inlineFooterJs = $tsfe->cObj->cObjGet($tsfe->pSetup['jsFooterInline.'], 'jsFooterInline.');
775 // Should minify?
776 if ($tsfe->config['config']['compressJs']) {
777 $pageRenderer->enableCompressJavascript();
778 $minifyErrorScript = ($minifyErrorInline = '');
779 $scriptJsCode = GeneralUtility::minifyJavaScript($scriptJsCode, $minifyErrorScript);
780 if ($minifyErrorScript) {
781 $timeTracker->setTSlogMessage($minifyErrorScript, 3);
782 }
783 if ($inlineJS) {
784 $inlineJS = GeneralUtility::minifyJavaScript($inlineJS, $minifyErrorInline);
785 if ($minifyErrorInline) {
786 $timeTracker->setTSlogMessage($minifyErrorInline, 3);
787 }
788 }
789 if ($inlineFooterJs) {
790 $inlineFooterJs = GeneralUtility::minifyJavaScript($inlineFooterJs, $minifyErrorInline);
791 if ($minifyErrorInline) {
792 $timeTracker->setTSlogMessage($minifyErrorInline, 3);
793 }
794 }
795 }
796 if (!$tsfe->config['config']['removeDefaultJS']) {
797 // inlude default and inlineJS
798 if ($scriptJsCode) {
799 $pageRenderer->addJsInlineCode('_scriptCode', $scriptJsCode, $tsfe->config['config']['compressJs']);
800 }
801 if ($inlineJS) {
802 $pageRenderer->addJsInlineCode('TS_inlineJS', $inlineJS, $tsfe->config['config']['compressJs']);
803 }
804 if ($inlineFooterJs) {
805 $pageRenderer->addJsFooterInlineCode('TS_inlineFooter', $inlineFooterJs, $tsfe->config['config']['compressJs']);
806 }
807 } elseif ($tsfe->config['config']['removeDefaultJS'] === 'external') {
808 /*
809 * This keeps inlineJS from *_INT Objects from being moved to external files.
810 * At this point in frontend rendering *_INT Objects only have placeholders instead
811 * of actual content so moving these placeholders to external files would
812 * a) break the JS file (syntax errors due to the placeholders)
813 * b) the needed JS would never get included to the page
814 * Therefore inlineJS from *_INT Objects must not be moved to external files but
815 * kept internal.
816 */
817 $inlineJSint = '';
818 self::stripIntObjectPlaceholder($inlineJS, $inlineJSint);
819 if ($inlineJSint) {
820 $pageRenderer->addJsInlineCode('TS_inlineJSint', $inlineJSint, $tsfe->config['config']['compressJs']);
821 }
822 if (trim($scriptJsCode . $inlineJS)) {
823 $pageRenderer->addJsFile(self::inline2TempFile($scriptJsCode . $inlineJS, 'js'), 'text/javascript', $tsfe->config['config']['compressJs']);
824 }
825 if ($inlineFooterJs) {
826 $inlineFooterJSint = '';
827 self::stripIntObjectPlaceholder($inlineFooterJs, $inlineFooterJSint);
828 if ($inlineFooterJSint) {
829 $pageRenderer->addJsFooterInlineCode('TS_inlineFooterJSint', $inlineFooterJSint, $tsfe->config['config']['compressJs']);
830 }
831 $pageRenderer->addJsFooterFile(self::inline2TempFile($inlineFooterJs, 'js'), 'text/javascript', $tsfe->config['config']['compressJs']);
832 }
833 } else {
834 // Include only inlineJS
835 if ($inlineJS) {
836 $pageRenderer->addJsInlineCode('TS_inlineJS', $inlineJS, $tsfe->config['config']['compressJs']);
837 }
838 if ($inlineFooterJs) {
839 $pageRenderer->addJsFooterInlineCode('TS_inlineFooter', $inlineFooterJs, $tsfe->config['config']['compressJs']);
840 }
841 }
842 if (is_array($tsfe->pSetup['inlineLanguageLabelFiles.'])) {
843 foreach ($tsfe->pSetup['inlineLanguageLabelFiles.'] as $key => $languageFile) {
844 if (is_array($languageFile)) {
845 continue;
846 }
847 $languageFileConfig = &$tsfe->pSetup['inlineLanguageLabelFiles.'][$key . '.'];
848 if (isset($languageFileConfig['if.']) && !$tsfe->cObj->checkIf($languageFileConfig['if.'])) {
849 continue;
850 }
851 $pageRenderer->addInlineLanguageLabelFile(
852 $languageFile,
853 $languageFileConfig['selectionPrefix'] ?: '',
854 $languageFileConfig['stripFromSelectionName'] ?: '',
855 $languageFileConfig['errorMode'] ? (int)$languageFileConfig['errorMode'] : 0
856 );
857 }
858 }
859 // ExtJS specific code
860 if (is_array($tsfe->pSetup['inlineLanguageLabel.'])) {
861 $pageRenderer->addInlineLanguageLabelArray($tsfe->pSetup['inlineLanguageLabel.'], true);
862 }
863 if (is_array($tsfe->pSetup['inlineSettings.'])) {
864 $pageRenderer->addInlineSettingArray('TS', $tsfe->pSetup['inlineSettings.']);
865 }
866 if (is_array($tsfe->pSetup['extOnReady.'])) {
867 $pageRenderer->addExtOnReadyCode($tsfe->cObj->cObjGet($tsfe->pSetup['extOnReady.'], 'extOnReady.'));
868 }
869 // Compression and concatenate settings
870 if ($tsfe->config['config']['compressCss']) {
871 $pageRenderer->enableCompressCss();
872 }
873 if ($tsfe->config['config']['compressJs']) {
874 $pageRenderer->enableCompressJavascript();
875 }
876 if ($tsfe->config['config']['concatenateCss']) {
877 $pageRenderer->enableConcatenateCss();
878 }
879 if ($tsfe->config['config']['concatenateJs']) {
880 $pageRenderer->enableConcatenateJavascript();
881 }
882 // Backward compatibility for old configuration
883 if ($tsfe->config['config']['concatenateJsAndCss']) {
884 $pageRenderer->enableConcatenateFiles();
885 }
886 // Add header data block
887 if ($tsfe->additionalHeaderData) {
888 $pageRenderer->addHeaderData(implode(LF, $tsfe->additionalHeaderData));
889 }
890 // Add footer data block
891 if ($tsfe->additionalFooterData) {
892 $pageRenderer->addFooterData(implode(LF, $tsfe->additionalFooterData));
893 }
894 // Header complete, now add content
895 if ($tsfe->pSetup['frameSet.']) {
896 $fs = GeneralUtility::makeInstance(FramesetRenderer::class);
897 $pageRenderer->addBodyContent($fs->make($tsfe->pSetup['frameSet.']));
898 $pageRenderer->addBodyContent(LF . '<noframes>' . LF);
899 }
900 // Bodytag:
901 if ($tsfe->config['config']['disableBodyTag']) {
902 $bodyTag = '';
903 } else {
904 $defBT = $tsfe->pSetup['bodyTagCObject'] ? $tsfe->cObj->cObjGetSingle($tsfe->pSetup['bodyTagCObject'], $tsfe->pSetup['bodyTagCObject.'], 'bodyTagCObject') : '';
905 if (!$defBT) {
906 $defBT = $tsfe->defaultBodyTag;
907 }
908 $bodyTag = $tsfe->pSetup['bodyTag'] ? $tsfe->pSetup['bodyTag'] : $defBT;
909 if (isset($tsfe->pSetup['bodyTagMargins'])) {
910 $margins = (int)$tsfe->pSetup['bodyTagMargins'];
911 if ($tsfe->pSetup['bodyTagMargins.']['useCSS']) {
912 } else {
913 $bodyTag = preg_replace('/>$/', '', trim($bodyTag)) . ' leftmargin="' . $margins . '" topmargin="' . $margins . '" marginwidth="' . $margins . '" marginheight="' . $margins . '">';
914 }
915 }
916 if (trim($tsfe->pSetup['bodyTagAdd'])) {
917 $bodyTag = preg_replace('/>$/', '', trim($bodyTag)) . ' ' . trim($tsfe->pSetup['bodyTagAdd']) . '>';
918 }
919 }
920 $pageRenderer->addBodyContent(LF . $bodyTag);
921 // Div-sections
922 if ($tsfe->divSection) {
923 $pageRenderer->addBodyContent(LF . $tsfe->divSection);
924 }
925 // Page content
926 $pageRenderer->addBodyContent(LF . $pageContent);
927 if (!empty($tsfe->config['INTincScript']) && is_array($tsfe->config['INTincScript'])) {
928 // Store the serialized pageRenderer in configuration
929 $tsfe->config['INTincScript_ext']['pageRenderer'] = serialize($pageRenderer);
930 // Render complete page, keep placeholders for JavaScript and CSS
931 $tsfe->content = $pageRenderer->renderPageWithUncachedObjects($tsfe->config['INTincScript_ext']['divKey']);
932 } else {
933 // Render complete page
934 $tsfe->content = $pageRenderer->render();
935 }
936 // Ending page
937 if ($tsfe->pSetup['frameSet.']) {
938 $tsfe->content .= LF . '</noframes>';
939 }
940 }
941
942 /*************************
943 *
944 * Helper functions
945 * Remember: Calls internally must still be done on the non-instantiated class: PageGenerator::inline2TempFile()
946 *
947 *************************/
948 /**
949 * Searches for placeholder created from *_INT cObjects, removes them from
950 * $searchString and merges them to $intObjects
951 *
952 * @param string $searchString The String which should be cleaned from int-object markers
953 * @param string $intObjects The String the found int-placeholders are moved to (for further processing)
954 */
955 protected static function stripIntObjectPlaceholder(&$searchString, &$intObjects)
956 {
957 $tempArray = array();
958 preg_match_all('/\\<\\!--INT_SCRIPT.[a-z0-9]*--\\>/', $searchString, $tempArray);
959 $searchString = preg_replace('/\\<\\!--INT_SCRIPT.[a-z0-9]*--\\>/', '', $searchString);
960 $intObjects = implode('', $tempArray[0]);
961 }
962
963 /**
964 * Writes string to a temporary file named after the md5-hash of the string
965 *
966 * @param string $str CSS styles / JavaScript to write to file.
967 * @param string $ext Extension: "css" or "js
968 * @return string <script> or <link> tag for the file.
969 */
970 public static function inline2TempFile($str, $ext)
971 {
972 // Create filename / tags:
973 $script = '';
974 switch ($ext) {
975 case 'js':
976 $script = 'typo3temp/assets/js/' . GeneralUtility::shortMD5($str) . '.js';
977 break;
978 case 'css':
979 $script = 'typo3temp/assets/css/' . GeneralUtility::shortMD5($str) . '.css';
980 break;
981 }
982 // Write file:
983 if ($script) {
984 if (!@is_file(PATH_site . $script)) {
985 GeneralUtility::writeFileToTypo3tempDir(PATH_site . $script, $str);
986 }
987 }
988 return $script;
989 }
990
991 /**
992 * Checks if the value defined in "config.linkVars" contains an allowed value. Otherwise, return FALSE which means the value will not be added to any links.
993 *
994 * @param string $haystack The string in which to find $needle
995 * @param string $needle The string to find in $haystack
996 * @return bool Returns TRUE if $needle matches or is found in $haystack
997 */
998 public static function isAllowedLinkVarValue($haystack, $needle)
999 {
1000 $OK = false;
1001 // Integer
1002 if ($needle == 'int' || $needle == 'integer') {
1003 if (MathUtility::canBeInterpretedAsInteger($haystack)) {
1004 $OK = true;
1005 }
1006 } elseif (preg_match('/^\\/.+\\/[imsxeADSUXu]*$/', $needle)) {
1007 // Regular expression, only "//" is allowed as delimiter
1008 if (@preg_match($needle, $haystack)) {
1009 $OK = true;
1010 }
1011 } elseif (strstr($needle, '-')) {
1012 // Range
1013 if (MathUtility::canBeInterpretedAsInteger($haystack)) {
1014 $range = explode('-', $needle);
1015 if ($range[0] <= $haystack && $range[1] >= $haystack) {
1016 $OK = true;
1017 }
1018 }
1019 } elseif (strstr($needle, '|')) {
1020 // List
1021 // Trim the input
1022 $haystack = str_replace(' ', '', $haystack);
1023 if (strstr('|' . $needle . '|', '|' . $haystack . '|')) {
1024 $OK = true;
1025 }
1026 } elseif ((string)$needle === (string)$haystack) {
1027 // String comparison
1028 $OK = true;
1029 }
1030 return $OK;
1031 }
1032
1033 /**
1034 * Generate title for page.
1035 * Takes the settings [config][noPageTitle], [config][pageTitleFirst], [config][titleTagFunction]
1036 * [config][pageTitleSeparator] and [config][noPageTitle] into account.
1037 * Furthermore $GLOBALS[TSFE]->altPageTitle is observed.
1038 *
1039 * @return void
1040 */
1041 public static function generatePageTitle()
1042 {
1043 /** @var TypoScriptFrontendController $tsfe */
1044 $tsfe = $GLOBALS['TSFE'];
1045
1046 $pageTitleSeparator = '';
1047
1048 // check for a custom pageTitleSeparator, and perform stdWrap on it
1049 if (isset($tsfe->config['config']['pageTitleSeparator']) && $tsfe->config['config']['pageTitleSeparator'] !== '') {
1050 $pageTitleSeparator = $tsfe->config['config']['pageTitleSeparator'];
1051
1052 if (isset($tsfe->config['config']['pageTitleSeparator.']) && is_array($tsfe->config['config']['pageTitleSeparator.'])) {
1053 $pageTitleSeparator = $tsfe->cObj->stdWrap($pageTitleSeparator, $tsfe->config['config']['pageTitleSeparator.']);
1054 } else {
1055 $pageTitleSeparator .= ' ';
1056 }
1057 }
1058
1059 $titleTagContent = $tsfe->tmpl->printTitle(
1060 $tsfe->altPageTitle ?: $tsfe->page['title'],
1061 $tsfe->config['config']['noPageTitle'],
1062 $tsfe->config['config']['pageTitleFirst'],
1063 $pageTitleSeparator
1064 );
1065 if ($tsfe->config['config']['titleTagFunction']) {
1066 $titleTagContent = $tsfe->cObj->callUserFunction(
1067 $tsfe->config['config']['titleTagFunction'],
1068 array(),
1069 $titleTagContent
1070 );
1071 }
1072 // stdWrap around the title tag
1073 if (isset($tsfe->config['config']['pageTitle.']) && is_array($tsfe->config['config']['pageTitle.'])) {
1074 $titleTagContent = $tsfe->cObj->stdWrap($titleTagContent, $tsfe->config['config']['pageTitle.']);
1075 }
1076 if ($titleTagContent !== '' && (int)$tsfe->config['config']['noPageTitle'] !== self::NO_PAGE_TITLE) {
1077 static::getPageRenderer()->setTitle($titleTagContent);
1078 }
1079 }
1080
1081 /**
1082 * Generate meta tags from meta tag TypoScript
1083 *
1084 * @param array $metaTagTypoScript TypoScript configuration for meta tags (e.g. $GLOBALS['TSFE']->pSetup['meta.'])
1085 * @param bool $xhtml Whether xhtml tag-style should be used. (e.g. pass $GLOBALS['TSFE']->xhtmlVersion here)
1086 * @param ContentObjectRenderer $cObj
1087 * @return array Array of HTML meta tags
1088 */
1089 protected static function generateMetaTagHtml(array $metaTagTypoScript, $xhtml, ContentObjectRenderer $cObj)
1090 {
1091 // Add ending slash only to documents rendered as xhtml
1092 $endingSlash = $xhtml ? ' /' : '';
1093
1094 $metaTags = array(
1095 '<meta name="generator" content="TYPO3 CMS"' . $endingSlash . '>'
1096 );
1097
1098 /** @var TypoScriptService $typoScriptService */
1099 $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
1100 $conf = $typoScriptService->convertTypoScriptArrayToPlainArray($metaTagTypoScript);
1101 foreach ($conf as $key => $properties) {
1102 if (is_array($properties)) {
1103 $nodeValue = isset($properties['_typoScriptNodeValue']) ? $properties['_typoScriptNodeValue'] : '';
1104 $value = trim($cObj->stdWrap($nodeValue, $metaTagTypoScript[$key . '.']));
1105 if ($value === '' && !empty($properties['value'])) {
1106 $value = $properties['value'];
1107 }
1108 } else {
1109 $value = $properties;
1110 }
1111
1112 $attribute = 'name';
1113 if ((is_array($properties) && !empty($properties['httpEquivalent'])) || strtolower($key) === 'refresh') {
1114 $attribute = 'http-equiv';
1115 }
1116 if (is_array($properties) && !empty($properties['attribute'])) {
1117 $attribute = $properties['attribute'];
1118 }
1119
1120 if (!is_array($value)) {
1121 $value = (array)$value;
1122 }
1123 foreach ($value as $subValue) {
1124 if (trim($subValue) !== '') {
1125 $metaTags[] = '<meta ' . $attribute . '="' . $key . '" content="' . htmlspecialchars($subValue) . '"' . $endingSlash . '>';
1126 }
1127 }
1128 }
1129 return $metaTags;
1130 }
1131
1132 /**
1133 * Fills the sWordList property and builds the regular expression in TSFE that can be used to split
1134 * strings by the submitted search words.
1135 *
1136 * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::sWordList
1137 * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::sWordRegEx
1138 */
1139 protected static function initializeSearchWordDataInTsfe()
1140 {
1141 /** @var TypoScriptFrontendController $tsfe */
1142 $tsfe = $GLOBALS['TSFE'];
1143
1144 $tsfe->sWordRegEx = '';
1145 $tsfe->sWordList = GeneralUtility::_GP('sword_list');
1146 if (is_array($tsfe->sWordList)) {
1147 $space = !empty($tsfe->config['config']['sword_standAlone']) ? '[[:space:]]' : '';
1148 foreach ($tsfe->sWordList as $val) {
1149 if (trim($val) !== '') {
1150 $tsfe->sWordRegEx .= $space . preg_quote($val, '/') . $space . '|';
1151 }
1152 }
1153 $tsfe->sWordRegEx = rtrim($tsfe->sWordRegEx, '|');
1154 }
1155 }
1156
1157 /**
1158 * @return PageRenderer
1159 */
1160 protected static function getPageRenderer()
1161 {
1162 return GeneralUtility::makeInstance(PageRenderer::class);
1163 }
1164
1165 /**
1166 * Adds inline CSS code, by respecting the inlineStyle2TempFile option
1167 *
1168 * @param string $cssStyles the inline CSS styling
1169 * @param bool $excludeFromConcatenation option to see if it should be conctatenated
1170 * @param string $inlineBlockName the block name to add it
1171 */
1172 protected static function addCssToPageRenderer($cssStyles, $excludeFromConcatenation = false, $inlineBlockName = 'TSFEinlineStyle')
1173 {
1174 if (empty($GLOBALS['TSFE']->config['config']['inlineStyle2TempFile'])) {
1175 self::getPageRenderer()->addCssInlineBlock($inlineBlockName, $cssStyles, !empty($GLOBALS['TSFE']->config['config']['compressCss']));
1176 } else {
1177 self::getPageRenderer()->addCssFile(
1178 self::inline2TempFile($cssStyles, 'css'),
1179 'stylesheet',
1180 'all',
1181 '',
1182 (bool)$GLOBALS['TSFE']->config['config']['compressCss'],
1183 false,
1184 '',
1185 $excludeFromConcatenation
1186 );
1187 }
1188 }
1189 }