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