[FEATURE] Add a value slider as wizard to tceforms
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_pagerenderer.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009-2011 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 */
36 class t3lib_PageRenderer implements t3lib_Singleton {
37
38 protected $compressJavascript = FALSE;
39 protected $compressCss = FALSE;
40 protected $removeLineBreaksFromTemplate = FALSE;
41
42 protected $concatenateFiles = FALSE;
43
44 protected $moveJsFromHeaderToFooter = FALSE;
45
46 /* @var t3lib_cs Instance of t3lib_cs */
47 protected $csConvObj;
48 protected $lang;
49
50 /* @var t3lib_Compressor Instance of t3lib_Compressor */
51 protected $compressor;
52
53 // static array containing associative array for the included files
54 protected static $jsFiles = array();
55 protected static $jsFooterFiles = array();
56 protected static $jsLibs = array();
57 protected static $jsFooterLibs = array();
58 protected static $cssFiles = array();
59
60 protected $title;
61 protected $charSet;
62 protected $favIcon;
63 protected $baseUrl;
64
65 protected $renderXhtml = TRUE;
66
67 // static header blocks
68 protected $xmlPrologAndDocType = '';
69 protected $metaTags = array();
70 protected $inlineComments = array();
71 protected $headerData = array();
72 protected $footerData = array();
73 protected $titleTag = '<title>|</title>';
74 protected $metaCharsetTag = '<meta http-equiv="Content-Type" content="text/html; charset=|" />';
75 protected $htmlTag = '<html>';
76 protected $headTag = '<head>';
77 protected $baseUrlTag = '<base href="|" />';
78 protected $iconMimeType = '';
79 protected $shortcutTag = '<link rel="shortcut icon" href="%1$s"%2$s />
80 <link rel="icon" href="%1$s"%2$s />';
81
82 // static inline code blocks
83 protected $jsInline = array();
84 protected $jsFooterInline = array();
85 protected $extOnReadyCode = array();
86 protected $cssInline = array();
87
88 protected $bodyContent;
89
90 protected $templateFile;
91
92 protected $jsLibraryNames = array('prototype', 'scriptaculous', 'extjs');
93
94 const PART_COMPLETE = 0;
95 const PART_HEADER = 1;
96 const PART_FOOTER = 2;
97
98 // paths to contibuted libraries
99 protected $prototypePath = 'contrib/prototype/';
100 protected $scriptaculousPath = 'contrib/scriptaculous/';
101 protected $extCorePath = 'contrib/extjs/';
102 protected $extJsPath = 'contrib/extjs/';
103 protected $svgPath = 'contrib/websvg/';
104
105
106 // internal flags for JS-libraries
107 protected $addPrototype = FALSE;
108 protected $addScriptaculous = FALSE;
109 protected $addScriptaculousModules = array('builder' => FALSE, 'effects' => FALSE, 'dragdrop' => FALSE, 'controls' => FALSE, 'slider' => FALSE);
110 protected $addExtJS = FALSE;
111 protected $addExtCore = FALSE;
112 protected $extJSadapter = 'ext/ext-base.js';
113 protected $extDirectCodeAdded = FALSE;
114
115 protected $enableExtJsDebug = FALSE;
116 protected $enableExtCoreDebug = FALSE;
117
118 // available adapters for extJs
119 const EXTJS_ADAPTER_JQUERY = 'jquery';
120 const EXTJS_ADAPTER_PROTOTYPE = 'prototype';
121 const EXTJS_ADAPTER_YUI = 'yui';
122
123 protected $extJStheme = TRUE;
124 protected $extJScss = TRUE;
125
126 protected $enableExtJSQuickTips = FALSE;
127
128 protected $inlineLanguageLabels = array();
129 protected $inlineLanguageLabelFiles = array();
130 protected $inlineSettings = array();
131
132 protected $inlineJavascriptWrap = array();
133
134 // saves error messages generated during compression
135 protected $compressError = '';
136
137 // SVG library
138 protected $addSvg = FALSE;
139 protected $enableSvgDebug = FALSE;
140
141 // used by BE modules
142 public $backPath;
143
144 /**
145 * Constructor
146 *
147 * @param string $templateFile declare the used template file. Omit this parameter will use default template
148 * @param string $backPath relative path to typo3-folder. It varies for BE modules, in FE it will be typo3/
149 * @return void
150 */
151 public function __construct($templateFile = '', $backPath = NULL) {
152
153 $this->reset();
154 $this->csConvObj = t3lib_div::makeInstance('t3lib_cs');
155
156 if (strlen($templateFile)) {
157 $this->templateFile = $templateFile;
158 }
159 $this->backPath = isset($backPath) ? $backPath : $GLOBALS['BACK_PATH'];
160
161 $this->inlineJavascriptWrap = array(
162 '<script type="text/javascript">' . LF . '/*<![CDATA[*/' . LF . '<!-- ' . LF,
163 '// -->' . LF . '/*]]>*/' . LF . '</script>' . LF
164 );
165 $this->inlineCssWrap = array(
166 '<style type="text/css">' . LF . '/*<![CDATA[*/' . LF . '<!-- ' . LF,
167 '-->' . LF . '/*]]>*/' . LF . '</style>' . LF
168 );
169
170 }
171
172 /**
173 * reset all vars to initial values
174 *
175 * @return void
176 */
177 protected function reset() {
178 $this->templateFile = TYPO3_mainDir . 'templates/template_page_backend.html';
179 $this->jsFiles = array();
180 $this->jsFooterFiles = array();
181 $this->jsInline = array();
182 $this->jsFooterInline = array();
183 $this->jsLibs = array();
184 $this->cssFiles = array();
185 $this->cssInline = array();
186 $this->metaTags = array();
187 $this->inlineComments = array();
188 $this->headerData = array();
189 $this->footerData = array();
190 $this->extOnReadyCode = array();
191 }
192
193 /*****************************************************/
194 /* */
195 /* Public Setters */
196 /* */
197 /* */
198 /*****************************************************/
199
200 /**
201 * Sets the title
202 *
203 * @param string $title title of webpage
204 * @return void
205 */
206 public function setTitle($title) {
207 $this->title = $title;
208 }
209
210
211 /**
212 * Enables/disables rendering of XHTML code
213 *
214 * @param boolean $enable Enable XHTML
215 * @return void
216 */
217 public function setRenderXhtml($enable) {
218 $this->renderXhtml = $enable;
219 }
220
221 /**
222 * Sets xml prolog and docType
223 *
224 * @param string $xmlPrologAndDocType complete tags for xml prolog and docType
225 * @return void
226 */
227 public function setXmlPrologAndDocType($xmlPrologAndDocType) {
228 $this->xmlPrologAndDocType = $xmlPrologAndDocType;
229 }
230
231 /**
232 * Sets meta charset
233 *
234 * @param string $charSet used charset
235 * @return void
236 */
237 public function setCharSet($charSet) {
238 $this->charSet = $charSet;
239 }
240
241 /**
242 * Sets language
243 *
244 * @param string $lang used language
245 * @return void
246 */
247 public function setLanguage($lang) {
248 $this->lang = $lang;
249 }
250
251 /**
252 * Set the meta charset tag
253 *
254 * @param string $metaCharsetTag
255 * @return void
256 */
257 public function setMetaCharsetTag($metaCharsetTag) {
258 $this->metaCharsetTag = $metaCharsetTag;
259 }
260
261 /**
262 * Sets html tag
263 *
264 * @param string $htmlTag html tag
265 * @return void
266 */
267 public function setHtmlTag($htmlTag) {
268 $this->htmlTag = $htmlTag;
269 }
270
271 /**
272 * Sets head tag
273 *
274 * @param string $tag head tag
275 * @return void
276 */
277 public function setHeadTag($headTag) {
278 $this->headTag = $headTag;
279 }
280
281 /**
282 * Sets favicon
283 *
284 * @param string $favIcon
285 * @return void
286 */
287 public function setFavIcon($favIcon) {
288 $this->favIcon = $favIcon;
289 }
290
291 /**
292 * Sets icon mime type
293 *
294 * @param string $iconMimeType
295 * @return void
296 */
297 public function setIconMimeType($iconMimeType) {
298 $this->iconMimeType = $iconMimeType;
299 }
300
301 /**
302 * Sets base url
303 *
304 * @param string $url
305 * @return void
306 */
307 public function setBaseUrl($baseUrl) {
308 $this->baseUrl = $baseUrl;
309 }
310
311 /**
312 * Sets template file
313 *
314 * @param string $file
315 * @return void
316 */
317 public function setTemplateFile($file) {
318 $this->templateFile = $file;
319 }
320
321 /**
322 * Sets back path
323 *
324 * @param string $backPath
325 * @return void
326 */
327 public function setBackPath($backPath) {
328 $this->backPath = $backPath;
329 }
330
331 /**
332 * Sets Content for Body
333 *
334 * @param string $content
335 * @return void
336 */
337 public function setBodyContent($content) {
338 $this->bodyContent = $content;
339 }
340
341 /**
342 * Sets Path for prototype library (relative to typo3 directory)
343 *
344 * @param string path
345 * @return void
346 */
347 public function setPrototypePath($path) {
348 $this->prototypePath = $path;
349 }
350
351 /**
352 * Sets Path for scriptaculous library (relative to typo3 directory)
353 *
354 * @param string $path
355 * @return void
356 */
357 public function setScriptaculousPath($path) {
358 $this->scriptaculousPath = $path;
359 }
360
361 /**
362 * Sets Path for Ext Core library (relative to typo3 directory)
363 *
364 * @param string $path
365 * @return void
366 */
367 public function setExtCorePath($path) {
368 $this->extCorePath = $path;
369 }
370
371 /**
372 * Sets Path for ExtJs library (relative to typo3 directory)
373 *
374 * @param string $path
375 * @return void
376 */
377 public function setExtJsPath($path) {
378 $this->extJsPath = $path;
379 }
380
381 /**
382 * Sets Path for SVG library (websvg)
383 *
384 * @param string $path
385 * @return void
386 */
387 public function setSvgPath($path) {
388 $this->svgPath = $path;
389 }
390
391 /*****************************************************/
392 /* */
393 /* Public Enablers / Disablers */
394 /* */
395 /* */
396 /*****************************************************/
397
398 /**
399 * Enables MoveJsFromHeaderToFooter
400 *
401 * @param void
402 * @return void
403 */
404 public function enableMoveJsFromHeaderToFooter() {
405 $this->moveJsFromHeaderToFooter = TRUE;
406 }
407
408 /**
409 * Disables MoveJsFromHeaderToFooter
410 *
411 * @param void
412 * @return void
413 */
414 public function disableMoveJsFromHeaderToFooter() {
415 $this->moveJsFromHeaderToFooter = FALSE;
416 }
417
418 /**
419 * Enables compression of javascript
420 *
421 * @param void
422 * @return void
423 */
424 public function enableCompressJavascript() {
425 $this->compressJavascript = TRUE;
426 }
427
428 /**
429 * Disables compression of javascript
430 *
431 * @param void
432 * @return void
433 */
434 public function disableCompressJavascript() {
435 $this->compressJavascript = FALSE;
436 }
437
438 /**
439 * Enables compression of css
440 *
441 * @param void
442 * @return void
443 */
444 public function enableCompressCss() {
445 $this->compressCss = TRUE;
446 }
447
448 /**
449 * Disables compression of css
450 *
451 * @param void
452 * @return void
453 */
454 public function disableCompressCss() {
455 $this->compressCss = FALSE;
456 }
457
458 /**
459 * Enables concatenation of js/css files
460 *
461 * @param void
462 * @return void
463 */
464 public function enableConcatenateFiles() {
465 $this->concatenateFiles = TRUE;
466 }
467
468 /**
469 * Disables concatenation of js/css files
470 *
471 * @param void
472 * @return void
473 */
474 public function disableConcatenateFiles() {
475 $this->concatenateFiles = FALSE;
476 }
477
478 /**
479 * Sets removal of all line breaks in template
480 *
481 * @param void
482 * @return void
483 */
484 public function enableRemoveLineBreaksFromTemplate() {
485 $this->removeLineBreaksFromTemplate = TRUE;
486 }
487
488 /**
489 * Unsets removal of all line breaks in template
490 *
491 * @param void
492 * @return void
493 */
494 public function disableRemoveLineBreaksFromTemplate() {
495 $this->removeLineBreaksFromTemplate = FALSE;
496 }
497
498 /**
499 * Enables Debug Mode
500 * This is a shortcut to switch off all compress/concatenate features to enable easier debug
501 *
502 * @param void
503 * @return void
504 */
505 public function enableDebugMode() {
506 $this->compressJavascript = FALSE;
507 $this->compressCss = FALSE;
508 $this->concatenateFiles = FALSE;
509 $this->removeLineBreaksFromTemplate = FALSE;
510 $this->enableExtCoreDebug = TRUE;
511 $this->enableExtJsDebug = TRUE;
512 $this->enableSvgDebug = TRUE;
513 }
514
515 /*****************************************************/
516 /* */
517 /* Public Getters */
518 /* */
519 /* */
520 /*****************************************************/
521
522 /**
523 * Gets the title
524 *
525 * @return string $title title of webpage
526 */
527 public function getTitle() {
528 return $this->title;
529 }
530
531 /**
532 * Gets the charSet
533 *
534 * @return string $charSet
535 */
536 public function getCharSet() {
537 return $this->charSet;
538 }
539
540 /**
541 * Gets the language
542 *
543 * @return string $lang
544 */
545 public function getLanguage() {
546 return $this->lang;
547 }
548
549 /**
550 * Returns rendering mode XHTML or HTML
551 *
552 * @return boolean TRUE if XHTML, FALSE if HTML
553 */
554 public function getRenderXhtml() {
555 return $this->renderXhtml;
556 }
557
558 /**
559 * Gets html tag
560 *
561 * @return string $htmlTag html tag
562 */
563 public function getHtmlTag() {
564 return $this->htmlTag;
565 }
566
567 /**
568 * Get meta charset
569 *
570 * @return string
571 */
572 public function getMetaCharsetTag() {
573 return $this->metaCharsetTag;
574 }
575
576 /**
577 * Gets head tag
578 *
579 * @return string $tag head tag
580 */
581 public function getHeadTag() {
582 return $this->headTag;
583 }
584
585 /**
586 * Gets favicon
587 *
588 * @return string $favIcon
589 */
590 public function getFavIcon() {
591 return $this->favIcon;
592 }
593
594 /**
595 * Gets icon mime type
596 *
597 * @return string $iconMimeType
598 */
599 public function getIconMimeType() {
600 return $this->iconMimeType;
601 }
602
603 /**
604 * Gets base url
605 *
606 * @return string $url
607 */
608 public function getBaseUrl() {
609 return $this->baseUrl;
610 }
611
612 /**
613 * Gets template file
614 *
615 * @return string $file
616 */
617 public function getTemplateFile($file) {
618 return $this->templateFile;
619 }
620
621 /**
622 * Gets MoveJsFromHeaderToFooter
623 *
624 * @return boolean
625 */
626 public function getMoveJsFromHeaderToFooter() {
627 return $this->moveJsFromHeaderToFooter;
628 }
629
630 /**
631 * Gets compress of javascript
632 *
633 * @return boolean
634 */
635 public function getCompressJavascript() {
636 return $this->compressJavascript;
637 }
638
639 /**
640 * Gets compress of css
641 *
642 * @return boolean
643 */
644 public function getCompressCss() {
645 return $this->compressCss;
646 }
647
648 /**
649 * Gets concatenate of files
650 *
651 * @return boolean
652 */
653 public function getConcatenateFiles() {
654 return $this->concatenateFiles;
655 }
656
657 /**
658 * Gets remove of empty lines from template
659 *
660 * @return boolean
661 */
662 public function getRemoveLineBreaksFromTemplate() {
663 return $this->removeLineBreaksFromTemplate;
664 }
665
666 /**
667 * Gets content for body
668 *
669 * @return string
670 */
671 public function getBodyContent() {
672 return $this->bodyContent;
673 }
674
675 /**
676 * Gets Path for prototype library (relative to typo3 directory)
677 *
678 * @return string
679 */
680 public function getPrototypePath() {
681 return $this->prototypePath;
682 }
683
684 /**
685 * Gets Path for scriptaculous library (relative to typo3 directory)
686 *
687 * @return string
688 */
689 public function getScriptaculousPath() {
690 return $this->scriptaculousPath;
691 }
692
693 /**
694 * Gets Path for Ext Core library (relative to typo3 directory)
695 *
696 * @return string
697 */
698 public function getExtCorePath() {
699 return $this->extCorePath;
700 }
701
702 /**
703 * Gets Path for ExtJs library (relative to typo3 directory)
704 *
705 * @return string
706 */
707 public function getExtJsPath() {
708 return $this->extJsPath;
709 }
710
711 /**
712 * Gets Path for SVG library (relative to typo3 directory)
713 *
714 * @return string
715 */
716 public function getSvgPath() {
717 return $this->svgPath;
718 }
719
720 /**
721 * Gets the inline language labels.
722 *
723 * @return array The inline language labels
724 */
725 public function getInlineLanguageLabels() {
726 return $this->inlineLanguageLabels;
727 }
728
729 /**
730 * Gets the inline language files
731 *
732 * @return array
733 */
734 public function getInlineLanguageLabelFiles() {
735 return $this->inlineLanguageLabelFiles;
736 }
737
738 /*****************************************************/
739 /* */
740 /* Public Function to add Data */
741 /* */
742 /* */
743 /*****************************************************/
744
745 /**
746 * Adds meta data
747 *
748 * @param string $meta meta data (complete metatag)
749 * @return void
750 */
751 public function addMetaTag($meta) {
752 if (!in_array($meta, $this->metaTags)) {
753 $this->metaTags[] = $meta;
754 }
755 }
756
757 /**
758 * Adds inline HTML comment
759 *
760 * @param string $comment
761 * @return void
762 */
763 public function addInlineComment($comment) {
764 if (!in_array($comment, $this->inlineComments)) {
765 $this->inlineComments[] = $comment;
766 }
767 }
768
769 /**
770 * Adds header data
771 *
772 * @param string $data free header data for HTML header
773 * @return void
774 */
775 public function addHeaderData($data) {
776 if (!in_array($data, $this->headerData)) {
777 $this->headerData[] = $data;
778 }
779 }
780
781 /**
782 * Adds footer data
783 *
784 * @param string $data free header data for HTML header
785 * @return void
786 */
787 public function addFooterData($data) {
788 if (!in_array($data, $this->footerData)) {
789 $this->footerData[] = $data;
790 }
791 }
792
793 /* Javascript Files */
794
795 /**
796 * Adds JS Library. JS Library block is rendered on top of the JS files.
797 *
798 * @param string $name
799 * @param string $file
800 * @param string $type
801 * @param boolean $compress flag if library should be compressed
802 * @param boolean $forceOnTop flag if added library should be inserted at begin of this block
803 * @param string $allWrap
804 * @return void
805 */
806 public function addJsLibrary($name, $file, $type = 'text/javascript', $compress = FALSE, $forceOnTop = FALSE, $allWrap = '') {
807 if (!$type) {
808 $type = 'text/javascript';
809 }
810 if (!in_array(strtolower($name), $this->jsLibs)) {
811 $this->jsLibs[strtolower($name)] = array(
812 'file' => $file,
813 'type' => $type,
814 'section' => self::PART_HEADER,
815 'compress' => $compress,
816 'forceOnTop' => $forceOnTop,
817 'allWrap' => $allWrap
818 );
819 }
820
821 }
822
823 /**
824 * Adds JS Library to Footer. JS Library block is rendered on top of the Footer JS files.
825 *
826 * @param string $name
827 * @param string $file
828 * @param string $type
829 * @param boolean $compress flag if library should be compressed
830 * @param boolean $forceOnTop flag if added library should be inserted at begin of this block
831 * @param string $allWrap
832 * @return void
833 */
834 public function addJsFooterLibrary($name, $file, $type = 'text/javascript', $compress = FALSE, $forceOnTop = FALSE, $allWrap = '') {
835 if (!$type) {
836 $type = 'text/javascript';
837 }
838 if (!in_array(strtolower($name), $this->jsLibs)) {
839 $this->jsLibs[strtolower($name)] = array(
840 'file' => $file,
841 'type' => $type,
842 'section' => self::PART_FOOTER,
843 'compress' => $compress,
844 'forceOnTop' => $forceOnTop,
845 'allWrap' => $allWrap
846 );
847 }
848
849 }
850
851 /**
852 * Adds JS file
853 *
854 * @param string $file
855 * @param string $type
856 * @param boolean $compress
857 * @param boolean $forceOnTop
858 * @param string $allWrap
859 * @return void
860 */
861 public function addJsFile($file, $type = 'text/javascript', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '') {
862 if (!$type) {
863 $type = 'text/javascript';
864 }
865 if (!isset($this->jsFiles[$file])) {
866 $this->jsFiles[$file] = array(
867 'type' => $type,
868 'section' => self::PART_HEADER,
869 'compress' => $compress,
870 'forceOnTop' => $forceOnTop,
871 'allWrap' => $allWrap
872 );
873 }
874 }
875
876 /**
877 * Adds JS file to footer
878 *
879 * @param string $file
880 * @param string $type
881 * @param boolean $compress
882 * @param boolean $forceOnTop
883 * @return void
884 */
885 public function addJsFooterFile($file, $type = 'text/javascript', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '') {
886 if (!$type) {
887 $type = 'text/javascript';
888 }
889 if (!isset($this->jsFiles[$file])) {
890 $this->jsFiles[$file] = array(
891 'type' => $type,
892 'section' => self::PART_FOOTER,
893 'compress' => $compress,
894 'forceOnTop' => $forceOnTop,
895 'allWrap' => $allWrap
896 );
897 }
898 }
899
900 /*Javascript Inline Blocks */
901
902 /**
903 * Adds JS inline code
904 *
905 * @param string $name
906 * @param string $block
907 * @param boolean $compress
908 * @param boolean $forceOnTop
909 * @return void
910 */
911 public function addJsInlineCode($name, $block, $compress = TRUE, $forceOnTop = FALSE) {
912 if (!isset($this->jsInline[$name]) && !empty($block)) {
913 $this->jsInline[$name] = array(
914 'code' => $block . LF,
915 'section' => self::PART_HEADER,
916 'compress' => $compress,
917 'forceOnTop' => $forceOnTop
918 );
919 }
920 }
921
922 /**
923 * Adds JS inline code to footer
924 *
925 * @param string $name
926 * @param string $block
927 * @param boolean $compress
928 * @param boolean $forceOnTop
929 * @return void
930 */
931 public function addJsFooterInlineCode($name, $block, $compress = TRUE, $forceOnTop = FALSE) {
932 if (!isset($this->jsInline[$name]) && !empty($block)) {
933 $this->jsInline[$name] = array(
934 'code' => $block . LF,
935 'section' => self::PART_FOOTER,
936 'compress' => $compress,
937 'forceOnTop' => $forceOnTop
938 );
939 }
940 }
941
942 /**
943 * Adds Ext.onready code, which will be wrapped in Ext.onReady(function() {...});
944 *
945 * @param string $block javascript code
946 * @param boolean $forceOnTop position of the javascript code (TRUE for putting it on top, default is FALSE = bottom)
947 * @return void
948 */
949 public function addExtOnReadyCode($block, $forceOnTop = FALSE) {
950 if (!in_array($block, $this->extOnReadyCode)) {
951 if ($forceOnTop) {
952 array_unshift($this->extOnReadyCode, $block);
953 } else {
954 $this->extOnReadyCode[] = $block;
955 }
956 }
957 }
958
959 /**
960 * Adds the ExtDirect code
961 *
962 * @param array $filterNamespaces limit the output to defined namespaces. If empty, all namespaces are generated
963 * @return void
964 */
965 public function addExtDirectCode(array $filterNamespaces = array()) {
966 if ($this->extDirectCodeAdded) {
967 return;
968 }
969 $this->extDirectCodeAdded = TRUE;
970
971 if (count($filterNamespaces) === 0) {
972 $filterNamespaces = array('TYPO3');
973 }
974
975 // for ExtDirect we need flash message support
976 $this->addJsFile(t3lib_div::resolveBackPath($this->backPath . '../t3lib/js/extjs/ux/flashmessages.js'));
977
978 // add language labels for ExtDirect
979 if (TYPO3_MODE === 'FE') {
980 $this->addInlineLanguageLabelArray(array(
981 'extDirect_timeoutHeader' => $GLOBALS['TSFE']->sL('LLL:EXT:lang/locallang_misc.xml:extDirect_timeoutHeader'),
982 'extDirect_timeoutMessage' => $GLOBALS['TSFE']->sL('LLL:EXT:lang/locallang_misc.xml:extDirect_timeoutMessage'),
983 ));
984 } else {
985 $this->addInlineLanguageLabelArray(array(
986 'extDirect_timeoutHeader' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:extDirect_timeoutHeader'),
987 'extDirect_timeoutMessage' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xml:extDirect_timeoutMessage'),
988 ));
989 }
990
991 $token = $api = '';
992 if (TYPO3_MODE === 'BE') {
993 $formprotection = t3lib_formprotection_Factory::get();
994 $token = $formprotection->generateToken('extDirect');
995 }
996
997 /** @var $extDirect t3lib_extjs_ExtDirectApi */
998 $extDirect = t3lib_div::makeInstance('t3lib_extjs_ExtDirectApi');
999 $api = $extDirect->getApiPhp($filterNamespaces);
1000 if ($api) {
1001 $this->addJsInlineCode('TYPO3ExtDirectAPI', $api);
1002 }
1003 // Note: we need to iterate thru the object, because the addProvider method
1004 // does this only with multiple arguments
1005 $this->addExtOnReadyCode('
1006 (function() {
1007 TYPO3.ExtDirectToken = "' . $token . '";
1008 for (var api in Ext.app.ExtDirectAPI) {
1009 var provider = Ext.Direct.addProvider(Ext.app.ExtDirectAPI[api]);
1010 provider.on("beforecall", function(provider, transaction, meta) {
1011 if (transaction.data) {
1012 transaction.data[transaction.data.length] = TYPO3.ExtDirectToken;
1013 } else {
1014 transaction.data = [TYPO3.ExtDirectToken];
1015 }
1016 });
1017
1018 provider.on("call", function(provider, transaction, meta) {
1019 if (transaction.isForm) {
1020 transaction.params.securityToken = TYPO3.ExtDirectToken;
1021 }
1022 });
1023 }
1024 })();
1025
1026 var extDirectDebug = function(message, header, group) {
1027 var TYPO3ViewportInstance = null;
1028
1029 if (top && top.TYPO3 && typeof top.TYPO3.Backend === "object") {
1030 TYPO3ViewportInstance = top.TYPO3.Backend;
1031 } else if (typeof TYPO3 === "object" && typeof TYPO3.Backend === "object") {
1032 TYPO3ViewportInstance = TYPO3.Backend;
1033 }
1034
1035 if (TYPO3ViewportInstance !== null) {
1036 TYPO3ViewportInstance.DebugConsole.addTab(message, header, group);
1037 } else if (typeof console === "object") {
1038 console.log(message);
1039 } else {
1040 document.write(message);
1041 }
1042 };
1043
1044 Ext.Direct.on("exception", function(event) {
1045 if (event.code === Ext.Direct.exceptions.TRANSPORT && !event.where) {
1046 TYPO3.Flashmessage.display(
1047 TYPO3.Severity.error,
1048 TYPO3.lang.extDirect_timeoutHeader,
1049 TYPO3.lang.extDirect_timeoutMessage,
1050 30
1051 );
1052 } else {
1053 var backtrace = "";
1054 if (event.code === "parse") {
1055 extDirectDebug(
1056 "<p>" + event.xhr.responseText + "<\/p>",
1057 event.type,
1058 "ExtDirect - Exception"
1059 );
1060 } else if (event.code === "router") {
1061 TYPO3.Flashmessage.display(
1062 TYPO3.Severity.error,
1063 event.code,
1064 event.message,
1065 30
1066 );
1067 } else if (event.where) {
1068 backtrace = "<p style=\"margin-top: 20px;\">" +
1069 "<strong>Backtrace:<\/strong><br \/>" +
1070 event.where.replace(/#/g, "<br \/>#") +
1071 "<\/p>";
1072 extDirectDebug(
1073 "<p>" + event.message + "<\/p>" + backtrace,
1074 event.method,
1075 "ExtDirect - Exception"
1076 );
1077 }
1078
1079
1080 }
1081 });
1082
1083 Ext.Direct.on("event", function(event, provider) {
1084 if (typeof event.debug !== "undefined" && event.debug !== "") {
1085 extDirectDebug(event.debug, event.method, "ExtDirect - Debug");
1086 }
1087 });
1088 ',
1089 TRUE
1090 );
1091 }
1092
1093 /* CSS Files */
1094
1095 /**
1096 * Adds CSS file
1097 *
1098 * @param string $file
1099 * @param string $rel
1100 * @param string $media
1101 * @param string $title
1102 * @param boolean $compress
1103 * @param boolean $forceOnTop
1104 * @return void
1105 */
1106 public function addCssFile($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '') {
1107 if (!isset($this->cssFiles[$file])) {
1108 $this->cssFiles[$file] = array(
1109 'rel' => $rel,
1110 'media' => $media,
1111 'title' => $title,
1112 'compress' => $compress,
1113 'forceOnTop' => $forceOnTop,
1114 'allWrap' => $allWrap
1115 );
1116 }
1117 }
1118
1119 /*CSS Inline Blocks */
1120
1121 /**
1122 * Adds CSS inline code
1123 *
1124 * @param string $name
1125 * @param string $block
1126 * @param boolean $compress
1127 * @param boolean $forceOnTop
1128 * @return void
1129 */
1130 public function addCssInlineBlock($name, $block, $compress = FALSE, $forceOnTop = FALSE) {
1131 if (!isset($this->cssInline[$name]) && !empty($block)) {
1132 $this->cssInline[$name] = array(
1133 'code' => $block,
1134 'compress' => $compress,
1135 'forceOnTop' => $forceOnTop
1136 );
1137 }
1138 }
1139
1140 /* JS Libraries */
1141
1142 /**
1143 * call function if you need the prototype library
1144 *
1145 * @return void
1146 */
1147 public function loadPrototype() {
1148 $this->addPrototype = TRUE;
1149 }
1150
1151 /**
1152 * call function if you need the Scriptaculous library
1153 *
1154 * @param string $modules add modules you need. use "all" if you need complete modules
1155 * @return void
1156 */
1157 public function loadScriptaculous($modules = 'all') {
1158 // Scriptaculous require prototype, so load prototype too.
1159 $this->addPrototype = TRUE;
1160 $this->addScriptaculous = TRUE;
1161 if ($modules) {
1162 if ($modules == 'all') {
1163 foreach ($this->addScriptaculousModules as $key => $value) {
1164 $this->addScriptaculousModules[$key] = TRUE;
1165 }
1166 } else {
1167 $mods = t3lib_div::trimExplode(',', $modules);
1168 foreach ($mods as $mod) {
1169 if (isset($this->addScriptaculousModules[strtolower($mod)])) {
1170 $this->addScriptaculousModules[strtolower($mod)] = TRUE;
1171 }
1172 }
1173 }
1174 }
1175 }
1176
1177 /**
1178 * call this function if you need the extJS library
1179 *
1180 * @param boolean $css flag, if set the ext-css will be loaded
1181 * @param boolean $theme flag, if set the ext-theme "grey" will be loaded
1182 * @param string $adapter choose alternative adapter, possible values: yui, prototype, jquery
1183 * @return void
1184 */
1185 public function loadExtJS($css = TRUE, $theme = TRUE, $adapter = '') {
1186 if ($adapter) {
1187 // empty $adapter will always load the ext adapter
1188 switch (t3lib_div::strtolower(trim($adapter))) {
1189 case self::EXTJS_ADAPTER_YUI :
1190 $this->extJSadapter = 'yui/ext-yui-adapter.js';
1191 break;
1192 case self::EXTJS_ADAPTER_PROTOTYPE :
1193 $this->extJSadapter = 'prototype/ext-prototype-adapter.js';
1194 break;
1195 case self::EXTJS_ADAPTER_JQUERY :
1196 $this->extJSadapter = 'jquery/ext-jquery-adapter.js';
1197 break;
1198 }
1199 }
1200 $this->addExtJS = TRUE;
1201 $this->extJStheme = $theme;
1202 $this->extJScss = $css;
1203
1204 }
1205
1206 /**
1207 * Enables ExtJs QuickTips
1208 * Need extJs loaded
1209 *
1210 * @return void
1211 *
1212 */
1213 public function enableExtJSQuickTips() {
1214 $this->enableExtJSQuickTips = TRUE;
1215 }
1216
1217
1218 /**
1219 * call function if you need the ExtCore library
1220 *
1221 * @return void
1222 */
1223 public function loadExtCore() {
1224 $this->addExtCore = TRUE;
1225 }
1226
1227 /**
1228 * call function if you need the SVG library
1229 *
1230 * @return void
1231 */
1232 public function loadSvg() {
1233 $this->addSvg = TRUE;
1234 }
1235
1236 /**
1237 * call this function to load debug version of ExtJS. Use this for development only
1238 *
1239 */
1240 public function enableSvgDebug() {
1241 $this->enableSvgDebug = TRUE;
1242 }
1243
1244 /**
1245 * call this function to force flash usage with SVG library
1246 *
1247 */
1248 public function svgForceFlash() {
1249 $this->addMetaTag('<meta name="svg.render.forceflash" content="true" />');
1250 }
1251
1252 /**
1253 * call this function to load debug version of ExtJS. Use this for development only
1254 *
1255 */
1256 public function enableExtJsDebug() {
1257 $this->enableExtJsDebug = TRUE;
1258 }
1259
1260 /**
1261 * call this function to load debug version of ExtCore. Use this for development only
1262 *
1263 * @return void
1264 */
1265 public function enableExtCoreDebug() {
1266 $this->enableExtCoreDebug = TRUE;
1267 }
1268
1269 /**
1270 * Adds Javascript Inline Label. This will occur in TYPO3.lang - object
1271 * The label can be used in scripts with TYPO3.lang.<key>
1272 * Need extJs loaded
1273 *
1274 * @param string $key
1275 * @param string $value
1276 * @return void
1277 */
1278 public function addInlineLanguageLabel($key, $value) {
1279 $this->inlineLanguageLabels[$key] = $value;
1280 }
1281
1282 /**
1283 * Adds Javascript Inline Label Array. This will occur in TYPO3.lang - object
1284 * The label can be used in scripts with TYPO3.lang.<key>
1285 * Array will be merged with existing array.
1286 * Need extJs loaded
1287 *
1288 * @param array $array
1289 * @return void
1290 */
1291 public function addInlineLanguageLabelArray(array $array) {
1292 $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $array);
1293 }
1294
1295 /**
1296 * Gets labels to be used in JavaScript fetched from a locallang file.
1297 *
1298 * @param string Input is a file-reference (see t3lib_div::getFileAbsFileName). That file is expected to be a 'locallang.xml' file containing a valid XML TYPO3 language structure.
1299 * @param string $selectionPrefix: Prefix to select the correct labels (default: '')
1300 * @param string $stripFromSelectionName: Sub-prefix to be removed from label names in the result (default: '')
1301 * @param integer Error mode (when file could not be found): 0 - syslog entry, 1 - do nothing, 2 - throw an exception
1302 * @return void
1303 */
1304 public function addInlineLanguageLabelFile($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0) {
1305 $index = md5($fileRef . $selectionPrefix . $stripFromSelectionName);
1306 if ($fileRef && !isset($this->inlineLanguageLabelFiles[$index])) {
1307 $this->inlineLanguageLabelFiles[$index] = array(
1308 'fileRef' => $fileRef,
1309 'selectionPrefix' => $selectionPrefix,
1310 'stripFromSelectionName' => $stripFromSelectionName,
1311 'errorMode' => $errorMode
1312 );
1313 }
1314 }
1315
1316
1317 /**
1318 * Adds Javascript Inline Setting. This will occur in TYPO3.settings - object
1319 * The label can be used in scripts with TYPO3.setting.<key>
1320 * Need extJs loaded
1321 *
1322 * @param string $namespace
1323 * @param string $key
1324 * @param string $value
1325 * @return void
1326 */
1327 public function addInlineSetting($namespace, $key, $value) {
1328 if ($namespace) {
1329 if (strpos($namespace, '.')) {
1330 $parts = explode('.', $namespace);
1331 $a = &$this->inlineSettings;
1332 foreach ($parts as $part) {
1333 $a = &$a[$part];
1334 }
1335 $a[$key] = $value;
1336 } else {
1337 $this->inlineSettings[$namespace][$key] = $value;
1338 }
1339 } else {
1340 $this->inlineSettings[$key] = $value;
1341 }
1342 }
1343
1344 /**
1345 * Adds Javascript Inline Setting. This will occur in TYPO3.settings - object
1346 * The label can be used in scripts with TYPO3.setting.<key>
1347 * Array will be merged with existing array.
1348 * Need extJs loaded
1349 *
1350 * @param string $namespace
1351 * @param array $array
1352 * @return void
1353 */
1354 public function addInlineSettingArray($namespace, array $array) {
1355 if ($namespace) {
1356 if (strpos($namespace, '.')) {
1357 $parts = explode('.', $namespace);
1358 $a = &$this->inlineSettings;
1359 foreach ($parts as $part) {
1360 $a = &$a[$part];
1361 }
1362 $a = array_merge((array) $a, $array);
1363 } else {
1364 $this->inlineSettings[$namespace] = array_merge((array) $this->inlineSettings[$namespace], $array);
1365 }
1366 } else {
1367 $this->inlineSettings = array_merge($this->inlineSettings, $array);
1368 }
1369 }
1370
1371 /**
1372 * Adds content to body content
1373 *
1374 * @param string $content
1375 * @return void
1376 */
1377 public function addBodyContent($content) {
1378 $this->bodyContent .= $content;
1379 }
1380
1381 /*****************************************************/
1382 /* */
1383 /* Render Functions */
1384 /* */
1385 /* */
1386 /*****************************************************/
1387
1388 /**
1389 * render the section (Header or Footer)
1390 *
1391 * @param int $part section which should be rendered: self::PART_COMPLETE, self::PART_HEADER or self::PART_FOOTER
1392 * @return string content of rendered section
1393 */
1394 public function render($part = self::PART_COMPLETE) {
1395
1396 $jsFiles = '';
1397 $cssFiles = '';
1398 $cssInline = '';
1399 $jsInline = '';
1400 $jsFooterInline = '';
1401 $jsFooterLibs = '';
1402 $jsFooterFiles = '';
1403
1404 // preRenderHook for possible manuipulation
1405 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'])) {
1406 $params = array(
1407 'jsLibs' => &$this->jsLibs,
1408 'jsFooterLibs' => &$this->jsFooterLibs,
1409 'jsFiles' => &$this->jsFiles,
1410 'jsFooterFiles' => &$this->jsFooterFiles,
1411 'cssFiles' => &$this->cssFiles,
1412 'headerData' => &$this->headerData,
1413 'footerData' => &$this->footerData,
1414 'jsInline' => &$this->jsInline,
1415 'jsFooterInline' => &$this->jsFooterInline,
1416 'cssInline' => &$this->cssInline,
1417 );
1418 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'] as $hook) {
1419 t3lib_div::callUserFunction($hook, $params, $this);
1420 }
1421 }
1422
1423 $jsLibs = $this->renderJsLibraries();
1424
1425 if ($this->concatenateFiles) {
1426 // do the file concatenation
1427 $this->doConcatenate();
1428 }
1429 if ($this->compressCss || $this->compressJavascript) {
1430 // do the file compression
1431 $this->doCompress();
1432 }
1433
1434 $metaTags = implode(LF, $this->metaTags);
1435
1436 // remove ending slashes from static header block
1437 // if the page is beeing rendered as html (not xhtml)
1438 // and define variable $endingSlash for further use
1439 if ($this->getRenderXhtml()) {
1440 $endingSlash = ' /';
1441 } else {
1442 $this->metaCharsetTag = str_replace(' />', '>', $this->metaCharsetTag);
1443 $this->baseUrlTag = str_replace(' />', '>', $this->baseUrlTag);
1444 $this->shortcutTag = str_replace(' />', '>', $this->shortcutTag);
1445 $endingSlash = '';
1446 }
1447
1448 if (count($this->cssFiles)) {
1449 foreach ($this->cssFiles as $file => $properties) {
1450 $file = t3lib_div::resolveBackPath($file);
1451 $file = t3lib_div::createVersionNumberedFilename($file);
1452 $tag = '<link rel="' . htmlspecialchars($properties['rel']) . '" type="text/css" href="' .
1453 htmlspecialchars($file) . '" media="' . htmlspecialchars($properties['media']) . '"' .
1454 ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '') .
1455 $endingSlash . '>';
1456 if ($properties['allWrap'] && strpos($properties['allWrap'], '|') !== FALSE) {
1457 $tag = str_replace('|', $tag, $properties['allWrap']);
1458 }
1459 if ($properties['forceOnTop']) {
1460 $cssFiles = $tag . LF . $cssFiles;
1461 } else {
1462 $cssFiles .= LF . $tag;
1463 }
1464 }
1465 }
1466
1467 if (count($this->cssInline)) {
1468 foreach ($this->cssInline as $name => $properties) {
1469 if ($properties['forceOnTop']) {
1470 $cssInline = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF . $cssInline;
1471 } else {
1472 $cssInline .= '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
1473 }
1474 }
1475 $cssInline = $this->inlineCssWrap[0] . $cssInline . $this->inlineCssWrap[1];
1476 }
1477
1478 if (count($this->jsLibs)) {
1479 foreach ($this->jsLibs as $name => $properties) {
1480 $properties['file'] = t3lib_div::resolveBackPath($properties['file']);
1481 $properties['file'] = t3lib_div::createVersionNumberedFilename($properties['file']);
1482 $tag = '<script src="' . htmlspecialchars($properties['file']) . '" type="' . htmlspecialchars($properties['type']) . '"></script>';
1483 if ($properties['allWrap'] && strpos($properties['allWrap'], '|') !== FALSE) {
1484 $tag = str_replace('|', $tag, $properties['allWrap']);
1485 }
1486 if ($properties['forceOnTop']) {
1487 if ($properties['section'] === self::PART_HEADER) {
1488 $jsLibs = $tag . LF . $jsLibs;
1489 } else {
1490 $jsFooterLibs = $tag . LF . $jsFooterLibs;
1491 }
1492 } else {
1493 if ($properties['section'] === self::PART_HEADER) {
1494 $jsLibs .= LF . $tag;
1495 } else {
1496 $jsFooterLibs .= LF . $tag;
1497 }
1498 }
1499 }
1500 }
1501
1502 if (count($this->jsFiles)) {
1503 foreach ($this->jsFiles as $file => $properties) {
1504 $file = t3lib_div::resolveBackPath($file);
1505 $file = t3lib_div::createVersionNumberedFilename($file);
1506 $tag = '<script src="' . htmlspecialchars($file) . '" type="' . htmlspecialchars($properties['type']) . '"></script>';
1507 if ($properties['allWrap'] && strpos($properties['allWrap'], '|') !== FALSE) {
1508 $tag = str_replace('|', $tag, $properties['allWrap']);
1509 }
1510 if ($properties['forceOnTop']) {
1511 if ($properties['section'] === self::PART_HEADER) {
1512 $jsFiles = $tag . LF . $jsFiles;
1513 } else {
1514 $jsFooterFiles = $tag . LF . $jsFooterFiles;
1515 }
1516 } else {
1517 if ($properties['section'] === self::PART_HEADER) {
1518 $jsFiles .= LF . $tag;
1519 } else {
1520 $jsFooterFiles .= LF . $tag;
1521 }
1522 }
1523 }
1524 }
1525
1526 if (count($this->jsInline)) {
1527 foreach ($this->jsInline as $name => $properties) {
1528 if ($properties['forceOnTop']) {
1529 if ($properties['section'] === self::PART_HEADER) {
1530 $jsInline = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF . $jsInline;
1531 } else {
1532 $jsFooterInline = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF . $jsFooterInline;
1533 }
1534 } else {
1535 if ($properties['section'] === self::PART_HEADER) {
1536 $jsInline .= '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
1537 } else {
1538 $jsFooterInline .= '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
1539 }
1540 }
1541 }
1542 }
1543
1544
1545 if ($jsInline) {
1546 $jsInline = $this->inlineJavascriptWrap[0] . $jsInline . $this->inlineJavascriptWrap[1];
1547 }
1548
1549 if ($jsFooterInline) {
1550 $jsFooterInline = $this->inlineJavascriptWrap[0] . $jsFooterInline . $this->inlineJavascriptWrap[1];
1551 }
1552
1553
1554 // get template
1555 $templateFile = t3lib_div::getFileAbsFileName($this->templateFile, TRUE);
1556 $template = t3lib_div::getUrl($templateFile);
1557
1558 if ($this->removeLineBreaksFromTemplate) {
1559 $template = strtr($template, array(LF => '', CR => ''));
1560 }
1561 if ($part != self::PART_COMPLETE) {
1562 $templatePart = explode('###BODY###', $template);
1563 $template = $templatePart[$part - 1];
1564 }
1565
1566 if ($this->moveJsFromHeaderToFooter) {
1567 $jsFooterLibs = $jsLibs . LF . $jsFooterLibs;
1568 $jsLibs = '';
1569 $jsFooterFiles = $jsFiles . LF . $jsFooterFiles;
1570 $jsFiles = '';
1571 $jsFooterInline = $jsInline . LF . $jsFooterInline;
1572 $jsInline = '';
1573 }
1574
1575 // postRenderHook for possible manipulation
1576 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'])) {
1577 $params = array (
1578 'jsLibs' => &$jsLibs,
1579 'jsFiles' => &$jsFiles,
1580 'jsFooterFiles' => &$jsFooterFiles,
1581 'cssFiles' => &$cssFiles,
1582 'headerData' => &$this->headerData,
1583 'footerData' => &$this->footerData,
1584 'jsInline' => &$jsInline,
1585 'cssInline' => &$cssInline,
1586 'xmlPrologAndDocType' => &$this->xmlPrologAndDocType,
1587 'htmlTag' => &$this->htmlTag,
1588 'headTag' => &$this->headTag,
1589 'charSet' => &$this->charSet,
1590 'metaCharsetTag' => &$this->metaCharsetTag,
1591 'shortcutTag' => &$this->shortcutTag,
1592 'inlineComments' => &$this->inlineComments,
1593 'baseUrl' => &$this->baseUrl,
1594 'baseUrlTag' => &$this->baseUrlTag,
1595 'favIcon' => &$this->favIcon,
1596 'iconMimeType' => &$this->iconMimeType,
1597 'titleTag' => &$this->titleTag,
1598 'title' => &$this->title,
1599 'metaTags' => &$metaTags,
1600 'jsFooterInline' => &$jsFooterInline,
1601 'jsFooterLibs' => &$jsFooterLibs,
1602 'bodyContent' => &$this->bodyContent,
1603 );
1604 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'] as $hook) {
1605 t3lib_div::callUserFunction($hook, $params, $this);
1606 }
1607 }
1608
1609 $markerArray = array(
1610 'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
1611 'HTMLTAG' => $this->htmlTag,
1612 'HEADTAG' => $this->headTag,
1613 'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
1614 'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
1615 'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
1616 'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
1617 'CSS_INCLUDE' => $cssFiles,
1618 'CSS_INLINE' => $cssInline,
1619 'JS_INLINE' => $jsInline,
1620 'JS_INCLUDE' => $jsFiles,
1621 'JS_LIBS' => $jsLibs,
1622 'TITLE' => $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '',
1623 'META' => $metaTags,
1624 'HEADERDATA' => $this->headerData ? implode(LF, $this->headerData) : '',
1625 'FOOTERDATA' => $this->footerData ? implode(LF, $this->footerData) : '',
1626 'JS_LIBS_FOOTER' => $jsFooterLibs,
1627 'JS_INCLUDE_FOOTER' => $jsFooterFiles,
1628 'JS_INLINE_FOOTER' => $jsFooterInline,
1629 'BODY' => $this->bodyContent,
1630 );
1631
1632 $markerArray = array_map('trim', $markerArray);
1633
1634 $this->reset();
1635 return trim(t3lib_parsehtml::substituteMarkerArray($template, $markerArray, '###|###'));
1636 }
1637
1638 /**
1639 * helper function for render the javascript libraries
1640 *
1641 * @return string content with javascript libraries
1642 */
1643 protected function renderJsLibraries() {
1644 $out = '';
1645
1646 if ($this->addSvg) {
1647 $out .= '<script src="' . $this->processJsFile($this->backPath . $this->svgPath . 'svg.js') .
1648 '" data-path="' . $this->backPath . $this->svgPath .
1649 '"' . ($this->enableSvgDebug ? ' data-debug="true"' : '') . '></script>';
1650 }
1651
1652 if ($this->addPrototype) {
1653 $out .= '<script src="' . $this->processJsFile($this->backPath . $this->prototypePath . 'prototype.js') .
1654 '" type="text/javascript"></script>' . LF;
1655 unset($this->jsFiles[$this->backPath . $this->prototypePath . 'prototype.js']);
1656 }
1657
1658 if ($this->addScriptaculous) {
1659 $mods = array();
1660 foreach ($this->addScriptaculousModules as $key => $value) {
1661 if ($this->addScriptaculousModules[$key]) {
1662 $mods[] = $key;
1663 }
1664 }
1665 // resolve dependencies
1666 if (in_array('dragdrop', $mods) || in_array('controls', $mods)) {
1667 $mods = array_merge(array('effects'), $mods);
1668 }
1669
1670 if (count($mods)) {
1671 foreach ($mods as $module) {
1672 $out .= '<script src="' . $this->processJsFile($this->backPath .
1673 $this->scriptaculousPath . $module . '.js') . '" type="text/javascript"></script>' . LF;
1674 unset($this->jsFiles[$this->backPath . $this->scriptaculousPath . $module . '.js']);
1675 }
1676 }
1677 $out .= '<script src="' . $this->processJsFile($this->backPath . $this->scriptaculousPath .
1678 'scriptaculous.js') . '" type="text/javascript"></script>' . LF;
1679 unset($this->jsFiles[$this->backPath . $this->scriptaculousPath . 'scriptaculous.js']);
1680 }
1681
1682 // include extCore, but only if ExtJS is not included
1683 if ($this->addExtCore && !$this->addExtJS) {
1684 $out .= '<script src="' . $this->processJsFile($this->backPath .
1685 $this->extCorePath . 'ext-core' . ($this->enableExtCoreDebug ? '-debug' : '') . '.js') .
1686 '" type="text/javascript"></script>' . LF;
1687 unset($this->jsFiles[$this->backPath . $this->extCorePath . 'ext-core' . ($this->enableExtCoreDebug ? '-debug' : '') . '.js']);
1688 }
1689
1690 // include extJS
1691 if ($this->addExtJS) {
1692 // use the base adapter all the time
1693 $out .= '<script src="' . $this->processJsFile($this->backPath . $this->extJsPath .
1694 'adapter/' . ($this->enableExtJsDebug ?
1695 str_replace('.js', '-debug.js', $this->extJSadapter) : $this->extJSadapter)) .
1696 '" type="text/javascript"></script>' . LF;
1697 $out .= '<script src="' . $this->processJsFile($this->backPath . $this->extJsPath .
1698 'ext-all' . ($this->enableExtJsDebug ? '-debug' : '') . '.js') .
1699 '" type="text/javascript"></script>' . LF;
1700
1701 // add extJS localization
1702 $localeMap = $this->csConvObj->isoArray; // load standard ISO mapping and modify for use with ExtJS
1703 $localeMap[''] = 'en';
1704 $localeMap['default'] = 'en';
1705 $localeMap['gr'] = 'el_GR'; // Greek
1706 $localeMap['no'] = 'no_BO'; // Norwegian Bokmaal
1707 $localeMap['se'] = 'se_SV'; // Swedish
1708
1709
1710 $extJsLang = isset($localeMap[$this->lang]) ? $localeMap[$this->lang] : $this->lang;
1711 // TODO autoconvert file from UTF8 to current BE charset if necessary!!!!
1712 $extJsLocaleFile = $this->extJsPath . 'locale/ext-lang-' . $extJsLang . '.js';
1713 if (file_exists(PATH_typo3 . $extJsLocaleFile)) {
1714 $out .= '<script src="' . $this->processJsFile($this->backPath .
1715 $extJsLocaleFile) . '" type="text/javascript" charset="utf-8"></script>' . LF;
1716 }
1717
1718
1719 // remove extjs from JScodeLibArray
1720 unset(
1721 $this->jsFiles[$this->backPath . $this->extJsPath . 'ext-all.js'],
1722 $this->jsFiles[$this->backPath . $this->extJsPath . 'ext-all-debug.js']
1723 );
1724 }
1725
1726 if (count($this->inlineLanguageLabelFiles)) {
1727 foreach ($this->inlineLanguageLabelFiles as $languageLabelFile) {
1728 $this->includeLanguageFileForInline(
1729 $languageLabelFile['fileRef'],
1730 $languageLabelFile['selectionPrefix'],
1731 $languageLabelFile['stripFromSelectionName'],
1732 $languageLabelFile['$errorMode']
1733 );
1734 }
1735 }
1736 unset($this->inlineLanguageLabelFiles);
1737
1738 // Convert labels/settings back to UTF-8 since json_encode() only works with UTF-8:
1739 if ($this->getCharSet() !== 'utf-8') {
1740 if ($this->inlineLanguageLabels) {
1741 $this->csConvObj->convArray($this->inlineLanguageLabels, $this->getCharSet(), 'utf-8');
1742 }
1743 if ($this->inlineSettings) {
1744 $this->csConvObj->convArray($this->inlineSettings, $this->getCharSet(), 'utf-8');
1745 }
1746 }
1747
1748 $inlineSettings = $this->inlineLanguageLabels ? 'TYPO3.lang = ' . json_encode($this->inlineLanguageLabels) . ';' : '';
1749 $inlineSettings .= $this->inlineSettings ? 'TYPO3.settings = ' . json_encode($this->inlineSettings) . ';' : '';
1750
1751 if ($this->addExtCore || $this->addExtJS) {
1752 // set clear.gif, move it on top, add handler code
1753 $code = '';
1754 if (count($this->extOnReadyCode)) {
1755 foreach ($this->extOnReadyCode as $block) {
1756 $code .= $block;
1757 }
1758 }
1759
1760 $out .= $this->inlineJavascriptWrap[0] . '
1761 Ext.ns("TYPO3");
1762 Ext.BLANK_IMAGE_URL = "' . htmlspecialchars(t3lib_div::locationHeaderUrl($this->backPath . 'gfx/clear.gif')) . '";' . LF .
1763 $inlineSettings .
1764 'Ext.onReady(function() {' .
1765 ($this->enableExtJSQuickTips ? 'Ext.QuickTips.init();' . LF : '') . $code .
1766 ' });' . $this->inlineJavascriptWrap[1];
1767 unset ($this->extOnReadyCode);
1768
1769 // Include TYPO3.l10n object
1770 if (TYPO3_MODE === 'BE') {
1771 $out .= '<script src="' . $this->processJsFile($this->backPath . 'sysext/lang/res/js/be/typo3lang.js') . '" type="text/javascript" charset="utf-8"></script>' . LF;
1772 }
1773
1774 if ($this->extJStheme) {
1775 if (isset($GLOBALS['TBE_STYLES']['extJS']['theme'])) {
1776 $this->addCssFile($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['theme'], 'stylesheet', 'all', '', TRUE, TRUE);
1777 } else {
1778 $this->addCssFile($this->backPath . $this->extJsPath . 'resources/css/xtheme-blue.css', 'stylesheet', 'all', '', TRUE, TRUE);
1779 }
1780 }
1781 if ($this->extJScss) {
1782 if (isset($GLOBALS['TBE_STYLES']['extJS']['all'])) {
1783 $this->addCssFile($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['all'], 'stylesheet', 'all', '', TRUE, TRUE);
1784 } else {
1785 $this->addCssFile($this->backPath . $this->extJsPath . 'resources/css/ext-all-notheme.css', 'stylesheet', 'all', '', TRUE, TRUE);
1786 }
1787 }
1788 } else {
1789 if ($inlineSettings) {
1790 $out .= $this->inlineJavascriptWrap[0] . $inlineSettings . $this->inlineJavascriptWrap[1];
1791 }
1792 }
1793
1794 return $out;
1795 }
1796
1797 protected function includeLanguageFileForInline($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0) {
1798 if (!isset($this->lang) || !isset($this->charSet)) {
1799 throw new RuntimeException('Language and character encoding are not set.', 1284906026);
1800 }
1801
1802 $labelsFromFile = array();
1803 $allLabels = t3lib_div::readLLfile($fileRef, $this->lang, $this->charSet, $errorMode);
1804
1805 // Regular expression to strip the selection prefix and possibly something from the label name:
1806 $labelPattern = '#^' . preg_quote($selectionPrefix, '#') . '(' . preg_quote($stripFromSelectionName, '#') . ')?#';
1807
1808 if ($allLabels !== FALSE) {
1809 // Merge language specific translations:
1810 if ($this->lang !== 'default' && isset($allLabels[$this->lang])) {
1811 $labels = array_merge($allLabels['default'], $allLabels[$this->lang]);
1812 } else {
1813 $labels = $allLabels['default'];
1814 }
1815
1816 // Iterate through all locallang labels:
1817 foreach ($labels as $label => $value) {
1818 if ($selectionPrefix === '') {
1819 $labelsFromFile[$label] = $value;
1820 } elseif (strpos($label, $selectionPrefix) === 0) {
1821 $key = preg_replace($labelPattern, '', $label);
1822 $labelsFromFile[$label] = $value;
1823 }
1824 }
1825
1826 $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $labelsFromFile);
1827 }
1828 }
1829
1830 /*****************************************************/
1831 /* */
1832 /* Tools */
1833 /* */
1834 /* */
1835 /*****************************************************/
1836
1837 /**
1838 * concatenate files into one file
1839 * registered handler
1840 *
1841 * @return void
1842 */
1843 protected function doConcatenate() {
1844 // traverse the arrays, concatenate in one file
1845 // then remove concatenated files from array and add the concatenated file
1846
1847 if ($this->concatenateFiles) {
1848 $params = array(
1849 'jsLibs' => &$this->jsLibs,
1850 'jsFiles' => &$this->jsFiles,
1851 'jsFooterFiles' => &$this->jsFooterFiles,
1852 'cssFiles' => &$this->cssFiles,
1853 'headerData' => &$this->headerData,
1854 'footerData' => &$this->footerData,
1855 );
1856
1857 if ($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['concatenateHandler']) {
1858 // use extern concatenate routine
1859 t3lib_div::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['concatenateHandler'], $params, $this);
1860 } elseif (TYPO3_MODE === 'BE') {
1861 $cssOptions = array('baseDirectories' => $GLOBALS['TBE_TEMPLATE']->getSkinStylesheetDirectories());
1862 $this->cssFiles = $this->getCompressor()->concatenateCssFiles($this->cssFiles, $cssOptions);
1863 }
1864 }
1865 }
1866
1867 /**
1868 * compress inline code
1869 *
1870 * @return void
1871 */
1872 protected function doCompress() {
1873
1874 if ($this->compressJavascript && $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler']) {
1875 // use extern compress routine
1876 $params = array(
1877 'jsInline' => &$this->jsInline,
1878 'jsFooterInline' => &$this->jsFooterInline,
1879 'jsLibs' => &$this->jsLibs,
1880 'jsFiles' => &$this->jsFiles,
1881 'jsFooterFiles' => &$this->jsFooterFiles,
1882 'headerData' => &$this->headerData,
1883 'footerData' => &$this->footerData,
1884 );
1885 t3lib_div::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'], $params, $this);
1886 } else {
1887 // traverse the arrays, compress files
1888
1889 if ($this->compressJavascript) {
1890 if (count($this->jsInline)) {
1891 foreach ($this->jsInline as $name => $properties) {
1892 if ($properties['compress']) {
1893 $error = '';
1894 $this->jsInline[$name]['code'] = t3lib_div::minifyJavaScript($properties['code'], $error);
1895 if ($error) {
1896 $this->compressError .= 'Error with minify JS Inline Block "' . $name . '": ' . $error . LF;
1897 }
1898 }
1899 }
1900 }
1901 if (TYPO3_MODE === 'BE') {
1902 $this->jsFiles = $this->getCompressor()->compressJsFiles($this->jsFiles);
1903 $this->jsFooterFiles = $this->getCompressor()->compressJsFiles($this->jsFooterFiles);
1904 }
1905 }
1906 }
1907 if ($this->compressCss) {
1908 // use extern compress routine
1909 $params = array(
1910 'cssInline' => &$this->cssInline,
1911 'cssFiles' => &$this->cssFiles,
1912 'headerData' => &$this->headerData,
1913 'footerData' => &$this->footerData,
1914 );
1915
1916 if ($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler']) {
1917 // use extern concatenate routine
1918 t3lib_div::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'], $params, $this);
1919 } elseif (TYPO3_MODE === 'BE') {
1920 $this->cssFiles = $this->getCompressor()->compressCssFiles($this->cssFiles);
1921 }
1922 }
1923 }
1924
1925 /**
1926 * Returns instance of t3lib_Compressor
1927 *
1928 * @return t3lib_Compressor Instance of t3lib_Compressor
1929 */
1930 protected function getCompressor() {
1931 if ($this->compressor === NULL) {
1932 $this->compressor = t3lib_div::makeInstance('t3lib_Compressor');
1933 }
1934 return $this->compressor;
1935 }
1936
1937 /**
1938 * Processes a Javascript file dependent on the current context
1939 *
1940 * Adds the version number for Frontend, compresses the file for Backend
1941 *
1942 * @param string $filename Filename
1943 * @return string new filename
1944 */
1945 protected function processJsFile($filename) {
1946 switch (TYPO3_MODE) {
1947 case 'FE':
1948 $filename = t3lib_div::createVersionNumberedFilename($filename);
1949 break;
1950 case 'BE':
1951 if ($this->compressJavascript) {
1952 $filename = $this->getCompressor()->compressJsFile($filename);
1953 }
1954 break;
1955 }
1956 return $filename;
1957 }
1958
1959 }
1960
1961 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_pagerenderer.php'])) {
1962 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_pagerenderer.php']);
1963 }
1964 ?>