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