Cleanup: Set SVN properties
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_pagerenderer.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009 Steffen Kamper (info@sk-typo3.de)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * TYPO3 pageRender class (new in TYPO3 4.3.0)
30 * This class render the HTML of a webpage, usable for BE and FE
31 *
32 * @author Steffen Kamper <info@sk-typo3.de>
33 * @package TYPO3
34 * @subpackage t3lib
35 * $Id$
36 */
37 abstract class t3lib_PageRenderer implements t3lib_Singleton {
38
39 protected $compressJavascript = FALSE;
40 protected $compressCss = FALSE;
41 protected $removeLineBreaksFromTemplate = FALSE;
42
43 protected $concatenateFiles = FALSE;
44
45 protected $moveJsFromHeaderToFooter = FALSE;
46
47 protected $csConvObj;
48 protected $lang;
49
50 // static array containing associative array for the included files
51 protected static $jsFiles = array ();
52 protected static $jsFooterFiles = array ();
53 protected static $jsLibs = array ();
54 protected static $jsFooterLibs = array ();
55 protected static $cssFiles = array ();
56
57 protected $title;
58 protected $charSet;
59 protected $favIcon;
60 protected $baseUrl;
61
62 // static header blocks
63 protected $xmlPrologAndDocType = '';
64 protected $metaTags = array ();
65 protected $inlineComments = array ();
66 protected $headerData = array ();
67 protected $footerData = array ();
68 protected $titleTag = '<title>|</title>';
69 protected $metaCharsetTag = '<meta http-equiv="Content-Type" content="text/html; charset=|" />';
70 protected $htmlTag = '<html>';
71 protected $headTag = '<head>';
72 protected $baseUrlTag = '<base href="|" />';
73 protected $iconMimeType = '';
74 protected $shortcutTag = '<link rel="shortcut icon" href="%1$s"%2$s />
75 <link rel="icon" href="%1$s"%2$s />';
76
77 // static inline code blocks
78 protected $jsInline = array ();
79 protected $extOnReadyCode = array ();
80 protected $cssInline = array ();
81
82 protected $bodyContent;
83
84 protected $templateFile;
85
86 protected $jsLibraryNames = array ('prototype', 'scriptaculous', 'extjs');
87
88 const PART_COMPLETE = 0;
89 const PART_HEADER = 1;
90 const PART_FOOTER = 2;
91
92 // internal flags for JS-libraries
93 protected $addPrototype = FALSE;
94 protected $addScriptaculous = FALSE;
95 protected $addScriptaculousModules = array ('builder' => FALSE, 'effects' => FALSE, 'dragdrop' => FALSE, 'controls' => FALSE, 'slider' => FALSE);
96 protected $addExtJS = FALSE;
97 protected $addExtCore = FALSE;
98 protected $extJSadapter = 'ext/ext-base.js';
99
100 protected $enableExtJsDebug = FALSE;
101 protected $enableExtCoreDebug = FALSE;
102
103 // available adapters for extJs
104 const EXTJS_ADAPTER_JQUERY = 'jquery';
105 const EXTJS_ADAPTER_PROTOTYPE = 'prototype';
106 const EXTJS_ADAPTER_YUI = 'yui';
107
108 protected $enableExtJSQuickTips = false;
109
110 protected $inlineLanguageLabels = array ();
111 protected $inlineSettings = array ();
112
113 protected $inlineJavascriptWrap = array ();
114
115 // used by BE modules
116 public $backPath;
117
118 /**
119 * Constructor
120 *
121 * @param string $templateFile declare the used template file. Omit this parameter will use default template
122 * @param string $backPath relative path to typo3-folder. It varies for BE modules, in FE it will be typo3/
123 * @return void
124 */
125 public function __construct($templateFile = '', $backPath = '') {
126
127 $this->reset();
128
129 if (strlen($templateFile)) {
130 $this->templateFile = $templateFile;
131 }
132 $this->backPath = $backPath;
133
134 $this->inlineJavascriptWrap = array(
135 '<script type="text/javascript">' . chr(10) . '/*<![CDATA[*/' . chr(10) . '<!-- ' . chr(10),
136 '// -->' . chr(10) . '/*]]>*/' . chr(10) . '</script>' . chr(10)
137 );
138 $this->inlineCssWrap = array(
139 '<style type="text/css">' . chr(10) . '/*<![CDATA[*/' . chr(10) . '<!-- ' . chr(10),
140 '-->' . chr(10) . '/*]]>*/' . chr(10) . '</style>' . chr(10)
141 );
142
143 }
144
145 /**
146 * reset all vars to initial values
147 *
148 * @return void
149 */
150 protected function reset() {
151 $this->templateFile = TYPO3_mainDir . 'templates/template_page_backend.html';
152 $this->jsFiles = array ();
153 $this->jsFooterFiles = array ();
154 $this->jsInline = array ();
155 $this->jsFooterInline = array ();
156 $this->jsLibs = array ();
157 $this->cssFiles = array ();
158 $this->cssInline = array ();
159 $this->metaTags = array ();
160 $this->inlineComments = array ();
161 $this->headerData = array ();
162 $this->footerData = array ();
163 $this->extOnReadyCode = array ();
164 }
165 /*****************************************************/
166 /* */
167 /* Public Setters */
168 /* */
169 /* */
170 /*****************************************************/
171
172 /**
173 * Sets the title
174 *
175 * @param string $title title of webpage
176 * @return void
177 */
178 public function setTitle($title) {
179 $this->title = $title;
180 }
181
182 /**
183 * Sets xml prolog and docType
184 *
185 * @param string $xmlPrologAndDocType complete tags for xml prolog and docType
186 * @return void
187 */
188 public function setXmlPrologAndDocType($xmlPrologAndDocType) {
189 $this->xmlPrologAndDocType = $xmlPrologAndDocType;
190 }
191
192 /**
193 * Sets meta charset
194 * @return void
195 *
196 * @param string $charSet used charset
197 */
198 public function setCharSet($charSet) {
199 $this->charSet = $charSet;
200 }
201
202 /**
203 * Sets html tag
204 *
205 * @param string $htmlTag html tag
206 * @return void
207 */
208 public function setHtmlTag($htmlTag) {
209 $this->htmlTag = $htmlTag;
210 }
211
212 /**
213 * Sets head tag
214 *
215 * @param string $tag head tag
216 * @return void
217 */
218 public function setHeadTag($headTag) {
219 $this->headTag = $headTag;
220 }
221
222 /**
223 * Sets favicon
224 *
225 * @param string $favIcon
226 * @return void
227 */
228 public function setFavIcon($favIcon) {
229 $this->favIcon = $favIcon;
230 }
231
232 /**
233 * Sets icon mime type
234 *
235 * @param string $iconMimeType
236 * @return void
237 */
238 public function setIconMimeType($iconMimeType) {
239 $this->iconMimeType = $iconMimeType;
240 }
241
242 /**
243 * Sets base url
244 *
245 * @param string $url
246 * @return void
247 */
248 public function setBaseUrl($baseUrl) {
249 $this->baseUrl = $baseUrl;
250 }
251
252 /**
253 * Sets template file
254 *
255 * @param string $file
256 * @return void
257 */
258 public function setTemplateFile($file) {
259 $this->templateFile = $file;
260 }
261
262 /**
263 * Sets Content for Body
264 *
265 * @param string $content
266 * @return void
267 */
268 public function setBodyContent($content) {
269 $this->bodyContent = $content;
270 }
271
272 /*****************************************************/
273 /* */
274 /* Public Enablers */
275 /* */
276 /* */
277 /*****************************************************/
278 /**
279 * Enables MoveJsFromHeaderToFooter
280 *
281 * @param void
282 * @return void
283 */
284 public function enableMoveJsFromHeaderToFooter() {
285 $this->moveJsFromHeaderToFooter = TRUE;
286 }
287
288 /**
289 * Enables compression of javascript
290 *
291 * @param void
292 * @return void
293 */
294 public function enableCompressJavascript() {
295 $this->compressJavascript = TRUE;
296 }
297
298 /**
299 * Enables compression of css
300 *
301 * @param void
302 * @return void
303 */
304 public function enableCompressCss() {
305 $this->compressCss = TRUE;
306 }
307
308 /**
309 /**
310 * Enables concatenation of js/css files
311 *
312 * @param void
313 * @return void
314 */
315 public function enableConcatenateFiles() {
316 $this->concatenateFiles = TRUE;
317 }
318
319 /**
320 * Sets removal of all line breaks in template
321 *
322 * @param void
323 * @return void
324 */
325 public function enableRemoveLineBreaksFromTemplate() {
326 $this->removeLineBreaksFromTemplate = TRUE;
327 }
328
329 /*****************************************************/
330 /* */
331 /* Public Getters */
332 /* */
333 /* */
334 /*****************************************************/
335
336 /**
337 * Gets the title
338 *
339 * @return string $title title of webpage
340 */
341 public function getTitle() {
342 return $this->title;
343 }
344
345 /**
346 * Gets the charSet
347 *
348 * @return string $charSet
349 */
350 public function getCharSet() {
351 return $this->charSet;
352 }
353
354 /**
355 * Gets html tag
356 *
357 * @return string $htmlTag html tag
358 */
359 public function getHtmlTag() {
360 return $this->htmlTag;
361 }
362
363 /**
364 * Gets head tag
365 *
366 * @return string $tag head tag
367 */
368 public function getHeadTag() {
369 return $this->headTag;
370 }
371
372 /**
373 * Gets favicon
374 *
375 * @return string $favIcon
376 */
377 public function getFavIcon() {
378 return $this->favIcon;
379 }
380
381 /**
382 * Gets icon mime type
383 *
384 * @return string $iconMimeType
385 */
386 public function getIconMimeType() {
387 return $this->iconMimeType;
388 }
389
390 /**
391 * Gets base url
392 *
393 * @return string $url
394 */
395 public function getBaseUrl() {
396 return $this->baseUrl;
397 }
398
399 /**
400 * Gets template file
401 *
402 * @return string $file
403 */
404 public function getTemplateFile($file) {
405 return $this->templateFile;
406 }
407
408 /**
409 * Gets MoveJsFromHeaderToFooter
410 *
411 * @return boolean
412 */
413 public function getMoveJsFromHeaderToFooter() {
414 return $this->moveJsFromHeaderToFooter;
415 }
416
417 /**
418 * Gets compress of javascript
419 *
420 * @return boolean
421 */
422 public function getCompressJavascript() {
423 return $this->compressJavascript;
424 }
425
426 /**
427 * Gets compress of css
428 *
429 * @return boolean
430 */
431 public function getCompressCss() {
432 return $this->compressCss;
433 }
434
435 /**
436 * Gets concatenate of files
437 *
438 * @return boolean
439 */
440 public function getConcatenateFiles() {
441 return $this->concatenateFiles;
442 }
443
444 /**
445 * Gets remove of empty lines from template
446 *
447 * @return boolean
448 */
449 public function getRemoveLineBreaksFromTemplate() {
450 return $this->removeLineBreaksFromTemplate;
451 }
452
453 /**
454 * Gets content for body
455 *
456 * @return string
457 */
458 public function getBodyContent() {
459 return $this->bodyContent;
460 }
461
462 /*****************************************************/
463 /* */
464 /* Public Function to add Data */
465 /* */
466 /* */
467 /*****************************************************/
468
469 /**
470 * Adds meta data
471 *
472 * @param string $meta meta data (complete metatag)
473 * @return void
474 */
475 public function addMetaTag($meta) {
476 if (!in_array($meta, $this->metaTags)) {
477 $this->metaTags[] = $meta;
478 }
479 }
480
481 /**
482 * Adds inline HTML comment
483 *
484 * @param string $comment
485 * @return void
486 */
487 public function addInlineComment($comment) {
488 if (!in_array($comment, $this->inlineComments)) {
489 $this->inlineComments[] = $comment;
490 }
491 }
492
493 /**
494 * Adds header data
495 *
496 * @param string $data free header data for HTML header
497 * @return void
498 */
499 public function addHeaderData($data) {
500 if (!in_array($data, $this->headerData)) {
501 $this->headerData[] = $data;
502 }
503 }
504
505 /**
506 * Adds footer data
507 *
508 * @param string $data free header data for HTML header
509 * @return void
510 */
511 public function addFooterData($data) {
512 if (!in_array($data, $this->footerData)) {
513 $this->footerData[] = $data;
514 }
515 }
516
517 /* Javascript Files */
518
519 /**
520 * Adds JS Library. JS Library block is rendered on top of the JS files.
521 *
522 * @param string $name
523 * @param string $file
524 * @param string $type
525 * @param boolean $compressed flag if library is compressed
526 * @param boolean $forceOnTop flag if added library should be inserted at begin of this block
527 * @param string $allWrap
528 * @return void
529 */
530 public function addJsLibrary($name, $file, $type = 'text/javascript', $compressed = TRUE, $forceOnTop = FALSE, $allWrap = '') {
531 if (!in_array(strtolower($name), $this->jsLibs)) {
532 $this->jsLibs[strtolower($name)] = array (
533 'file' => $file,
534 'type' => $type,
535 'section' => self::PART_HEADER,
536 'compressed' => $compressed,
537 'forceOnTop' => $forceOnTop,
538 'allWrap' => $allWrap
539 );
540 }
541
542 }
543
544 /**
545 * Adds JS Library to Footer. JS Library block is rendered on top of the Footer JS files.
546 *
547 * @param string $name
548 * @param string $file
549 * @param string $type
550 * @param boolean $compressed flag if library is compressed
551 * @param boolean $forceOnTop flag if added library should be inserted at begin of this block
552 * @param string $allWrap
553 * @return void
554 */
555 public function addJsFooterLibrary($name, $file, $type = 'text/javascript', $compressed = TRUE, $forceOnTop = FALSE, $allWrap = '') {
556 if (!in_array(strtolower($name), $this->jsLibs)) {
557 $this->jsLibs[strtolower($name)] = array (
558 'file' => $file,
559 'type' => $type,
560 'section' => self::PART_FOOTER,
561 'compressed' => $compressed,
562 'forceOnTop' => $forceOnTop,
563 'allWrap' => $allWrap
564 );
565 }
566
567 }
568
569 /**
570 * Adds JS file
571 *
572 * @param string $file
573 * @param string $type
574 * @param boolean $compressed
575 * @param boolean $forceOnTop
576 * @param string $allWrap
577 * @return void
578 */
579 public function addJsFile($file, $type = 'text/javascript', $compressed = FALSE, $forceOnTop = FALSE, $allWrap = '') {
580 if (!isset($this->jsFiles[$file])) {
581 $this->jsFiles[$file] = array (
582 'type' => $type,
583 'section' => self::PART_HEADER,
584 'compressed' => $compressed,
585 'forceOnTop' => $forceOnTop,
586 'allWrap' => $allWrap
587 );
588 }
589 }
590
591 /**
592 * Adds JS file to footer
593 *
594 * @param string $file
595 * @param string $type
596 * @param boolean $compressed
597 * @param boolean $forceOnTop
598 * @return void
599 */
600 public function addJsFooterFile($file, $type = 'text/javascript', $compressed = FALSE, $forceOnTop = FALSE, $allWrap = '') {
601 if (!isset($this->jsFiles[$file])) {
602 $this->jsFiles[$file] = array (
603 'type' => $type,
604 'section' => self::PART_FOOTER,
605 'compressed' => $compressed,
606 'forceOnTop' => $forceOnTop,
607 'allWrap' => $allWrap
608 );
609 }
610 }
611
612 /*Javascript Inline Blocks */
613
614 /**
615 * Adds JS inline code
616 *
617 * @param string $name
618 * @param string $block
619 * @param boolean $compressed
620 * @param boolean $forceOnTop
621 * @return void
622 */
623 public function addJsInlineCode($name, $block, $compressed = FALSE, $forceOnTop = FALSE) {
624 if (!isset($this->jsInline[$name])) {
625 $this->jsInline[$name] = array (
626 'code' => $block . chr(10),
627 'section' => self::PART_HEADER,
628 'compressed' => $compressed,
629 'forceOnTop' => $forceOnTop
630 );
631 }
632 }
633
634 /**
635 * Adds JS inline code to footer
636 *
637 * @param string $name
638 * @param string $block
639 * @param boolean $compressed
640 * @param boolean $forceOnTop
641 * @return void
642 */
643 public function addJsFooterInlineCode($name, $block, $compressed = FALSE, $forceOnTop = FALSE) {
644 if (!isset($this->jsInline[$name])) {
645 $this->jsInline[$name] = array (
646 'code' => $block . chr(10),
647 'section' => self::PART_FOOTER,
648 'compressed' => $compressed,
649 'forceOnTop' => $forceOnTop
650 );
651 }
652 }
653
654 /**
655 * Adds Ext.onready code, which will be wrapped in Ext.onReady(function() {...});
656 *
657 * @param string $block
658 * @return void
659 */
660 public function addExtOnReadyCode($block) {
661 if (!in_array($block, $this->extOnReadyCode)) {
662 $this->extOnReadyCode[] = $block;
663 }
664 }
665
666 /* CSS Files */
667
668 /**
669 * Adds CSS file
670 *
671 * @param string $file
672 * @param string $rel
673 * @param string $media
674 * @param string $title
675 * @param boolean $compressed
676 * @param boolean $forceOnTop
677 * @return void
678 */
679 public function addCssFile($file, $rel = 'stylesheet', $media = 'screen', $title = '', $compressed = FALSE, $forceOnTop = FALSE, $allWrap = '') {
680 if (!isset($this->cssFiles[$file])) {
681 $this->cssFiles[$file] = array ('rel' => $rel, 'media' => $media, 'title' => $title, 'compressed' => $compressed, 'forceOnTop' => $forceOnTop, 'allWrap' => $allWrap);
682 }
683 }
684
685 /*CSS Inline Blocks */
686
687 /**
688 * Adds CSS inline code
689 *
690 * @param string $name
691 * @param string $block
692 * @param boolean $compressed
693 * @param boolean $forceOnTop
694 * @return void
695 */
696 public function addCssInlineBlock($name, $block, $compressed = FALSE, $forceOnTop = FALSE) {
697 if (!isset($this->cssInline[$name])) {
698 $this->cssInline[$name] = array ('code' => $block, 'compressed' => $compressed, 'forceOnTop' => $forceOnTop);
699 }
700 }
701
702 /* JS Libraries */
703
704 /**
705 * call function if you need the prototype library
706 *
707 * @return void
708 */
709 public function loadPrototype() {
710 $this->addPrototype = TRUE;
711 }
712
713 /**
714 * call function if you need the Scriptaculous library
715 *
716 * @param string $modules add modules you need. use "all" if you need complete modules
717 * @return void
718 */
719 public function loadScriptaculous($modules = '') {
720 // Scriptaculous require prototype, so load prototype too.
721 $this->addPrototype = TRUE;
722 $this->addScriptaculous = TRUE;
723 if ($modules) {
724 if ($modules == 'all') {
725 foreach ($this->addScriptaculousModules as $key => $value) {
726 $this->addScriptaculousModules[$key] = TRUE;
727 }
728 } else {
729 $mods = t3lib_div::trimExplode(',', $modules);
730 foreach ($mods as $mod) {
731 if (isset($this->addScriptaculousModules[strtolower($mod)])) {
732 $this->addScriptaculousModules[strtolower($mod)] = TRUE;
733 }
734 }
735 }
736 }
737 }
738
739 /**
740 * call this function if you need the extJS library
741 *
742 * @param boolean $css flag, if set the ext-css will be loaded
743 * @param boolean $theme flag, if set the ext-theme "grey" will be loaded
744 * @param string $adapter choose alternative adapter, possible values: yui, prototype, jquery
745 * @return void
746 */
747 public function loadExtJS($css = TRUE, $theme = TRUE, $adapter = '') {
748 if ($adapter) {
749 // empty $adapter will always load the ext adapter
750 switch (t3lib_div::strtolower(trim($adapter))) {
751 case self::EXTJS_ADAPTER_YUI :
752 $this->extJSadapter = 'yui/ext-yui-adapter.js';
753 break;
754 case self::EXTJS_ADAPTER_PROTOTYPE :
755 $this->extJSadapter = 'prototype/ext-prototype-adapter.js';
756 break;
757 case self::EXTJS_ADAPTER_JQUERY :
758 $this->extJSadapter = 'jquery/ext-jquery-adapter.js';
759 break;
760 }
761 }
762 if (!$this->addExtJS) {
763 $this->addExtJS = TRUE;
764 if ($theme) {
765 if (isset($GLOBALS['TBE_STYLES']['extJS']['theme'])) {
766 $this->addCssFile($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['theme'], 'stylesheet', 'screen', '', FALSE, TRUE);
767 } else {
768 $this->addCssFile($this->backPath . 'contrib/extjs/resources/css/xtheme-blue.css', 'stylesheet', 'screen', '', FALSE, TRUE);
769 }
770 }
771 if ($css) {
772 if (isset($GLOBALS['TBE_STYLES']['extJS']['all'])) {
773 $this->addCssFile($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['all'], 'stylesheet', 'screen', '', FALSE, TRUE);
774 } else {
775 $this->addCssFile($this->backPath . 'contrib/extjs/resources/css/ext-all-notheme.css', 'stylesheet', 'screen', '', FALSE, TRUE);
776 }
777 }
778
779 }
780 }
781
782 /**
783 * Enables ExtJs QuickTips
784 * Need extJs loaded
785 *
786 * @return void
787 *
788 */
789 public function enableExtJSQuickTips() {
790 $this->enableExtJSQuickTips = TRUE;
791 }
792
793
794 /**
795 * call function if you need the ExtCore library
796 *
797 * @return void
798 */
799 public function loadExtCore() {
800 $this->addExtCore = TRUE;
801 }
802
803 /**
804 * call this function to load debug version of ExtJS. Use this for development only
805 *
806 */
807 public function enableExtJsDebug() {
808 $this->enableExtJsDebug = TRUE;
809 }
810
811 /**
812 * call this function to load debug version of ExtCore. Use this for development only
813 *
814 * @return void
815 */
816 public function enableExtCoreDebug() {
817 $this->enableExtCoreDebug = TRUE;
818 }
819
820 /**
821 * Adds Javascript Inline Label. This will occur in TYPO3.lang - object
822 * The label can be used in scripts with TYPO3.lang.<key>
823 * Need extJs loaded
824 *
825 * @param string $key
826 * @param string $value
827 * @return void
828 */
829 public function addInlineLanguageLabel($key, $value) {
830 $this->inlineLanguageLabels[$key] = $value;
831 }
832
833 /**
834 * Adds Javascript Inline Label Array. This will occur in TYPO3.lang - object
835 * The label can be used in scripts with TYPO3.lang.<key>
836 * Array will be merged with existing array.
837 * Need extJs loaded
838 *
839 * @param array $array
840 * @return void
841 */
842 public function addInlineLanguageLabelArray(array $array) {
843 $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $array);
844 }
845
846 /**
847 * Adds Javascript Inline Setting. This will occur in TYPO3.settings - object
848 * The label can be used in scripts with TYPO3.setting.<key>
849 * Need extJs loaded
850 *
851 * @param string $namespace
852 * @param string $key
853 * @param string $value
854 * @return void
855 */
856 public function addInlineSetting($namespace, $key, $value) {
857 if ($namespace) {
858 if (strpos($namespace, '.')) {
859 $parts = explode('.', $namespace);
860 $a = &$this->inlineSettings;
861 foreach ($parts as $part) {
862 $a = &$a[$part];
863 }
864 $a[$key] = $value;
865 } else {
866 $this->inlineSettings[$namespace][$key] = $value;
867 }
868 } else {
869 $this->inlineSettings[$key] = $value;
870 }
871 }
872
873 /**
874 * Adds Javascript Inline Setting. This will occur in TYPO3.settings - object
875 * The label can be used in scripts with TYPO3.setting.<key>
876 * Array will be merged with existing array.
877 * Need extJs loaded
878 *
879 * @param string $namespace
880 * @param array $array
881 * @return void
882 */
883 public function addInlineSettingArray($namespace, array $array) {
884 if ($namespace) {
885 if (strpos($namespace, '.')) {
886 $parts = explode('.', $namespace);
887 $a = &$this->inlineSettings;
888 foreach ($parts as $part) {
889 $a = &$a[$part];
890 }
891 $a = array_merge((array) $a, $array);
892 } else {
893 $this->inlineSettings[$namespace] = array_merge((array) $this->inlineSettings[$namespace], $array);
894 }
895 } else {
896 $this->inlineSettings = array_merge($this->inlineSettings, $array);
897 }
898 }
899
900 /**
901 * Adds content to body content
902 *
903 * @param string $content
904 * @return void
905 */
906 public function addBodyContent($content) {
907 $this->bodyContent .= $content;
908 }
909
910 /*****************************************************/
911 /* */
912 /* Render Functions */
913 /* */
914 /* */
915 /*****************************************************/
916
917 /**
918 * render the section (Header or Footer)
919 *
920 * @param int $part section which should be rendered: self::PART_COMPLETE, self::PART_HEADER or self::PART_FOOTER
921 * @return string content of rendered section
922 */
923 public function render($part = self::PART_COMPLETE) {
924
925 $jsFiles = '';
926 $cssFiles = '';
927 $cssInline = '';
928 $jsInline = '';
929 $jsFooterInline = '';
930 $jsFooterLibs = '';
931 $jsFooterFiles = '';
932 $noJS = FALSE;
933
934 $jsLibs = $this->renderJsLibraries();
935
936 if ($this->compressCss || $this->compressJavascript) {
937 // do the file compression
938 $this->doCompress();
939 }
940 if ($this->concatenateFiles) {
941 // do the file concatenation
942 $this->doConcatenate();
943 }
944
945 $metaTags = implode(chr(10), $this->metaTags);
946
947 if (count($this->cssFiles)) {
948 foreach ($this->cssFiles as $file => $properties) {
949 $tag = '<link rel="' . $properties['rel'] . '" type="text/css" href="' . $file . '" media="' . $properties['media'] . '"' . ($properties['title'] ? ' title="' . $properties['title'] . '"' : '') . ' />';
950 if ($properties['allWrap'] && strpos($properties['allWrap'], '|') !== FALSE) {
951 $tag = str_replace('|', $tag, $properties['allWrap']);
952 }
953 if ($properties['forceOnTop']) {
954 $cssFiles = $tag . chr(10) . $cssFiles;
955 } else {
956 $cssFiles .= chr(10) . $tag;
957 }
958 }
959 }
960
961 if (count($this->cssInline)) {
962
963 foreach ($this->cssInline as $name => $properties) {
964 if ($properties['forceOnTop']) {
965 $cssInline = '/*' . htmlspecialchars($name) . '*/' . chr(10) . $properties['code'] . chr(10) . $cssInline;
966 } else {
967 $cssInline .= '/*' . htmlspecialchars($name) . '*/' . chr(10) . $properties['code'] . chr(10);
968 }
969 }
970 $cssInline = $this->inlineCssWrap[0] . $cssInline . $this->inlineCssWrap[1];
971
972 }
973
974 if (count($this->jsLibs)) {
975 foreach ($this->jsLibs as $name => $properties) {
976 $tag = '<script src="' . $properties['file'] . '" type="' . $properties['type'] . '"></script>';
977 if ($properties['allWrap'] && strpos($properties['allWrap'], '|') !== FALSE) {
978 $tag = str_replace('|', $tag, $properties['allWrap']);
979 }
980 if ($properties['forceOnTop']) {
981 if ($properties['section'] === self::PART_HEADER) {
982 $jsLibs = $tag . chr(10) . $jsLibs;
983 } else {
984 $jsFooterLibs = $tag . chr(10) . $jsFooterLibs;
985 }
986 } else {
987 if ($properties['section'] === self::PART_HEADER) {
988 $jsLibs .= chr(10) . $tag;
989 } else {
990 $jsFooterLibs .= chr(10) . $tag;
991 }
992 }
993
994 }
995 }
996
997 if (count($this->jsFiles)) {
998 foreach ($this->jsFiles as $file => $properties) {
999 $tag = '<script src="' . $file . '" type="' . $properties['type'] . '"></script>';
1000 if ($properties['allWrap'] && strpos($properties['allWrap'], '|') !== FALSE) {
1001 $tag = str_replace('|', $tag, $properties['allWrap']);
1002 }
1003 if ($properties['forceOnTop']) {
1004 if ($properties['section'] === self::PART_HEADER) {
1005 $jsFiles = $tag . chr(10) . $jsFiles;
1006 } else {
1007 $jsFooterFiles = $tag . chr(10) . $jsFooterFiles;
1008 }
1009 } else {
1010 if ($properties['section'] === self::PART_HEADER) {
1011 $jsFiles .= chr(10) . $tag;
1012 } else {
1013 $jsFooterFiles .= chr(10) . $tag;
1014 }
1015 }
1016 }
1017 }
1018
1019 if (count($this->jsInline)) {
1020 foreach ($this->jsInline as $name => $properties) {
1021 if ($properties['forceOnTop']) {
1022 if ($properties['section'] === self::PART_HEADER) {
1023 $jsInline = '/*' . htmlspecialchars($name) . '*/' . chr(10) . $properties['code'] . chr(10) . $jsInline;
1024 } else {
1025 $jsFooterInline = '/*' . htmlspecialchars($name) . '*/' . chr(10) . $properties['code'] . chr(10) . $jsFooterInline;
1026 }
1027 } else {
1028 if ($properties['section'] === self::PART_HEADER) {
1029 $jsInline .= '/*' . htmlspecialchars($name) . '*/' . chr(10) . $properties['code'] . chr(10);
1030 } else {
1031 $jsFooterInline .= '/*' . htmlspecialchars($name) . '*/' . chr(10) . $properties['code'] . chr(10);
1032 }
1033 }
1034 }
1035 }
1036
1037
1038 if ($jsInline) {
1039 $jsInline = $this->inlineJavascriptWrap[0] . $jsInline . $this->inlineJavascriptWrap[1];
1040 }
1041
1042 if ($jsFooterInline) {
1043 $jsFooterInline = $this->inlineJavascriptWrap[0] . $jsFooterInline . $this->inlineJavascriptWrap[1];
1044 }
1045
1046
1047 // get template
1048 $templateFile = t3lib_div::getFileAbsFileName($this->templateFile, TRUE);
1049 $template = t3lib_div::getURL($templateFile);
1050
1051 if ($this->removeEmptyLinesFromTemplate) {
1052 $template = strtr($template, array(chr(10) => '', chr(13) => ''));
1053 }
1054 if ($part != self::PART_COMPLETE) {
1055 $templatePart = explode('###BODY###', $template);
1056 $template = $templatePart[$part - 1];
1057 }
1058
1059 if ($this->moveJsFromHeaderToFooter) {
1060 $jsFooterLibs = $jsLibs . chr(10) . $jsFooterLibs;
1061 $jsLibs = '';
1062 $jsFooterFiles = $jsFiles . chr(10) . $jsFooterFiles;
1063 $jsFiles = '';
1064 $jsFooterInline = $jsInline . chr(10) . $jsFooterInline;
1065 $jsInline = '';
1066 }
1067
1068 $markerArray = array(
1069 'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
1070 'HTMLTAG' => $this->htmlTag,
1071 'HEADTAG' => $this->headTag,
1072 'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
1073 'INLINECOMMENT' => $this->inlineComments ? chr(10) . chr(10) . '<!-- ' . chr(10) . implode(chr(10), $this->inlineComments) . '-->' . chr(10) . chr(10) : '',
1074 'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
1075 'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
1076 'CSS_INCLUDE' => $cssFiles,
1077 'CSS_INLINE' => $cssInline,
1078 'JS_INLINE' => $jsInline,
1079 'JS_INCLUDE' => $jsFiles,
1080 'JS_LIBS' => $jsLibs,
1081 'TITLE' => $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '',
1082 'META' => $metaTags,
1083 'HEADERDATA' => $this->headerData ? implode(chr(10), $this->headerData) : '',
1084 'FOOTERDATA' => $this->footerData ? implode(chr(10), $this->footerData) : '',
1085 'JS_LIBS_FOOTER' => $jsFooterLibs,
1086 'JS_INCLUDE_FOOTER' => $jsFooterFiles,
1087 'JS_INLINE_FOOTER' => $jsFooterInline,
1088 'BODY' => $this->bodyContent,
1089 );
1090
1091 $markerArray = array_map('trim', $markerArray);
1092
1093 $this->reset();
1094 return trim(t3lib_parsehtml::substituteMarkerArray($template, $markerArray, '###|###'));
1095 }
1096
1097 /**
1098 * helper function for render the javascript libraries
1099 *
1100 * @return string content with javascript libraries
1101 */
1102 protected function renderJsLibraries() {
1103 $out = '';
1104
1105 if ($this->addPrototype) {
1106 $out .= '<script src="' . $this->backPath . 'contrib/prototype/prototype.js" type="text/javascript"></script>' . chr(10);
1107 unset($this->jsFiles[$this->backPath . 'contrib/prototype/prototype.js']);
1108 }
1109
1110 if ($this->addScriptaculous) {
1111 $mods = array ();
1112 foreach ($this->addScriptaculousModules as $key => $value) {
1113 if ($this->addScriptaculousModules[$key]) {
1114 $mods[] = $key;
1115 }
1116 }
1117 // resolve dependencies
1118 if (in_array('dragdrop', $mods) || in_array('controls', $mods)) {
1119 $mods = array_merge(array('effects'), $mods);
1120 }
1121
1122 if (count($mods)) {
1123 $moduleLoadString = '?load=' . implode(',', $mods);
1124 }
1125
1126 $out .= '<script src="' . $this->backPath . 'contrib/scriptaculous/scriptaculous.js' . $moduleLoadString . '" type="text/javascript"></script>' . chr(10);
1127 unset($this->jsFiles[$this->backPath . 'contrib/scriptaculous/scriptaculous.js' . $moduleLoadString]);
1128 }
1129
1130 // include extCore
1131 if ($this->addExtCore) {
1132 $out .= '<script src="' . $this->backPath . 'contrib/extjs/ext-core' . ($this->enableExtCoreDebug ? '-debug' : '') . '.js" type="text/javascript"></script>' . chr(10);
1133 unset($this->jsFiles[$this->backPath . 'contrib/extjs/ext-core' . ($this->enableExtCoreDebug ? '-debug' : '') . '.js']);
1134 }
1135
1136 // include extJS
1137 if ($this->addExtJS) {
1138 // use the base adapter all the time
1139 $out .= '<script src="' . $this->backPath . 'contrib/extjs/adapter/' . $this->extJSadapter . '" type="text/javascript"></script>' . chr(10);
1140 $out .= '<script src="' . $this->backPath . 'contrib/extjs/ext-all' . ($this->enableExtJsDebug ? '-debug' : '') . '.js" type="text/javascript"></script>' . chr(10);
1141
1142 // add extJS localization
1143 $localeMap = $this->csConvObj->isoArray; // load standard ISO mapping and modify for use with ExtJS
1144 $localeMap[''] = 'en';
1145 $localeMap['default'] = 'en';
1146 $localeMap['gr'] = 'el_GR'; // Greek
1147 $localeMap['no'] = 'no_BO'; // Norwegian Bokmaal
1148 $localeMap['se'] = 'se_SV'; // Swedish
1149
1150
1151 $extJsLang = isset($localeMap[$this->lang]) ? $localeMap[$this->lang] : $this->lang;
1152 // TODO autoconvert file from UTF8 to current BE charset if necessary!!!!
1153 $extJsLocaleFile = 'contrib/extjs/locale/ext-lang-' . $extJsLang . '-min.js';
1154 if (file_exists(PATH_typo3 . $extJsLocaleFile)) {
1155 $out .= '<script src="' . $this->backPath . $extJsLocaleFile . '" type="text/javascript"></script>' . chr(10);
1156 }
1157
1158
1159 // remove extjs from JScodeLibArray
1160 unset(
1161 $this->jsFiles[$this->backPath . 'contrib/extjs/ext-all.js'], $this->jsFiles[$this->backPath . 'contrib/extjs/ext-all-debug.js']
1162 );
1163 }
1164 if ($this->addExtCore || $this->addExtJS) {
1165 // set clear.gif, move it on top, add handler code
1166 $code = '';
1167 if (count($this->extOnReadyCode)) {
1168 foreach ($this->extOnReadyCode as $block) {
1169 $code .= $block;
1170 }
1171 }
1172
1173 $out .= $this->inlineJavascriptWrap[0] . '
1174 Ext.ns("TYPO3");
1175 Ext.BLANK_IMAGE_URL = "' . htmlspecialchars(t3lib_div::locationHeaderUrl($this->backPath . 'gfx/clear.gif')) . '";' . chr(10) .
1176 'TYPO3.lang = ' . json_encode($this->inlineLanguageLabels) . ';' . 'TYPO3.settings = ' . json_encode($this->inlineSettings) . ';' .
1177 'Ext.onReady(function() {' .
1178 ($this->enableExtJSQuickTips ? 'Ext.QuickTips.init();' . chr(10) : '') . $code .
1179 ' });' . $this->inlineJavascriptWrap[1];
1180 unset ($this->extOnReadyCode);
1181 }
1182
1183 return $out;
1184 }
1185
1186 /*****************************************************/
1187 /* */
1188 /* Tools */
1189 /* */
1190 /* */
1191 /*****************************************************/
1192
1193 /**
1194 * concatenate files into one file
1195 * registered handler
1196 * TODO: implement own method
1197 *
1198 * @return void
1199 */
1200 protected function doConcatenate() {
1201 // traverse the arrays, concatenate in one file
1202 // then remove concatenated files from array and add the concatenated file
1203
1204
1205 // extern concatination
1206 if ($this->concatenateFiles && $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['concatenateHandler']) {
1207 // use extern concatenate routine
1208 $params = array (
1209 'jsLibs' => &$this->jsLibs,
1210 'jsFiles' => &$this->jsFiles,
1211 'jsFooterFiles' => &$this->jsFiles,
1212 'cssFiles' => &$this->cssFiles,
1213 );
1214 t3lib_div::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['concatenateHandler'], $params, $this);
1215 } else {
1216 // own method, nothing implemented atm
1217
1218
1219 }
1220 }
1221
1222 /**
1223 * compress inline code
1224 *
1225 */
1226 protected function doCompress() {
1227
1228 if ($this->compressJavascript && $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler']) {
1229 // use extern compress routine
1230 $params = array (
1231 'jsInline' => &$this->jsInline,
1232 'jsFooterInline' => &$this->jsFooterInline
1233 );
1234 t3lib_div::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'], $params, $this);
1235 } else {
1236 // traverse the arrays, compress files
1237 $this->compressError = '';
1238
1239 if ($this->compressJavascript) {
1240 if (count($this->jsInline)) {
1241 foreach ($this->jsInline as $name => $properties) {
1242 if (!$properties['compressed']) {
1243 $error = '';
1244 $this->jsInline[$name]['code'] = t3lib_div::minifyJavaScript($properties['code'], $error);
1245 if ($error) {
1246 $this->compressError .= 'Error with minify JS Inline Block "' . $name . '": ' . $error . chr(10);
1247 }
1248 }
1249 }
1250 }
1251 }
1252 }
1253
1254 if ($this->compressCss && $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler']) {
1255 // use extern compress routine
1256 $params = array (
1257 'cssInline' => &$this->cssInline
1258 );
1259 t3lib_div::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'], $params, $this);
1260 } else {
1261 if ($this->compressCss) {
1262 // own method, nothing implemented atm
1263 }
1264 }
1265 }
1266
1267 }
1268
1269 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_pagerenderer.php']) {
1270 include_once ($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_pagerenderer.php']);
1271 }
1272 ?>