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