fcbb213aa048abaddd373e8391e379dfa4fb8471
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Page / PageRenderer.php
1 <?php
2 namespace TYPO3\CMS\Core\Page;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2009-2013 Steffen Kamper <info@sk-typo3.de>
8 * (c) 2011-2013 Kai Vogel <kai.vogel@speedprogs.de>
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the textfile GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30
31 use TYPO3\CMS\Core\Utility\GeneralUtility;
32
33 /**
34 * TYPO3 pageRender class (new in TYPO3 4.3.0)
35 * This class render the HTML of a webpage, usable for BE and FE
36 *
37 * @author Steffen Kamper <info@sk-typo3.de>
38 * @author Kai Vogel <kai.vogel@speedprogs.de>
39 */
40 class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
41
42 // Constants for the part to be rendered
43 const PART_COMPLETE = 0;
44 const PART_HEADER = 1;
45 const PART_FOOTER = 2;
46 // Available adapters for extJs
47 const EXTJS_ADAPTER_JQUERY = 'jquery';
48 const EXTJS_ADAPTER_PROTOTYPE = 'prototype';
49 const EXTJS_ADAPTER_YUI = 'yui';
50 // jQuery Core version that is shipped with TYPO3
51 const JQUERY_VERSION_LATEST = '1.9.1';
52 // jQuery namespace options
53 const JQUERY_NAMESPACE_NONE = 'none';
54 const JQUERY_NAMESPACE_DEFAULT = 'jQuery';
55 const JQUERY_NAMESPACE_DEFAULT_NOCONFLICT = 'defaultNoConflict';
56 /**
57 * @var boolean
58 */
59 protected $compressJavascript = FALSE;
60
61 /**
62 * @var boolean
63 */
64 protected $compressCss = FALSE;
65
66 /**
67 * @var boolean
68 */
69 protected $removeLineBreaksFromTemplate = FALSE;
70
71 /**
72 * @var boolean
73 */
74 protected $concatenateFiles = FALSE;
75
76 /**
77 * @var boolean
78 */
79 protected $concatenateJavascript = FALSE;
80
81 /**
82 * @var boolean
83 */
84 protected $concatenateCss = FALSE;
85
86 /**
87 * @var boolean
88 */
89 protected $moveJsFromHeaderToFooter = FALSE;
90
91 /**
92 * @var \TYPO3\CMS\Core\Charset\CharsetConverter
93 */
94 protected $csConvObj;
95
96 /**
97 * @var \TYPO3\CMS\Core\Localization\Locales
98 */
99 protected $locales;
100
101 /**
102 * The language key
103 * Two character string or 'default'
104 *
105 * @var string
106 */
107 protected $lang;
108
109 /**
110 * List of language dependencies for actual language. This is used for local variants of a language
111 * that depend on their "main" language, like Brazilian Portuguese or Canadian French.
112 *
113 * @var array
114 */
115 protected $languageDependencies = array();
116
117 /**
118 * @var \TYPO3\CMS\Core\Resource\ResourceCompressor
119 */
120 protected $compressor;
121
122 // Arrays containing associative array for the included files
123 /**
124 * @var array
125 */
126 protected $jsFiles = array();
127
128 /**
129 * @var array
130 */
131 protected $jsFooterFiles = array();
132
133 /**
134 * @var array
135 */
136 protected $jsLibs = array();
137
138 /**
139 * @var array
140 */
141 protected $jsFooterLibs = array();
142
143 /**
144 * @var array
145 */
146 protected $cssFiles = array();
147
148 /**
149 * The title of the page
150 *
151 * @var string
152 */
153 protected $title;
154
155 /**
156 * Charset for the rendering
157 *
158 * @var string
159 */
160 protected $charSet;
161
162 /**
163 * @var string
164 */
165 protected $favIcon;
166
167 /**
168 * @var string
169 */
170 protected $baseUrl;
171
172 /**
173 * @var boolean
174 */
175 protected $renderXhtml = TRUE;
176
177 // Static header blocks
178 /**
179 * @var string
180 */
181 protected $xmlPrologAndDocType = '';
182
183 /**
184 * @var array
185 */
186 protected $metaTags = array();
187
188 /**
189 * @var array
190 */
191 protected $inlineComments = array();
192
193 /**
194 * @var array
195 */
196 protected $headerData = array();
197
198 /**
199 * @var array
200 */
201 protected $footerData = array();
202
203 /**
204 * @var string
205 */
206 protected $titleTag = '<title>|</title>';
207
208 /**
209 * @var string
210 */
211 protected $metaCharsetTag = '<meta http-equiv="Content-Type" content="text/html; charset=|" />';
212
213 /**
214 * @var string
215 */
216 protected $htmlTag = '<html>';
217
218 /**
219 * @var string
220 */
221 protected $headTag = '<head>';
222
223 /**
224 * @var string
225 */
226 protected $baseUrlTag = '<base href="|" />';
227
228 /**
229 * @var string
230 */
231 protected $iconMimeType = '';
232
233 /**
234 * @var string
235 */
236 protected $shortcutTag = '<link rel="shortcut icon" href="%1$s"%2$s />
237 <link rel="icon" href="%1$s"%2$s />';
238
239 // Static inline code blocks
240 /**
241 * @var array
242 */
243 protected $jsInline = array();
244
245 /**
246 * @var array
247 */
248 protected $jsFooterInline = array();
249
250 /**
251 * @var array
252 */
253 protected $extOnReadyCode = array();
254
255 /**
256 * @var array
257 */
258 protected $cssInline = array();
259
260 /**
261 * @var string
262 */
263 protected $bodyContent;
264
265 /**
266 * @var string
267 */
268 protected $templateFile;
269
270 /**
271 * @var array
272 */
273 protected $jsLibraryNames = array('prototype', 'scriptaculous', 'extjs');
274
275 // Paths to contibuted libraries
276
277 /**
278 * default path to the requireJS library, relative to the typo3/ directory
279 * @var string
280 */
281 protected $requireJsPath = 'contrib/requirejs/';
282
283 /**
284 * @var string
285 */
286 protected $prototypePath = 'contrib/prototype/';
287
288 /**
289 * @var string
290 */
291 protected $scriptaculousPath = 'contrib/scriptaculous/';
292
293 /**
294 * @var string
295 */
296 protected $extCorePath = 'contrib/extjs/';
297
298 /**
299 * @var string
300 */
301 protected $extJsPath = 'contrib/extjs/';
302
303 /**
304 * @var string
305 */
306 protected $svgPath = 'contrib/websvg/';
307
308 /**
309 * The local directory where one can find jQuery versions and plugins
310 *
311 * @var string
312 */
313 protected $jQueryPath = 'contrib/jquery/';
314
315 // Internal flags for JS-libraries
316 /**
317 * This array holds all jQuery versions that should be included in the
318 * current page.
319 * Each version is described by "source", "version" and "namespace"
320 *
321 * The namespace of every particular version is the key
322 * of that array, because only one version per namespace can exist.
323 *
324 * The type "source" describes where the jQuery core should be included from
325 * currently, TYPO3 supports "local" (make use of jQuery path), "google",
326 * "jquery" and "msn".
327 * Currently there are downsides to "local" and "jquery", as "local" only
328 * supports the latest/shipped jQuery core out of the box, and
329 * "jquery" does not have SSL support.
330 *
331 * @var array
332 */
333 protected $jQueryVersions = array();
334
335 /**
336 * Array of jQuery version numbers shipped with the core
337 *
338 * @var array
339 */
340 protected $availableLocalJqueryVersions = array(
341 '1.8.2', // jquery version shipped with TYPO3 6.0, still available in the contrib/ directory
342 self::JQUERY_VERSION_LATEST
343 );
344
345 /**
346 * Array of jQuery CDNs with placeholders
347 *
348 * @var array
349 */
350 protected $jQueryCdnUrls = array(
351 'google' => '//ajax.googleapis.com/ajax/libs/jquery/%1$s/jquery%2$s.js',
352 'msn' => '//ajax.aspnetcdn.com/ajax/jQuery/jquery-%1$s%2$s.js',
353 'jquery' => 'http://code.jquery.com/jquery-%1$s%2$s.js'
354 );
355
356 /**
357 * if set, the requireJS library is included
358 * @var boolean
359 */
360 protected $addRequireJs = FALSE;
361
362 /**
363 * inline configuration for requireJS
364 * @var array
365 */
366 protected $requireJsConfig = array();
367
368 /**
369 * @var boolean
370 */
371 protected $addPrototype = FALSE;
372
373 /**
374 * @var boolean
375 */
376 protected $addScriptaculous = FALSE;
377
378 /**
379 * @var array
380 */
381 protected $addScriptaculousModules = array('builder' => FALSE, 'effects' => FALSE, 'dragdrop' => FALSE, 'controls' => FALSE, 'slider' => FALSE);
382
383 /**
384 * @var boolean
385 */
386 protected $addExtJS = FALSE;
387
388 /**
389 * @var boolean
390 */
391 protected $addExtCore = FALSE;
392
393 /**
394 * @var string
395 */
396 protected $extJSadapter = 'ext/ext-base.js';
397
398 /**
399 * @var boolean
400 */
401 protected $extDirectCodeAdded = FALSE;
402
403 /**
404 * @var boolean
405 */
406 protected $enableExtJsDebug = FALSE;
407
408 /**
409 * @var boolean
410 */
411 protected $enableExtCoreDebug = FALSE;
412
413 /**
414 * @var boolean
415 */
416 protected $enableJqueryDebug = FALSE;
417
418 /**
419 * @var boolean
420 */
421 protected $extJStheme = TRUE;
422
423 /**
424 * @var boolean
425 */
426 protected $extJScss = TRUE;
427
428 /**
429 * @var boolean
430 */
431 protected $enableExtJSQuickTips = FALSE;
432
433 /**
434 * @var array
435 */
436 protected $inlineLanguageLabels = array();
437
438 /**
439 * @var array
440 */
441 protected $inlineLanguageLabelFiles = array();
442
443 /**
444 * @var array
445 */
446 protected $inlineSettings = array();
447
448 /**
449 * @var array
450 */
451 protected $inlineJavascriptWrap = array();
452
453 /**
454 * Saves error messages generated during compression
455 *
456 * @var string
457 */
458 protected $compressError = '';
459
460 /**
461 * Is empty string for HTML and ' /' for XHTML rendering
462 *
463 * @var string
464 */
465 protected $endingSlash = '';
466
467 /**
468 * SVG library
469 *
470 * @var boolean
471 */
472 protected $addSvg = FALSE;
473
474 /**
475 * @var boolean
476 */
477 protected $enableSvgDebug = FALSE;
478
479 /**
480 * Used by BE modules
481 *
482 * @var null|string
483 */
484 public $backPath;
485
486 /**
487 * @param string $templateFile Declare the used template file. Omit this parameter will use default template
488 * @param string $backPath Relative path to typo3-folder. It varies for BE modules, in FE it will be typo3/
489 */
490 public function __construct($templateFile = '', $backPath = NULL) {
491 $this->reset();
492 $this->csConvObj = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Charset\\CharsetConverter');
493 $this->locales = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Localization\\Locales');
494 if (strlen($templateFile)) {
495 $this->templateFile = $templateFile;
496 }
497 $this->backPath = isset($backPath) ? $backPath : $GLOBALS['BACK_PATH'];
498 $this->inlineJavascriptWrap = array(
499 '<script type="text/javascript">' . LF . '/*<![CDATA[*/' . LF . '<!-- ' . LF,
500 '// -->' . LF . '/*]]>*/' . LF . '</script>' . LF
501 );
502 $this->inlineCssWrap = array(
503 '<style type="text/css">' . LF . '/*<![CDATA[*/' . LF . '<!-- ' . LF,
504 '-->' . LF . '/*]]>*/' . LF . '</style>' . LF
505 );
506 }
507
508 /**
509 * Reset all vars to initial values
510 *
511 * @return void
512 */
513 protected function reset() {
514 $this->templateFile = 'EXT:core/Resources/Private/Templates/PageRenderer.html';
515 $this->jsFiles = array();
516 $this->jsFooterFiles = array();
517 $this->jsInline = array();
518 $this->jsFooterInline = array();
519 $this->jsLibs = array();
520 $this->cssFiles = array();
521 $this->cssInline = array();
522 $this->metaTags = array();
523 $this->inlineComments = array();
524 $this->headerData = array();
525 $this->footerData = array();
526 $this->extOnReadyCode = array();
527 $this->jQueryVersions = array();
528 }
529
530 /*****************************************************/
531 /* */
532 /* Public Setters */
533 /* */
534 /* */
535 /*****************************************************/
536 /**
537 * Sets the title
538 *
539 * @param string $title title of webpage
540 * @return void
541 */
542 public function setTitle($title) {
543 $this->title = $title;
544 }
545
546 /**
547 * Enables/disables rendering of XHTML code
548 *
549 * @param boolean $enable Enable XHTML
550 * @return void
551 */
552 public function setRenderXhtml($enable) {
553 $this->renderXhtml = $enable;
554 }
555
556 /**
557 * Sets xml prolog and docType
558 *
559 * @param string $xmlPrologAndDocType Complete tags for xml prolog and docType
560 * @return void
561 */
562 public function setXmlPrologAndDocType($xmlPrologAndDocType) {
563 $this->xmlPrologAndDocType = $xmlPrologAndDocType;
564 }
565
566 /**
567 * Sets meta charset
568 *
569 * @param string $charSet Used charset
570 * @return void
571 */
572 public function setCharSet($charSet) {
573 $this->charSet = $charSet;
574 }
575
576 /**
577 * Sets language
578 *
579 * @param string $lang Used language
580 * @return void
581 */
582 public function setLanguage($lang) {
583 $this->lang = $lang;
584 $this->languageDependencies = array();
585
586 // Language is found. Configure it:
587 if (in_array($this->lang, $this->locales->getLocales())) {
588 $this->languageDependencies[] = $this->lang;
589 foreach ($this->locales->getLocaleDependencies($this->lang) as $language) {
590 $this->languageDependencies[] = $language;
591 }
592 }
593 }
594
595 /**
596 * Set the meta charset tag
597 *
598 * @param string $metaCharsetTag
599 * @return void
600 */
601 public function setMetaCharsetTag($metaCharsetTag) {
602 $this->metaCharsetTag = $metaCharsetTag;
603 }
604
605 /**
606 * Sets html tag
607 *
608 * @param string $htmlTag Html tag
609 * @return void
610 */
611 public function setHtmlTag($htmlTag) {
612 $this->htmlTag = $htmlTag;
613 }
614
615 /**
616 * Sets HTML head tag
617 *
618 * @param string $headTag HTML head tag
619 * @return void
620 */
621 public function setHeadTag($headTag) {
622 $this->headTag = $headTag;
623 }
624
625 /**
626 * Sets favicon
627 *
628 * @param string $favIcon
629 * @return void
630 */
631 public function setFavIcon($favIcon) {
632 $this->favIcon = $favIcon;
633 }
634
635 /**
636 * Sets icon mime type
637 *
638 * @param string $iconMimeType
639 * @return void
640 */
641 public function setIconMimeType($iconMimeType) {
642 $this->iconMimeType = $iconMimeType;
643 }
644
645 /**
646 * Sets HTML base URL
647 *
648 * @param string $baseUrl HTML base URL
649 * @return void
650 */
651 public function setBaseUrl($baseUrl) {
652 $this->baseUrl = $baseUrl;
653 }
654
655 /**
656 * Sets template file
657 *
658 * @param string $file
659 * @return void
660 */
661 public function setTemplateFile($file) {
662 $this->templateFile = $file;
663 }
664
665 /**
666 * Sets back path
667 *
668 * @param string $backPath
669 * @return void
670 */
671 public function setBackPath($backPath) {
672 $this->backPath = $backPath;
673 }
674
675 /**
676 * Sets Content for Body
677 *
678 * @param string $content
679 * @return void
680 */
681 public function setBodyContent($content) {
682 $this->bodyContent = $content;
683 }
684
685 /**
686 * Sets path to requireJS library (relative to typo3 directory)
687 *
688 * @param string $path Path to requireJS library
689 * @return void
690 */
691 public function setRequireJsPath($path) {
692 $this->requireJsPath = $path;
693 }
694
695 /**
696 * Sets path to prototype library (relative to typo3 directory)
697 *
698 * @param string $path Path to prototype library
699 * @return void
700 */
701 public function setPrototypePath($path) {
702 $this->prototypePath = $path;
703 }
704
705 /**
706 * Sets Path for scriptaculous library (relative to typo3 directory)
707 *
708 * @param string $path
709 * @return void
710 */
711 public function setScriptaculousPath($path) {
712 $this->scriptaculousPath = $path;
713 }
714
715 /**
716 * Sets Path for Ext Core library (relative to typo3 directory)
717 *
718 * @param string $path
719 * @return void
720 */
721 public function setExtCorePath($path) {
722 $this->extCorePath = $path;
723 }
724
725 /**
726 * Sets Path for ExtJs library (relative to typo3 directory)
727 *
728 * @param string $path
729 * @return void
730 */
731 public function setExtJsPath($path) {
732 $this->extJsPath = $path;
733 }
734
735 /**
736 * Sets Path for SVG library (websvg)
737 *
738 * @param string $path
739 * @return void
740 */
741 public function setSvgPath($path) {
742 $this->svgPath = $path;
743 }
744
745 /*****************************************************/
746 /* */
747 /* Public Enablers / Disablers */
748 /* */
749 /* */
750 /*****************************************************/
751 /**
752 * Enables MoveJsFromHeaderToFooter
753 *
754 * @return void
755 */
756 public function enableMoveJsFromHeaderToFooter() {
757 $this->moveJsFromHeaderToFooter = TRUE;
758 }
759
760 /**
761 * Disables MoveJsFromHeaderToFooter
762 *
763 * @return void
764 */
765 public function disableMoveJsFromHeaderToFooter() {
766 $this->moveJsFromHeaderToFooter = FALSE;
767 }
768
769 /**
770 * Enables compression of javascript
771 *
772 * @return void
773 */
774 public function enableCompressJavascript() {
775 $this->compressJavascript = TRUE;
776 }
777
778 /**
779 * Disables compression of javascript
780 *
781 * @return void
782 */
783 public function disableCompressJavascript() {
784 $this->compressJavascript = FALSE;
785 }
786
787 /**
788 * Enables compression of css
789 *
790 * @return void
791 */
792 public function enableCompressCss() {
793 $this->compressCss = TRUE;
794 }
795
796 /**
797 * Disables compression of css
798 *
799 * @return void
800 */
801 public function disableCompressCss() {
802 $this->compressCss = FALSE;
803 }
804
805 /**
806 * Enables concatenation of js and css files
807 *
808 * @return void
809 */
810 public function enableConcatenateFiles() {
811 $this->concatenateFiles = TRUE;
812 }
813
814 /**
815 * Disables concatenation of js and css files
816 *
817 * @return void
818 */
819 public function disableConcatenateFiles() {
820 $this->concatenateFiles = FALSE;
821 }
822
823 /**
824 * Enables concatenation of js files
825 *
826 * @return void
827 */
828 public function enableConcatenateJavascript() {
829 $this->concatenateJavascript = TRUE;
830 }
831
832 /**
833 * Disables concatenation of js files
834 *
835 * @return void
836 */
837 public function disableConcatenateJavascript() {
838 $this->concatenateJavascript = FALSE;
839 }
840
841 /**
842 * Enables concatenation of css files
843 *
844 * @return void
845 */
846 public function enableConcatenateCss() {
847 $this->concatenateCss = TRUE;
848 }
849
850 /**
851 * Disables concatenation of css files
852 *
853 * @return void
854 */
855 public function disableConcatenateCss() {
856 $this->concatenateCss = FALSE;
857 }
858
859 /**
860 * Sets removal of all line breaks in template
861 *
862 * @return void
863 */
864 public function enableRemoveLineBreaksFromTemplate() {
865 $this->removeLineBreaksFromTemplate = TRUE;
866 }
867
868 /**
869 * Unsets removal of all line breaks in template
870 *
871 * @return void
872 */
873 public function disableRemoveLineBreaksFromTemplate() {
874 $this->removeLineBreaksFromTemplate = FALSE;
875 }
876
877 /**
878 * Enables Debug Mode
879 * This is a shortcut to switch off all compress/concatenate features to enable easier debug
880 *
881 * @return void
882 */
883 public function enableDebugMode() {
884 $this->compressJavascript = FALSE;
885 $this->compressCss = FALSE;
886 $this->concatenateFiles = FALSE;
887 $this->removeLineBreaksFromTemplate = FALSE;
888 $this->enableExtCoreDebug = TRUE;
889 $this->enableExtJsDebug = TRUE;
890 $this->enableJqueryDebug = TRUE;
891 $this->enableSvgDebug = TRUE;
892 }
893
894 /*****************************************************/
895 /* */
896 /* Public Getters */
897 /* */
898 /* */
899 /*****************************************************/
900 /**
901 * Gets the title
902 *
903 * @return string $title Title of webpage
904 */
905 public function getTitle() {
906 return $this->title;
907 }
908
909 /**
910 * Gets the charSet
911 *
912 * @return string $charSet
913 */
914 public function getCharSet() {
915 return $this->charSet;
916 }
917
918 /**
919 * Gets the language
920 *
921 * @return string $lang
922 */
923 public function getLanguage() {
924 return $this->lang;
925 }
926
927 /**
928 * Returns rendering mode XHTML or HTML
929 *
930 * @return boolean TRUE if XHTML, FALSE if HTML
931 */
932 public function getRenderXhtml() {
933 return $this->renderXhtml;
934 }
935
936 /**
937 * Gets html tag
938 *
939 * @return string $htmlTag Html tag
940 */
941 public function getHtmlTag() {
942 return $this->htmlTag;
943 }
944
945 /**
946 * Get meta charset
947 *
948 * @return string
949 */
950 public function getMetaCharsetTag() {
951 return $this->metaCharsetTag;
952 }
953
954 /**
955 * Gets head tag
956 *
957 * @return string $tag Head tag
958 */
959 public function getHeadTag() {
960 return $this->headTag;
961 }
962
963 /**
964 * Gets favicon
965 *
966 * @return string $favIcon
967 */
968 public function getFavIcon() {
969 return $this->favIcon;
970 }
971
972 /**
973 * Gets icon mime type
974 *
975 * @return string $iconMimeType
976 */
977 public function getIconMimeType() {
978 return $this->iconMimeType;
979 }
980
981 /**
982 * Gets HTML base URL
983 *
984 * @return string $url
985 */
986 public function getBaseUrl() {
987 return $this->baseUrl;
988 }
989
990 /**
991 * Gets template file
992 *
993 * @return string
994 */
995 public function getTemplateFile() {
996 return $this->templateFile;
997 }
998
999 /**
1000 * Gets MoveJsFromHeaderToFooter
1001 *
1002 * @return boolean
1003 */
1004 public function getMoveJsFromHeaderToFooter() {
1005 return $this->moveJsFromHeaderToFooter;
1006 }
1007
1008 /**
1009 * Gets compress of javascript
1010 *
1011 * @return boolean
1012 */
1013 public function getCompressJavascript() {
1014 return $this->compressJavascript;
1015 }
1016
1017 /**
1018 * Gets compress of css
1019 *
1020 * @return boolean
1021 */
1022 public function getCompressCss() {
1023 return $this->compressCss;
1024 }
1025
1026 /**
1027 * Gets concatenate of js and css files
1028 *
1029 * @return boolean
1030 */
1031 public function getConcatenateFiles() {
1032 return $this->concatenateFiles;
1033 }
1034
1035 /**
1036 * Gets concatenate of js files
1037 *
1038 * @return boolean
1039 */
1040 public function getConcatenateJavascript() {
1041 return $this->concatenateJavascript;
1042 }
1043
1044 /**
1045 * Gets concatenate of css files
1046 *
1047 * @return boolean
1048 */
1049 public function getConcatenateCss() {
1050 return $this->concatenateCss;
1051 }
1052
1053 /**
1054 * Gets remove of empty lines from template
1055 *
1056 * @return boolean
1057 */
1058 public function getRemoveLineBreaksFromTemplate() {
1059 return $this->removeLineBreaksFromTemplate;
1060 }
1061
1062 /**
1063 * Gets content for body
1064 *
1065 * @return string
1066 */
1067 public function getBodyContent() {
1068 return $this->bodyContent;
1069 }
1070
1071 /**
1072 * Gets Path for prototype library (relative to typo3 directory)
1073 *
1074 * @return string
1075 */
1076 public function getPrototypePath() {
1077 return $this->prototypePath;
1078 }
1079
1080 /**
1081 * Gets Path for scriptaculous library (relative to typo3 directory)
1082 *
1083 * @return string
1084 */
1085 public function getScriptaculousPath() {
1086 return $this->scriptaculousPath;
1087 }
1088
1089 /**
1090 * Gets Path for Ext Core library (relative to typo3 directory)
1091 *
1092 * @return string
1093 */
1094 public function getExtCorePath() {
1095 return $this->extCorePath;
1096 }
1097
1098 /**
1099 * Gets Path for ExtJs library (relative to typo3 directory)
1100 *
1101 * @return string
1102 */
1103 public function getExtJsPath() {
1104 return $this->extJsPath;
1105 }
1106
1107 /**
1108 * Gets Path for SVG library (relative to typo3 directory)
1109 *
1110 * @return string
1111 */
1112 public function getSvgPath() {
1113 return $this->svgPath;
1114 }
1115
1116 /**
1117 * Gets the inline language labels.
1118 *
1119 * @return array The inline language labels
1120 */
1121 public function getInlineLanguageLabels() {
1122 return $this->inlineLanguageLabels;
1123 }
1124
1125 /**
1126 * Gets the inline language files
1127 *
1128 * @return array
1129 */
1130 public function getInlineLanguageLabelFiles() {
1131 return $this->inlineLanguageLabelFiles;
1132 }
1133
1134 /*****************************************************/
1135 /* */
1136 /* Public Functions to add Data */
1137 /* */
1138 /* */
1139 /*****************************************************/
1140 /**
1141 * Adds meta data
1142 *
1143 * @param string $meta Meta data (complete metatag)
1144 * @return void
1145 */
1146 public function addMetaTag($meta) {
1147 if (!in_array($meta, $this->metaTags)) {
1148 $this->metaTags[] = $meta;
1149 }
1150 }
1151
1152 /**
1153 * Adds inline HTML comment
1154 *
1155 * @param string $comment
1156 * @return void
1157 */
1158 public function addInlineComment($comment) {
1159 if (!in_array($comment, $this->inlineComments)) {
1160 $this->inlineComments[] = $comment;
1161 }
1162 }
1163
1164 /**
1165 * Adds header data
1166 *
1167 * @param string $data Free header data for HTML header
1168 * @return void
1169 */
1170 public function addHeaderData($data) {
1171 if (!in_array($data, $this->headerData)) {
1172 $this->headerData[] = $data;
1173 }
1174 }
1175
1176 /**
1177 * Adds footer data
1178 *
1179 * @param string $data Free header data for HTML header
1180 * @return void
1181 */
1182 public function addFooterData($data) {
1183 if (!in_array($data, $this->footerData)) {
1184 $this->footerData[] = $data;
1185 }
1186 }
1187
1188 /**
1189 * Adds JS Library. JS Library block is rendered on top of the JS files.
1190 *
1191 * @param string $name Arbitrary identifier
1192 * @param string $file File name
1193 * @param string $type Content Type
1194 * @param boolean $compress Flag if library should be compressed
1195 * @param boolean $forceOnTop Flag if added library should be inserted at begin of this block
1196 * @param string $allWrap
1197 * @param boolean $excludeFromConcatenation
1198 * @return void
1199 */
1200 public function addJsLibrary($name, $file, $type = 'text/javascript', $compress = FALSE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE) {
1201 if (!$type) {
1202 $type = 'text/javascript';
1203 }
1204 if (!in_array(strtolower($name), $this->jsLibs)) {
1205 $this->jsLibs[strtolower($name)] = array(
1206 'file' => $file,
1207 'type' => $type,
1208 'section' => self::PART_HEADER,
1209 'compress' => $compress,
1210 'forceOnTop' => $forceOnTop,
1211 'allWrap' => $allWrap,
1212 'excludeFromConcatenation' => $excludeFromConcatenation
1213 );
1214 }
1215 }
1216
1217 /**
1218 * Adds JS Library to Footer. JS Library block is rendered on top of the Footer JS files.
1219 *
1220 * @param string $name Arbitrary identifier
1221 * @param string $file File name
1222 * @param string $type Content Type
1223 * @param boolean $compress Flag if library should be compressed
1224 * @param boolean $forceOnTop Flag if added library should be inserted at begin of this block
1225 * @param string $allWrap
1226 * @param boolean $excludeFromConcatenation
1227 * @return void
1228 */
1229 public function addJsFooterLibrary($name, $file, $type = 'text/javascript', $compress = FALSE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE) {
1230 if (!$type) {
1231 $type = 'text/javascript';
1232 }
1233 if (!in_array(strtolower($name), $this->jsLibs)) {
1234 $this->jsLibs[strtolower($name)] = array(
1235 'file' => $file,
1236 'type' => $type,
1237 'section' => self::PART_FOOTER,
1238 'compress' => $compress,
1239 'forceOnTop' => $forceOnTop,
1240 'allWrap' => $allWrap,
1241 'excludeFromConcatenation' => $excludeFromConcatenation
1242 );
1243 }
1244 }
1245
1246 /**
1247 * Adds JS file
1248 *
1249 * @param string $file File name
1250 * @param string $type Content Type
1251 * @param boolean $compress
1252 * @param boolean $forceOnTop
1253 * @param string $allWrap
1254 * @param boolean $excludeFromConcatenation
1255 * @return void
1256 */
1257 public function addJsFile($file, $type = 'text/javascript', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE) {
1258 if (!$type) {
1259 $type = 'text/javascript';
1260 }
1261 if (!isset($this->jsFiles[$file])) {
1262 if (strpos($file, 'ajax.php?') !== FALSE) {
1263 $compress = FALSE;
1264 }
1265 $this->jsFiles[$file] = array(
1266 'file' => $file,
1267 'type' => $type,
1268 'section' => self::PART_HEADER,
1269 'compress' => $compress,
1270 'forceOnTop' => $forceOnTop,
1271 'allWrap' => $allWrap,
1272 'excludeFromConcatenation' => $excludeFromConcatenation
1273 );
1274 }
1275 }
1276
1277 /**
1278 * Adds JS file to footer
1279 *
1280 * @param string $file File name
1281 * @param string $type Content Type
1282 * @param boolean $compress
1283 * @param boolean $forceOnTop
1284 * @param string $allWrap
1285 * @param boolean $excludeFromConcatenation
1286 * @return void
1287 */
1288 public function addJsFooterFile($file, $type = 'text/javascript', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE) {
1289 if (!$type) {
1290 $type = 'text/javascript';
1291 }
1292 if (!isset($this->jsFiles[$file])) {
1293 if (strpos($file, 'ajax.php?') !== FALSE) {
1294 $compress = FALSE;
1295 }
1296 $this->jsFiles[$file] = array(
1297 'file' => $file,
1298 'type' => $type,
1299 'section' => self::PART_FOOTER,
1300 'compress' => $compress,
1301 'forceOnTop' => $forceOnTop,
1302 'allWrap' => $allWrap,
1303 'excludeFromConcatenation' => $excludeFromConcatenation
1304 );
1305 }
1306 }
1307
1308 /**
1309 * Adds JS inline code
1310 *
1311 * @param string $name
1312 * @param string $block
1313 * @param boolean $compress
1314 * @param boolean $forceOnTop
1315 * @return void
1316 */
1317 public function addJsInlineCode($name, $block, $compress = TRUE, $forceOnTop = FALSE) {
1318 if (!isset($this->jsInline[$name]) && !empty($block)) {
1319 $this->jsInline[$name] = array(
1320 'code' => $block . LF,
1321 'section' => self::PART_HEADER,
1322 'compress' => $compress,
1323 'forceOnTop' => $forceOnTop
1324 );
1325 }
1326 }
1327
1328 /**
1329 * Adds JS inline code to footer
1330 *
1331 * @param string $name
1332 * @param string $block
1333 * @param boolean $compress
1334 * @param boolean $forceOnTop
1335 * @return void
1336 */
1337 public function addJsFooterInlineCode($name, $block, $compress = TRUE, $forceOnTop = FALSE) {
1338 if (!isset($this->jsInline[$name]) && !empty($block)) {
1339 $this->jsInline[$name] = array(
1340 'code' => $block . LF,
1341 'section' => self::PART_FOOTER,
1342 'compress' => $compress,
1343 'forceOnTop' => $forceOnTop
1344 );
1345 }
1346 }
1347
1348 /**
1349 * Adds Ext.onready code, which will be wrapped in Ext.onReady(function() {...});
1350 *
1351 * @param string $block Javascript code
1352 * @param boolean $forceOnTop Position of the javascript code (TRUE for putting it on top, default is FALSE = bottom)
1353 * @return void
1354 */
1355 public function addExtOnReadyCode($block, $forceOnTop = FALSE) {
1356 if (!in_array($block, $this->extOnReadyCode)) {
1357 if ($forceOnTop) {
1358 array_unshift($this->extOnReadyCode, $block);
1359 } else {
1360 $this->extOnReadyCode[] = $block;
1361 }
1362 }
1363 }
1364
1365 /**
1366 * Adds the ExtDirect code
1367 *
1368 * @param array $filterNamespaces Limit the output to defined namespaces. If empty, all namespaces are generated
1369 * @return void
1370 */
1371 public function addExtDirectCode(array $filterNamespaces = array()) {
1372 if ($this->extDirectCodeAdded) {
1373 return;
1374 }
1375 $this->extDirectCodeAdded = TRUE;
1376 if (count($filterNamespaces) === 0) {
1377 $filterNamespaces = array('TYPO3');
1378 }
1379 // For ExtDirect we need flash message support
1380 $this->addJsFile(GeneralUtility::resolveBackPath($this->backPath . 'sysext/backend/Resources/Public/JavaScript/flashmessages.js'));
1381 // Add language labels for ExtDirect
1382 if (TYPO3_MODE === 'FE') {
1383 $this->addInlineLanguageLabelArray(array(
1384 'extDirect_timeoutHeader' => $GLOBALS['TSFE']->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutHeader'),
1385 'extDirect_timeoutMessage' => $GLOBALS['TSFE']->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutMessage')
1386 ));
1387 } else {
1388 $this->addInlineLanguageLabelArray(array(
1389 'extDirect_timeoutHeader' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutHeader'),
1390 'extDirect_timeoutMessage' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutMessage')
1391 ));
1392 }
1393 $token = ($api = '');
1394 if (TYPO3_MODE === 'BE') {
1395 $formprotection = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get();
1396 $token = $formprotection->generateToken('extDirect');
1397 }
1398 /** @var $extDirect \TYPO3\CMS\Core\ExtDirect\ExtDirectApi */
1399 $extDirect = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\ExtDirect\\ExtDirectApi');
1400 $api = $extDirect->getApiPhp($filterNamespaces);
1401 if ($api) {
1402 $this->addJsInlineCode('TYPO3ExtDirectAPI', $api, FALSE);
1403 }
1404 // Note: we need to iterate thru the object, because the addProvider method
1405 // does this only with multiple arguments
1406 $this->addExtOnReadyCode('
1407 (function() {
1408 TYPO3.ExtDirectToken = "' . $token . '";
1409 for (var api in Ext.app.ExtDirectAPI) {
1410 var provider = Ext.Direct.addProvider(Ext.app.ExtDirectAPI[api]);
1411 provider.on("beforecall", function(provider, transaction, meta) {
1412 if (transaction.data) {
1413 transaction.data[transaction.data.length] = TYPO3.ExtDirectToken;
1414 } else {
1415 transaction.data = [TYPO3.ExtDirectToken];
1416 }
1417 });
1418
1419 provider.on("call", function(provider, transaction, meta) {
1420 if (transaction.isForm) {
1421 transaction.params.securityToken = TYPO3.ExtDirectToken;
1422 }
1423 });
1424 }
1425 })();
1426
1427 var extDirectDebug = function(message, header, group) {
1428 var TYPO3ViewportInstance = null;
1429
1430 if (top && top.TYPO3 && typeof top.TYPO3.Backend === "object") {
1431 TYPO3ViewportInstance = top.TYPO3.Backend;
1432 } else if (typeof TYPO3 === "object" && typeof TYPO3.Backend === "object") {
1433 TYPO3ViewportInstance = TYPO3.Backend;
1434 }
1435
1436 if (TYPO3ViewportInstance !== null) {
1437 TYPO3ViewportInstance.DebugConsole.addTab(message, header, group);
1438 } else if (typeof console === "object") {
1439 console.log(message);
1440 } else {
1441 document.write(message);
1442 }
1443 };
1444
1445 Ext.Direct.on("exception", function(event) {
1446 if (event.code === Ext.Direct.exceptions.TRANSPORT && !event.where) {
1447 TYPO3.Flashmessage.display(
1448 TYPO3.Severity.error,
1449 TYPO3.l10n.localize("extDirect_timeoutHeader"),
1450 TYPO3.l10n.localize("extDirect_timeoutMessage"),
1451 30
1452 );
1453 } else {
1454 var backtrace = "";
1455 if (event.code === "parse") {
1456 extDirectDebug(
1457 "<p>" + event.xhr.responseText + "<\\/p>",
1458 event.type,
1459 "ExtDirect - Exception"
1460 );
1461 } else if (event.code === "router") {
1462 TYPO3.Flashmessage.display(
1463 TYPO3.Severity.error,
1464 event.code,
1465 event.message,
1466 30
1467 );
1468 } else if (event.where) {
1469 backtrace = "<p style=\\"margin-top: 20px;\\">" +
1470 "<strong>Backtrace:<\\/strong><br \\/>" +
1471 event.where.replace(/#/g, "<br \\/>#") +
1472 "<\\/p>";
1473 extDirectDebug(
1474 "<p>" + event.message + "<\\/p>" + backtrace,
1475 event.method,
1476 "ExtDirect - Exception"
1477 );
1478 }
1479
1480
1481 }
1482 });
1483
1484 Ext.Direct.on("event", function(event, provider) {
1485 if (typeof event.debug !== "undefined" && event.debug !== "") {
1486 extDirectDebug(event.debug, event.method, "ExtDirect - Debug");
1487 }
1488 });
1489 ', TRUE);
1490 }
1491
1492 /**
1493 * Adds CSS file
1494 *
1495 * @param string $file
1496 * @param string $rel
1497 * @param string $media
1498 * @param string $title
1499 * @param boolean $compress
1500 * @param boolean $forceOnTop
1501 * @param string $allWrap
1502 * @param boolean $excludeFromConcatenation
1503 * @return void
1504 */
1505 public function addCssFile($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE) {
1506 if (!isset($this->cssFiles[$file])) {
1507 $this->cssFiles[$file] = array(
1508 'file' => $file,
1509 'rel' => $rel,
1510 'media' => $media,
1511 'title' => $title,
1512 'compress' => $compress,
1513 'forceOnTop' => $forceOnTop,
1514 'allWrap' => $allWrap,
1515 'excludeFromConcatenation' => $excludeFromConcatenation
1516 );
1517 }
1518 }
1519
1520 /**
1521 * Adds CSS inline code
1522 *
1523 * @param string $name
1524 * @param string $block
1525 * @param boolean $compress
1526 * @param boolean $forceOnTop
1527 * @return void
1528 */
1529 public function addCssInlineBlock($name, $block, $compress = FALSE, $forceOnTop = FALSE) {
1530 if (!isset($this->cssInline[$name]) && !empty($block)) {
1531 $this->cssInline[$name] = array(
1532 'code' => $block,
1533 'compress' => $compress,
1534 'forceOnTop' => $forceOnTop
1535 );
1536 }
1537 }
1538
1539 /**
1540 * Call this function if you need to include the jQuery library
1541 *
1542 * @param null|string $version The jQuery version that should be included, either "latest" or any available version
1543 * @param null|string $source The location of the jQuery source, can be "local", "google", "msn", "jquery" or just an URL to your jQuery lib
1544 * @param string $namespace The namespace in which the jQuery object of the specific version should be stored.
1545 * @return void
1546 * @throws \UnexpectedValueException
1547 */
1548 public function loadJquery($version = NULL, $source = NULL, $namespace = self::JQUERY_NAMESPACE_DEFAULT) {
1549 // Set it to the version that is shipped with the TYPO3 core
1550 if ($version === NULL || $version === 'latest') {
1551 $version = self::JQUERY_VERSION_LATEST;
1552 }
1553 // Check if the source is set, otherwise set it to "default"
1554 if ($source === NULL) {
1555 $source = 'local';
1556 }
1557 if ($source === 'local' && !in_array($version, $this->availableLocalJqueryVersions)) {
1558 throw new \UnexpectedValueException('The requested jQuery version is not available in the local filesystem.', 1341505305);
1559 }
1560 if (!preg_match('/^[a-zA-Z0-9]+$/', $namespace)) {
1561 throw new \UnexpectedValueException('The requested namespace contains non alphanumeric characters.', 1341571604);
1562 }
1563 $this->jQueryVersions[$namespace] = array(
1564 'version' => $version,
1565 'source' => $source
1566 );
1567 }
1568
1569 /**
1570 * Call function if you need the requireJS library
1571 * this automatically adds the JavaScript path of all loaded extensions in the requireJS path option
1572 * so it resolves names like TYPO3/CMS/MyExtension/MyJsFile to EXT:MyExtension/Resources/Public/JavaScript/MyJsFile.js
1573 * when using requireJS
1574 *
1575 * @return void
1576 */
1577 public function loadRequireJs() {
1578
1579 // load all paths to map to package names / namespaces
1580 if (count($this->requireJsConfig) === 0) {
1581 // first, load all paths for the namespaces
1582 $this->requireJsConfig['paths'] = array();
1583 // get all extensions that are loaded
1584 $loadedExtensions = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getLoadedExtensionListArray();
1585 foreach ($loadedExtensions as $packageName) {
1586 $fullJsPath = 'EXT:' . $packageName . '/Resources/Public/JavaScript/';
1587 $fullJsPath = GeneralUtility::getFileAbsFileName($fullJsPath);
1588 $fullJsPath = \TYPO3\CMS\Core\Utility\PathUtility::getRelativePath(PATH_typo3, $fullJsPath);
1589 $fullJsPath = rtrim($fullJsPath, '/');
1590 if ($fullJsPath) {
1591 $this->requireJsConfig['paths']['TYPO3/CMS/' . GeneralUtility::underscoredToUpperCamelCase($packageName)] = $this->backPath . $fullJsPath;
1592 }
1593 }
1594
1595 // check if additional AMD modules need to be loaded if a single AMD module is initialized
1596 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules'])) {
1597 $this->addInlineSettingArray('RequireJS.PostInitializationModules', $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules']);
1598 }
1599 }
1600
1601 $this->addRequireJs = TRUE;
1602 }
1603
1604 /**
1605 * includes a AMD-compatible JS file by resolving the ModuleName, and then requires the file via a requireJS request
1606 *
1607 * this function only works for AMD-ready JS modules, used like "define('TYPO3/CMS/Backend/FormEngine..."
1608 * in the JS file
1609 *
1610 * TYPO3/CMS/Backend/FormEngine =>
1611 * "TYPO3": Vendor Name
1612 * "CMS": Product Name
1613 * "Backend": Extension Name
1614 * "FormEngine": FileName in the Resources/Public/JavaScript folder
1615 *
1616 * @param $mainModuleName must be in the form of "TYPO3/CMS/PackageName/ModuleName" e.g. "TYPO3/CMS/Backend/FormEngine"
1617 * @return void
1618 */
1619 public function loadRequireJsModule($mainModuleName) {
1620
1621 // make sure requireJS is initialized
1622 $this->loadRequireJs();
1623
1624 // execute the main module
1625 $this->addJsInlineCode('RequireJS-Module-' . $mainModuleName, 'require(["' . $mainModuleName . '"]);');
1626 }
1627
1628 /**
1629 * Call function if you need the prototype library
1630 *
1631 * @return void
1632 */
1633 public function loadPrototype() {
1634 $this->addPrototype = TRUE;
1635 }
1636
1637 /**
1638 * Call function if you need the Scriptaculous library
1639 *
1640 * @param string $modules Add modules you need. use "all" if you need complete modules
1641 * @return void
1642 */
1643 public function loadScriptaculous($modules = 'all') {
1644 // Scriptaculous require prototype, so load prototype too.
1645 $this->addPrototype = TRUE;
1646 $this->addScriptaculous = TRUE;
1647 if ($modules) {
1648 if ($modules == 'all') {
1649 foreach ($this->addScriptaculousModules as $key => $value) {
1650 $this->addScriptaculousModules[$key] = TRUE;
1651 }
1652 } else {
1653 $mods = GeneralUtility::trimExplode(',', $modules);
1654 foreach ($mods as $mod) {
1655 if (isset($this->addScriptaculousModules[strtolower($mod)])) {
1656 $this->addScriptaculousModules[strtolower($mod)] = TRUE;
1657 }
1658 }
1659 }
1660 }
1661 }
1662
1663 /**
1664 * call this function if you need the extJS library
1665 *
1666 * @param boolean $css Flag, if set the ext-css will be loaded
1667 * @param boolean $theme Flag, if set the ext-theme "grey" will be loaded
1668 * @param string $adapter Choose alternative adapter, possible values: yui, prototype, jquery
1669 * @return void
1670 */
1671 public function loadExtJS($css = TRUE, $theme = TRUE, $adapter = '') {
1672 if ($adapter) {
1673 // Empty $adapter will always load the ext adapter
1674 switch (GeneralUtility::strtolower(trim($adapter))) {
1675 case self::EXTJS_ADAPTER_YUI:
1676 $this->extJSadapter = 'yui/ext-yui-adapter.js';
1677 break;
1678 case self::EXTJS_ADAPTER_PROTOTYPE:
1679 $this->extJSadapter = 'prototype/ext-prototype-adapter.js';
1680 break;
1681 case self::EXTJS_ADAPTER_JQUERY:
1682 $this->extJSadapter = 'jquery/ext-jquery-adapter.js';
1683 break;
1684 }
1685 }
1686 $this->addExtJS = TRUE;
1687 $this->extJStheme = $theme;
1688 $this->extJScss = $css;
1689 }
1690
1691 /**
1692 * Enables ExtJs QuickTips
1693 * Need extJs loaded
1694 *
1695 * @return void
1696 */
1697 public function enableExtJSQuickTips() {
1698 $this->enableExtJSQuickTips = TRUE;
1699 }
1700
1701 /**
1702 * Call function if you need the ExtCore library
1703 *
1704 * @return void
1705 */
1706 public function loadExtCore() {
1707 $this->addExtCore = TRUE;
1708 }
1709
1710 /**
1711 * Call function if you need the SVG library
1712 *
1713 * @return void
1714 */
1715 public function loadSvg() {
1716 $this->addSvg = TRUE;
1717 }
1718
1719 /**
1720 * Call this function to load debug version of ExtJS. Use this for development only
1721 *
1722 * @return void
1723 */
1724 public function enableSvgDebug() {
1725 $this->enableSvgDebug = TRUE;
1726 }
1727
1728 /**
1729 * Call this function to force flash usage with SVG library
1730 *
1731 * @return void
1732 */
1733 public function svgForceFlash() {
1734 $this->addMetaTag('<meta name="svg.render.forceflash" content="true" />');
1735 }
1736
1737 /**
1738 * Call this function to load debug version of ExtJS. Use this for development only
1739 *
1740 * @return void
1741 */
1742 public function enableExtJsDebug() {
1743 $this->enableExtJsDebug = TRUE;
1744 }
1745
1746 /**
1747 * Call this function to load debug version of ExtCore. Use this for development only
1748 *
1749 * @return void
1750 */
1751 public function enableExtCoreDebug() {
1752 $this->enableExtCoreDebug = TRUE;
1753 }
1754
1755 /**
1756 * Adds Javascript Inline Label. This will occur in TYPO3.lang - object
1757 * The label can be used in scripts with TYPO3.lang.<key>
1758 * Need extJs loaded
1759 *
1760 * @param string $key
1761 * @param string $value
1762 * @return void
1763 */
1764 public function addInlineLanguageLabel($key, $value) {
1765 $this->inlineLanguageLabels[$key] = $value;
1766 }
1767
1768 /**
1769 * Adds Javascript Inline Label Array. This will occur in TYPO3.lang - object
1770 * The label can be used in scripts with TYPO3.lang.<key>
1771 * Array will be merged with existing array.
1772 * Need extJs loaded
1773 *
1774 * @param array $array
1775 * @return void
1776 */
1777 public function addInlineLanguageLabelArray(array $array) {
1778 $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $array);
1779 }
1780
1781 /**
1782 * Gets labels to be used in JavaScript fetched from a locallang file.
1783 *
1784 * @param string $fileRef Input is a file-reference (see GeneralUtility::getFileAbsFileName). That file is expected to be a 'locallang.xml' file containing a valid XML TYPO3 language structure.
1785 * @param string $selectionPrefix Prefix to select the correct labels (default: '')
1786 * @param string $stripFromSelectionName Sub-prefix to be removed from label names in the result (default: '')
1787 * @param integer $errorMode Error mode (when file could not be found): 0 - syslog entry, 1 - do nothing, 2 - throw an exception
1788 * @return void
1789 */
1790 public function addInlineLanguageLabelFile($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0) {
1791 $index = md5($fileRef . $selectionPrefix . $stripFromSelectionName);
1792 if ($fileRef && !isset($this->inlineLanguageLabelFiles[$index])) {
1793 $this->inlineLanguageLabelFiles[$index] = array(
1794 'fileRef' => $fileRef,
1795 'selectionPrefix' => $selectionPrefix,
1796 'stripFromSelectionName' => $stripFromSelectionName,
1797 'errorMode' => $errorMode
1798 );
1799 }
1800 }
1801
1802 /**
1803 * Adds Javascript Inline Setting. This will occur in TYPO3.settings - object
1804 * The label can be used in scripts with TYPO3.setting.<key>
1805 * Need extJs loaded
1806 *
1807 * @param string $namespace
1808 * @param string $key
1809 * @param string $value
1810 * @return void
1811 */
1812 public function addInlineSetting($namespace, $key, $value) {
1813 if ($namespace) {
1814 if (strpos($namespace, '.')) {
1815 $parts = explode('.', $namespace);
1816 $a = &$this->inlineSettings;
1817 foreach ($parts as $part) {
1818 $a = &$a[$part];
1819 }
1820 $a[$key] = $value;
1821 } else {
1822 $this->inlineSettings[$namespace][$key] = $value;
1823 }
1824 } else {
1825 $this->inlineSettings[$key] = $value;
1826 }
1827 }
1828
1829 /**
1830 * Adds Javascript Inline Setting. This will occur in TYPO3.settings - object
1831 * The label can be used in scripts with TYPO3.setting.<key>
1832 * Array will be merged with existing array.
1833 * Need extJs loaded
1834 *
1835 * @param string $namespace
1836 * @param array $array
1837 * @return void
1838 */
1839 public function addInlineSettingArray($namespace, array $array) {
1840 if ($namespace) {
1841 if (strpos($namespace, '.')) {
1842 $parts = explode('.', $namespace);
1843 $a = &$this->inlineSettings;
1844 foreach ($parts as $part) {
1845 $a = &$a[$part];
1846 }
1847 $a = array_merge((array) $a, $array);
1848 } else {
1849 $this->inlineSettings[$namespace] = array_merge((array) $this->inlineSettings[$namespace], $array);
1850 }
1851 } else {
1852 $this->inlineSettings = array_merge($this->inlineSettings, $array);
1853 }
1854 }
1855
1856 /**
1857 * Adds content to body content
1858 *
1859 * @param string $content
1860 * @return void
1861 */
1862 public function addBodyContent($content) {
1863 $this->bodyContent .= $content;
1864 }
1865
1866 /*****************************************************/
1867 /* */
1868 /* Render Functions */
1869 /* */
1870 /*****************************************************/
1871 /**
1872 * Render the section (Header or Footer)
1873 *
1874 * @param integer $part Section which should be rendered: self::PART_COMPLETE, self::PART_HEADER or self::PART_FOOTER
1875 * @return string Content of rendered section
1876 */
1877 public function render($part = self::PART_COMPLETE) {
1878 $this->prepareRendering();
1879 list($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs) = $this->renderJavaScriptAndCss();
1880 $metaTags = implode(LF, $this->metaTags);
1881 $markerArray = $this->getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags);
1882 $template = $this->getTemplateForPart($part);
1883 $this->reset();
1884 return trim(\TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($template, $markerArray, '###|###'));
1885 }
1886
1887 /**
1888 * Render the page but not the JavaScript and CSS Files
1889 *
1890 * @param string $substituteHash The hash that is used for the placehoder markers
1891 * @access private
1892 * @return string Content of rendered section
1893 */
1894 public function renderPageWithUncachedObjects($substituteHash) {
1895 $this->prepareRendering();
1896 $markerArray = $this->getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash);
1897 $template = $this->getTemplateForPart(self::PART_COMPLETE);
1898 return trim(\TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($template, $markerArray, '###|###'));
1899 }
1900
1901 /**
1902 * Renders the JavaScript and CSS files that have been added during processing
1903 * of uncached content objects (USER_INT, COA_INT)
1904 *
1905 * @param string $cachedPageContent
1906 * @param string $substituteHash The hash that is used for the placehoder markers
1907 * @access private
1908 * @return string
1909 */
1910 public function renderJavaScriptAndCssForProcessingOfUncachedContentObjects($cachedPageContent, $substituteHash) {
1911 $this->prepareRendering();
1912 list($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs) = $this->renderJavaScriptAndCss();
1913 $markerArray = array(
1914 '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->' => $cssFiles,
1915 '<!-- ###CSS_INLINE' . $substituteHash . '### -->' => $cssInline,
1916 '<!-- ###JS_INLINE' . $substituteHash . '### -->' => $jsInline,
1917 '<!-- ###JS_INCLUDE' . $substituteHash . '### -->' => $jsFiles,
1918 '<!-- ###JS_LIBS' . $substituteHash . '### -->' => $jsLibs,
1919 '<!-- ###HEADERDATA' . $substituteHash . '### -->' => implode(LF, $this->headerData),
1920 '<!-- ###FOOTERDATA' . $substituteHash . '### -->' => implode(LF, $this->footerData),
1921 '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->' => $jsFooterLibs,
1922 '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->' => $jsFooterFiles,
1923 '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->' => $jsFooterInline
1924 );
1925 foreach ($markerArray as $placeHolder => $content) {
1926 $cachedPageContent = str_replace($placeHolder, $content, $cachedPageContent);
1927 }
1928 $this->reset();
1929 return $cachedPageContent;
1930 }
1931
1932 /**
1933 * Remove ending slashes from static header block
1934 * if the page is beeing rendered as html (not xhtml)
1935 * and define property $this->endingSlash for further use
1936 *
1937 * @return void
1938 */
1939 protected function prepareRendering() {
1940 if ($this->getRenderXhtml()) {
1941 $this->endingSlash = ' /';
1942 } else {
1943 $this->metaCharsetTag = str_replace(' />', '>', $this->metaCharsetTag);
1944 $this->baseUrlTag = str_replace(' />', '>', $this->baseUrlTag);
1945 $this->shortcutTag = str_replace(' />', '>', $this->shortcutTag);
1946 $this->endingSlash = '';
1947 }
1948 }
1949
1950 /**
1951 * Renders all JavaScript and CSS
1952 *
1953 * @return array<string>
1954 */
1955 protected function renderJavaScriptAndCss() {
1956 $this->executePreRenderHook();
1957 $mainJsLibs = $this->renderMainJavaScriptLibraries();
1958 if ($this->concatenateFiles || $this->concatenateJavascript || $this->concatenateCss) {
1959 // Do the file concatenation
1960 $this->doConcatenate();
1961 }
1962 if ($this->compressCss || $this->compressJavascript) {
1963 // Do the file compression
1964 $this->doCompress();
1965 }
1966 $this->executeRenderPostTransformHook();
1967 $cssFiles = $this->renderCssFiles();
1968 $cssInline = $this->renderCssInline();
1969 list($jsLibs, $jsFooterLibs) = $this->renderAdditionalJavaScriptLibraries();
1970 list($jsFiles, $jsFooterFiles) = $this->renderJavaScriptFiles();
1971 list($jsInline, $jsFooterInline) = $this->renderInlineJavaScript();
1972 $jsLibs = $mainJsLibs . $jsLibs;
1973 if ($this->moveJsFromHeaderToFooter) {
1974 $jsFooterLibs = $jsLibs . LF . $jsFooterLibs;
1975 $jsLibs = '';
1976 $jsFooterFiles = $jsFiles . LF . $jsFooterFiles;
1977 $jsFiles = '';
1978 $jsFooterInline = $jsInline . LF . $jsFooterInline;
1979 $jsInline = '';
1980 }
1981 $this->executePostRenderHook($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs);
1982 return array($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs);
1983 }
1984
1985 /**
1986 * Fills the marker array with the given strings and trims each value
1987 *
1988 * @param $jsLibs string
1989 * @param $jsFiles string
1990 * @param $jsFooterFiles string
1991 * @param $cssFiles string
1992 * @param $jsInline string
1993 * @param $cssInline string
1994 * @param $jsFooterInline string
1995 * @param $jsFooterLibs string
1996 * @param $metaTags string
1997 * @return array Marker array
1998 */
1999 protected function getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags) {
2000 $markerArray = array(
2001 'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
2002 'HTMLTAG' => $this->htmlTag,
2003 'HEADTAG' => $this->headTag,
2004 'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
2005 'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
2006 'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
2007 'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
2008 'CSS_INCLUDE' => $cssFiles,
2009 'CSS_INLINE' => $cssInline,
2010 'JS_INLINE' => $jsInline,
2011 'JS_INCLUDE' => $jsFiles,
2012 'JS_LIBS' => $jsLibs,
2013 'TITLE' => $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '',
2014 'META' => $metaTags,
2015 'HEADERDATA' => $this->headerData ? implode(LF, $this->headerData) : '',
2016 'FOOTERDATA' => $this->footerData ? implode(LF, $this->footerData) : '',
2017 'JS_LIBS_FOOTER' => $jsFooterLibs,
2018 'JS_INCLUDE_FOOTER' => $jsFooterFiles,
2019 'JS_INLINE_FOOTER' => $jsFooterInline,
2020 'BODY' => $this->bodyContent
2021 );
2022 $markerArray = array_map('trim', $markerArray);
2023 return $markerArray;
2024 }
2025
2026 /**
2027 * Fills the marker array with the given strings and trims each value
2028 *
2029 * @param string $substituteHash The hash that is used for the placehoder markers
2030 * @return array Marker array
2031 */
2032 protected function getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash) {
2033 $markerArray = array(
2034 'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
2035 'HTMLTAG' => $this->htmlTag,
2036 'HEADTAG' => $this->headTag,
2037 'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
2038 'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
2039 'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
2040 'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
2041 'TITLE' => $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '',
2042 'META' => implode(LF, $this->metaTags),
2043 'BODY' => $this->bodyContent,
2044 'CSS_INCLUDE' => '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->',
2045 'CSS_INLINE' => '<!-- ###CSS_INLINE' . $substituteHash . '### -->',
2046 'JS_INLINE' => '<!-- ###JS_INLINE' . $substituteHash . '### -->',
2047 'JS_INCLUDE' => '<!-- ###JS_INCLUDE' . $substituteHash . '### -->',
2048 'JS_LIBS' => '<!-- ###JS_LIBS' . $substituteHash . '### -->',
2049 'HEADERDATA' => '<!-- ###HEADERDATA' . $substituteHash . '### -->',
2050 'FOOTERDATA' => '<!-- ###FOOTERDATA' . $substituteHash . '### -->',
2051 'JS_LIBS_FOOTER' => '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->',
2052 'JS_INCLUDE_FOOTER' => '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->',
2053 'JS_INLINE_FOOTER' => '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->'
2054 );
2055 $markerArray = array_map('trim', $markerArray);
2056 return $markerArray;
2057 }
2058
2059 /**
2060 * Reads the template file and returns the requested part as string
2061 *
2062 * @param integer $part
2063 * @return string
2064 */
2065 protected function getTemplateForPart($part) {
2066 $templateFile = GeneralUtility::getFileAbsFileName($this->templateFile, TRUE);
2067 $template = GeneralUtility::getUrl($templateFile);
2068 if ($this->removeLineBreaksFromTemplate) {
2069 $template = strtr($template, array(LF => '', CR => ''));
2070 }
2071 if ($part != self::PART_COMPLETE) {
2072 $templatePart = explode('###BODY###', $template);
2073 $template = $templatePart[$part - 1];
2074 }
2075 return $template;
2076 }
2077
2078 /**
2079 * Helper function for render the main JavaScript libraries,
2080 * currently: RequireJS, jQuery, PrototypeJS, Scriptaculous, SVG, ExtJs
2081 *
2082 * @return string Content with JavaScript libraries
2083 */
2084 protected function renderMainJavaScriptLibraries() {
2085 $out = '';
2086
2087 // Include RequireJS
2088 if ($this->addRequireJs) {
2089 // load the paths of the requireJS configuration
2090 $out .= GeneralUtility::wrapJS('var require = ' . json_encode($this->requireJsConfig)) . LF;
2091 // directly after that, include the require.js file
2092 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->requireJsPath . 'require.js')) . '" type="text/javascript"></script>' . LF;
2093 }
2094
2095 if ($this->addSvg) {
2096 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->svgPath . 'svg.js')) . '" data-path="' . $this->backPath . $this->svgPath . '"' . ($this->enableSvgDebug ? ' data-debug="true"' : '') . '></script>' . LF;
2097 }
2098 // Include jQuery Core for each namespace, depending on the version and source
2099 if (!empty($this->jQueryVersions)) {
2100 foreach ($this->jQueryVersions as $namespace => $jQueryVersion) {
2101 $out .= $this->renderJqueryScriptTag($jQueryVersion['version'], $jQueryVersion['source'], $namespace);
2102 }
2103 }
2104 if ($this->addPrototype) {
2105 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->prototypePath . 'prototype.js')) . '" type="text/javascript"></script>' . LF;
2106 unset($this->jsFiles[$this->backPath . $this->prototypePath . 'prototype.js']);
2107 }
2108 if ($this->addScriptaculous) {
2109 $mods = array();
2110 foreach ($this->addScriptaculousModules as $key => $value) {
2111 if ($this->addScriptaculousModules[$key]) {
2112 $mods[] = $key;
2113 }
2114 }
2115 // Resolve dependencies
2116 if (in_array('dragdrop', $mods) || in_array('controls', $mods)) {
2117 $mods = array_merge(array('effects'), $mods);
2118 }
2119 if (count($mods)) {
2120 foreach ($mods as $module) {
2121 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->scriptaculousPath . $module . '.js')) . '" type="text/javascript"></script>' . LF;
2122 unset($this->jsFiles[$this->backPath . $this->scriptaculousPath . $module . '.js']);
2123 }
2124 }
2125 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->scriptaculousPath . 'scriptaculous.js')) . '" type="text/javascript"></script>' . LF;
2126 unset($this->jsFiles[$this->backPath . $this->scriptaculousPath . 'scriptaculous.js']);
2127 }
2128 // Include extCore, but only if ExtJS is not included
2129 if ($this->addExtCore && !$this->addExtJS) {
2130 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->extCorePath . 'ext-core' . ($this->enableExtCoreDebug ? '-debug' : '') . '.js')) . '" type="text/javascript"></script>' . LF;
2131 unset($this->jsFiles[$this->backPath . $this->extCorePath . 'ext-core' . ($this->enableExtCoreDebug ? '-debug' : '') . '.js']);
2132 }
2133 // Include extJS
2134 if ($this->addExtJS) {
2135 // Use the base adapter all the time
2136 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->extJsPath . 'adapter/' . ($this->enableExtJsDebug ? str_replace('.js', '-debug.js', $this->extJSadapter) : $this->extJSadapter))) . '" type="text/javascript"></script>' . LF;
2137 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->extJsPath . 'ext-all' . ($this->enableExtJsDebug ? '-debug' : '') . '.js')) . '" type="text/javascript"></script>' . LF;
2138 // Add extJS localization
2139 // Load standard ISO mapping and modify for use with ExtJS
2140 $localeMap = $this->locales->getIsoMapping();
2141 $localeMap[''] = 'en';
2142 $localeMap['default'] = 'en';
2143 // Greek
2144 $localeMap['gr'] = 'el_GR';
2145 // Norwegian Bokmaal
2146 $localeMap['no'] = 'no_BO';
2147 // Swedish
2148 $localeMap['se'] = 'se_SV';
2149 $extJsLang = isset($localeMap[$this->lang]) ? $localeMap[$this->lang] : $this->lang;
2150 // TODO autoconvert file from UTF8 to current BE charset if necessary!!!!
2151 $extJsLocaleFile = $this->extJsPath . 'locale/ext-lang-' . $extJsLang . '.js';
2152 if (file_exists(PATH_typo3 . $extJsLocaleFile)) {
2153 $out .= '<script src="' . $this->processJsFile(($this->backPath . $extJsLocaleFile)) . '" type="text/javascript" charset="utf-8"></script>' . LF;
2154 }
2155 // Remove extjs from JScodeLibArray
2156 unset($this->jsFiles[$this->backPath . $this->extJsPath . 'ext-all.js'], $this->jsFiles[$this->backPath . $this->extJsPath . 'ext-all-debug.js']);
2157 }
2158 if (count($this->inlineLanguageLabelFiles)) {
2159 foreach ($this->inlineLanguageLabelFiles as $languageLabelFile) {
2160 $this->includeLanguageFileForInline($languageLabelFile['fileRef'], $languageLabelFile['selectionPrefix'], $languageLabelFile['stripFromSelectionName'], $languageLabelFile['$errorMode']);
2161 }
2162 }
2163 unset($this->inlineLanguageLabelFiles);
2164 // Convert labels/settings back to UTF-8 since json_encode() only works with UTF-8:
2165 if ($this->getCharSet() !== 'utf-8') {
2166 if ($this->inlineLanguageLabels) {
2167 $this->csConvObj->convArray($this->inlineLanguageLabels, $this->getCharSet(), 'utf-8');
2168 }
2169 if ($this->inlineSettings) {
2170 $this->csConvObj->convArray($this->inlineSettings, $this->getCharSet(), 'utf-8');
2171 }
2172 }
2173 $inlineSettings = $this->inlineLanguageLabels ? 'TYPO3.lang = ' . json_encode($this->inlineLanguageLabels) . ';' : '';
2174 $inlineSettings .= $this->inlineSettings ? 'TYPO3.settings = ' . json_encode($this->inlineSettings) . ';' : '';
2175 if ($this->addExtCore || $this->addExtJS) {
2176 // Set clear.gif, move it on top, add handler code
2177 $code = '';
2178 if (count($this->extOnReadyCode)) {
2179 foreach ($this->extOnReadyCode as $block) {
2180 $code .= $block;
2181 }
2182 }
2183 $out .= $this->inlineJavascriptWrap[0] . '
2184 Ext.ns("TYPO3");
2185 Ext.BLANK_IMAGE_URL = "' . htmlspecialchars(GeneralUtility::locationHeaderUrl(($this->backPath . 'gfx/clear.gif'))) . '";' . LF . $inlineSettings . 'Ext.onReady(function() {' . ($this->enableExtJSQuickTips ? 'Ext.QuickTips.init();' . LF : '') . $code . ' });' . $this->inlineJavascriptWrap[1];
2186 unset($this->extOnReadyCode);
2187 // Include TYPO3.l10n object
2188 if (TYPO3_MODE === 'BE') {
2189 $out .= '<script src="' . $this->processJsFile(($this->backPath . 'sysext/lang/Resources/Public/JavaScript/Typo3Lang.js')) . '" type="text/javascript" charset="utf-8"></script>' . LF;
2190 }
2191 if ($this->extJStheme) {
2192 if (isset($GLOBALS['TBE_STYLES']['extJS']['theme'])) {
2193 $this->addCssFile($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['theme'], 'stylesheet', 'all', '', TRUE, TRUE);
2194 } else {
2195 $this->addCssFile($this->backPath . $this->extJsPath . 'resources/css/xtheme-blue.css', 'stylesheet', 'all', '', TRUE, TRUE);
2196 }
2197 }
2198 if ($this->extJScss) {
2199 if (isset($GLOBALS['TBE_STYLES']['extJS']['all'])) {
2200 $this->addCssFile($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['all'], 'stylesheet', 'all', '', TRUE, TRUE);
2201 } else {
2202 $this->addCssFile($this->backPath . $this->extJsPath . 'resources/css/ext-all-notheme.css', 'stylesheet', 'all', '', TRUE, TRUE);
2203 }
2204 }
2205 } else {
2206 // no extJS loaded, but still inline settings
2207 if ($inlineSettings !== '') {
2208 // make sure the global TYPO3 is available
2209 $inlineSettings = 'var TYPO3 = TYPO3 || {};' . CRLF . $inlineSettings;
2210 $out .= $this->inlineJavascriptWrap[0] . $inlineSettings . $this->inlineJavascriptWrap[1];
2211 }
2212 }
2213 return $out;
2214 }
2215
2216 /**
2217 * Renders the HTML script tag for the given jQuery version.
2218 *
2219 * @param string $version The jQuery version that should be included, either "latest" or any available version
2220 * @param string $source The location of the jQuery source, can be "local", "google", "msn" or "jquery
2221 * @param string $namespace The namespace in which the jQuery object of the specific version should be stored
2222 * @return string
2223 */
2224 protected function renderJqueryScriptTag($version, $source, $namespace) {
2225 switch (TRUE) {
2226 case isset($this->jQueryCdnUrls[$source]):
2227 if ($this->enableJqueryDebug) {
2228 $minifyPart = '';
2229 } else {
2230 $minifyPart = '.min';
2231 }
2232 $jQueryFileName = sprintf($this->jQueryCdnUrls[$source], $version, $minifyPart);
2233 break;
2234 case $source === 'local':
2235 $jQueryFileName = $this->backPath . $this->jQueryPath . 'jquery-' . rawurlencode($version);
2236 if ($this->enableJqueryDebug) {
2237 $jQueryFileName .= '.js';
2238 } else {
2239 $jQueryFileName .= '.min.js';
2240 }
2241 break;
2242 default:
2243 $jQueryFileName = $source;
2244 }
2245 // Include the jQuery Core
2246 $scriptTag = '<script src="' . htmlspecialchars($jQueryFileName) . '" type="text/javascript"></script>' . LF;
2247 // Set the noConflict mode to be available via "TYPO3.jQuery" in all installations
2248 switch ($namespace) {
2249 case self::JQUERY_NAMESPACE_DEFAULT_NOCONFLICT:
2250 $scriptTag .= GeneralUtility::wrapJS('jQuery.noConflict();') . LF;
2251 break;
2252 case self::JQUERY_NAMESPACE_NONE:
2253 break;
2254 case self::JQUERY_NAMESPACE_DEFAULT:
2255
2256 default:
2257 $scriptTag .= GeneralUtility::wrapJS('var TYPO3 = TYPO3 || {}; TYPO3.' . $namespace . ' = jQuery.noConflict(true);') . LF;
2258 }
2259 return $scriptTag;
2260 }
2261
2262 /**
2263 * Render CSS files
2264 *
2265 * @return string
2266 */
2267 protected function renderCssFiles() {
2268 $cssFiles = '';
2269 if (count($this->cssFiles)) {
2270 foreach ($this->cssFiles as $file => $properties) {
2271 $file = GeneralUtility::resolveBackPath($file);
2272 $file = GeneralUtility::createVersionNumberedFilename($file);
2273 $tag = '<link rel="' . htmlspecialchars($properties['rel']) . '" type="text/css" href="' . htmlspecialchars($file) . '" media="' . htmlspecialchars($properties['media']) . '"' . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '') . $this->endingSlash . '>';
2274 if ($properties['allWrap'] && strpos($properties['allWrap'], '|') !== FALSE) {
2275 $tag = str_replace('|', $tag, $properties['allWrap']);
2276 }
2277 if ($properties['forceOnTop']) {
2278 $cssFiles = $tag . LF . $cssFiles;
2279 } else {
2280 $cssFiles .= LF . $tag;
2281 }
2282 }
2283 }
2284 return $cssFiles;
2285 }
2286
2287 /**
2288 * Render inline CSS
2289 *
2290 * @return string
2291 */
2292 protected function renderCssInline() {
2293 $cssInline = '';
2294 if (count($this->cssInline)) {
2295 foreach ($this->cssInline as $name => $properties) {
2296 if ($properties['forceOnTop']) {
2297 $cssInline = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF . $cssInline;
2298 } else {
2299 $cssInline .= '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2300 }
2301 }
2302 $cssInline = $this->inlineCssWrap[0] . $cssInline . $this->inlineCssWrap[1];
2303 }
2304 return $cssInline;
2305 }
2306
2307 /**
2308 * Render JavaScipt libraries
2309 *
2310 * @return array<string> jsLibs and jsFooterLibs strings
2311 */
2312 protected function renderAdditionalJavaScriptLibraries() {
2313 $jsLibs = '';
2314 $jsFooterLibs = '';
2315 if (count($this->jsLibs)) {
2316 foreach ($this->jsLibs as $properties) {
2317 $properties['file'] = GeneralUtility::resolveBackPath($properties['file']);
2318 $properties['file'] = GeneralUtility::createVersionNumberedFilename($properties['file']);
2319 $tag = '<script src="' . htmlspecialchars($properties['file']) . '" type="' . htmlspecialchars($properties['type']) . '"></script>';
2320 if ($properties['allWrap'] && strpos($properties['allWrap'], '|') !== FALSE) {
2321 $tag = str_replace('|', $tag, $properties['allWrap']);
2322 }
2323 if ($properties['forceOnTop']) {
2324 if ($properties['section'] === self::PART_HEADER) {
2325 $jsLibs = $tag . LF . $jsLibs;
2326 } else {
2327 $jsFooterLibs = $tag . LF . $jsFooterLibs;
2328 }
2329 } else {
2330 if ($properties['section'] === self::PART_HEADER) {
2331 $jsLibs .= LF . $tag;
2332 } else {
2333 $jsFooterLibs .= LF . $tag;
2334 }
2335 }
2336 }
2337 }
2338 if ($this->moveJsFromHeaderToFooter) {
2339 $jsFooterLibs = $jsLibs . LF . $jsFooterLibs;
2340 $jsLibs = '';
2341 }
2342 return array($jsLibs, $jsFooterLibs);
2343 }
2344
2345 /**
2346 * Render JavaScript files
2347 *
2348 * @return array<string> jsFiles and jsFooterFiles strings
2349 */
2350 protected function renderJavaScriptFiles() {
2351 $jsFiles = '';
2352 $jsFooterFiles = '';
2353 if (count($this->jsFiles)) {
2354 foreach ($this->jsFiles as $file => $properties) {
2355 $file = GeneralUtility::resolveBackPath($file);
2356 $file = GeneralUtility::createVersionNumberedFilename($file);
2357 $tag = '<script src="' . htmlspecialchars($file) . '" type="' . htmlspecialchars($properties['type']) . '"></script>';
2358 if ($properties['allWrap'] && strpos($properties['allWrap'], '|') !== FALSE) {
2359 $tag = str_replace('|', $tag, $properties['allWrap']);
2360 }
2361 if ($properties['forceOnTop']) {
2362 if ($properties['section'] === self::PART_HEADER) {
2363 $jsFiles = $tag . LF . $jsFiles;
2364 } else {
2365 $jsFooterFiles = $tag . LF . $jsFooterFiles;
2366 }
2367 } else {
2368 if ($properties['section'] === self::PART_HEADER) {
2369 $jsFiles .= LF . $tag;
2370 } else {
2371 $jsFooterFiles .= LF . $tag;
2372 }
2373 }
2374 }
2375 }
2376 if ($this->moveJsFromHeaderToFooter) {
2377 $jsFooterFiles = $jsFiles . LF . $jsFooterFiles;
2378 $jsFiles = '';
2379 }
2380 return array($jsFiles, $jsFooterFiles);
2381 }
2382
2383 /**
2384 * Render inline JavaScript
2385 *
2386 * @return array<string> jsInline and jsFooterInline string
2387 */
2388 protected function renderInlineJavaScript() {
2389 $jsInline = '';
2390 $jsFooterInline = '';
2391 if (count($this->jsInline)) {
2392 foreach ($this->jsInline as $name => $properties) {
2393 if ($properties['forceOnTop']) {
2394 if ($properties['section'] === self::PART_HEADER) {
2395 $jsInline = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF . $jsInline;
2396 } else {
2397 $jsFooterInline = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF . $jsFooterInline;
2398 }
2399 } else {
2400 if ($properties['section'] === self::PART_HEADER) {
2401 $jsInline .= '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2402 } else {
2403 $jsFooterInline .= '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2404 }
2405 }
2406 }
2407 }
2408 if ($jsInline) {
2409 $jsInline = $this->inlineJavascriptWrap[0] . $jsInline . $this->inlineJavascriptWrap[1];
2410 }
2411 if ($jsFooterInline) {
2412 $jsFooterInline = $this->inlineJavascriptWrap[0] . $jsFooterInline . $this->inlineJavascriptWrap[1];
2413 }
2414 if ($this->moveJsFromHeaderToFooter) {
2415 $jsFooterInline = $jsInline . LF . $jsFooterInline;
2416 $jsInline = '';
2417 }
2418 return array($jsInline, $jsFooterInline);
2419 }
2420
2421 /**
2422 * Include language file for inline usage
2423 *
2424 * @param string $fileRef
2425 * @param string $selectionPrefix
2426 * @param string $stripFromSelectionName
2427 * @param integer $errorMode
2428 * @return void
2429 * @throws \RuntimeException
2430 */
2431 protected function includeLanguageFileForInline($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0) {
2432 if (!isset($this->lang) || !isset($this->charSet)) {
2433 throw new \RuntimeException('Language and character encoding are not set.', 1284906026);
2434 }
2435 $labelsFromFile = array();
2436 $allLabels = $this->readLLfile($fileRef, $errorMode);
2437 // Regular expression to strip the selection prefix and possibly something from the label name:
2438 $labelPattern = '#^' . preg_quote($selectionPrefix, '#') . '(' . preg_quote($stripFromSelectionName, '#') . ')?#';
2439 if ($allLabels !== FALSE) {
2440 // Merge language specific translations:
2441 if ($this->lang !== 'default' && isset($allLabels[$this->lang])) {
2442 $labels = array_merge($allLabels['default'], $allLabels[$this->lang]);
2443 } else {
2444 $labels = $allLabels['default'];
2445 }
2446 // Iterate through all locallang labels:
2447 foreach ($labels as $label => $value) {
2448 if ($selectionPrefix === '') {
2449 $labelsFromFile[$label] = $value;
2450 } elseif (strpos($label, $selectionPrefix) === 0) {
2451 $key = preg_replace($labelPattern, '', $label);
2452 $labelsFromFile[$label] = $value;
2453 }
2454 }
2455 $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $labelsFromFile);
2456 }
2457 }
2458
2459 /**
2460 * Reads a locallang file.
2461 *
2462 * @param string $fileRef Reference to a relative filename to include.
2463 * @param integer $errorMode Error mode (when file could not be found): 0 - syslog entry, 1 - do nothing, 2 - throw an exception
2464 * @return array Returns the $LOCAL_LANG array found in the file. If no array found, returns empty array.
2465 */
2466 protected function readLLfile($fileRef, $errorMode = 0) {
2467 if ($this->lang !== 'default') {
2468 $languages = array_reverse($this->languageDependencies);
2469 // At least we need to have English
2470 if (empty($languages)) {
2471 $languages[] = 'default';
2472 }
2473 } else {
2474 $languages = array('default');
2475 }
2476
2477 $localLanguage = array();
2478 foreach ($languages as $language) {
2479 $tempLL = GeneralUtility::readLLfile($fileRef, $language, $this->charSet, $errorMode);
2480 $localLanguage['default'] = $tempLL['default'];
2481 if (!isset($localLanguage[$this->lang])) {
2482 $localLanguage[$this->lang] = $localLanguage['default'];
2483 }
2484 if ($this->lang !== 'default' && isset($tempLL[$language])) {
2485 // Merge current language labels onto labels from previous language
2486 // This way we have a labels with fall back applied
2487 $localLanguage[$this->lang] = GeneralUtility::array_merge_recursive_overrule($localLanguage[$this->lang], $tempLL[$language], FALSE, FALSE);
2488 }
2489 }
2490
2491 return $localLanguage;
2492 }
2493
2494
2495 /*****************************************************/
2496 /* */
2497 /* Tools */
2498 /* */
2499 /*****************************************************/
2500 /**
2501 * Concatenate files into one file
2502 * registered handler
2503 *
2504 * @return void
2505 */
2506 protected function doConcatenate() {
2507 $this->doConcatenateCss();
2508 $this->doConcatenateJavaScript();
2509 }
2510
2511 /**
2512 * Concatenate JavaScript files according to the configuration.
2513 *
2514 * @return void
2515 */
2516 protected function doConcatenateJavaScript() {
2517 if ($this->concatenateFiles || $this->concatenateJavascript) {
2518 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsConcatenateHandler'])) {
2519 // use external concatenation routine
2520 $params = array(
2521 'jsLibs' => &$this->jsLibs,
2522 'jsFiles' => &$this->jsFiles,
2523 'jsFooterFiles' => &$this->jsFooterFiles,
2524 'headerData' => &$this->headerData,
2525 'footerData' => &$this->footerData
2526 );
2527 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsConcatenateHandler'], $params, $this);
2528 } else {
2529 $this->jsLibs = $this->getCompressor()->concatenateJsFiles($this->jsLibs);
2530 $this->jsFiles = $this->getCompressor()->concatenateJsFiles($this->jsFiles);
2531 $this->jsFooterFiles = $this->getCompressor()->concatenateJsFiles($this->jsFooterFiles);
2532 }
2533 }
2534 }
2535
2536 /**
2537 * Concatenate CSS files according to configuration.
2538 *
2539 * @return void
2540 */
2541 protected function doConcatenateCss() {
2542 if ($this->concatenateFiles || $this->concatenateCss) {
2543 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssConcatenateHandler'])) {
2544 // use external concatenation routine
2545 $params = array(
2546 'cssFiles' => &$this->cssFiles,
2547 'headerData' => &$this->headerData,
2548 'footerData' => &$this->footerData
2549 );
2550 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssConcatenateHandler'], $params, $this);
2551 } else {
2552 $cssOptions = array();
2553 if (TYPO3_MODE === 'BE') {
2554 $cssOptions = array('baseDirectories' => $GLOBALS['TBE_TEMPLATE']->getSkinStylesheetDirectories());
2555 }
2556 $this->cssFiles = $this->getCompressor()->concatenateCssFiles($this->cssFiles, $cssOptions);
2557 }
2558 }
2559 }
2560
2561 /**
2562 * Compresses inline code
2563 *
2564 * @return void
2565 */
2566 protected function doCompress() {
2567 $this->doCompressJavaScript();
2568 $this->doCompressCss();
2569 }
2570
2571 /**
2572 * Compresses CSS according to configuration.
2573 *
2574 * @return void
2575 */
2576 protected function doCompressCss() {
2577 if ($this->compressCss) {
2578 // Use external compression routine
2579 $params = array(
2580 'cssInline' => &$this->cssInline,
2581 'cssFiles' => &$this->cssFiles,
2582 'headerData' => &$this->headerData,
2583 'footerData' => &$this->footerData
2584 );
2585 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'])) {
2586 // use external concatenation routine
2587 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'], $params, $this);
2588 } else {
2589 $this->cssFiles = $this->getCompressor()->compressCssFiles($this->cssFiles);
2590 }
2591 }
2592 }
2593
2594 /**
2595 * Compresses JavaScript according to configuration.
2596 *
2597 * @return void
2598 */
2599 protected function doCompressJavaScript() {
2600 if ($this->compressJavascript) {
2601 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'])) {
2602 // Use external compression routine
2603 $params = array(
2604 'jsInline' => &$this->jsInline,
2605 'jsFooterInline' => &$this->jsFooterInline,
2606 'jsLibs' => &$this->jsLibs,
2607 'jsFiles' => &$this->jsFiles,
2608 'jsFooterFiles' => &$this->jsFooterFiles,
2609 'headerData' => &$this->headerData,
2610 'footerData' => &$this->footerData
2611 );
2612 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'], $params, $this);
2613 } else {
2614 // Traverse the arrays, compress files
2615 if (count($this->jsInline)) {
2616 foreach ($this->jsInline as $name => $properties) {
2617 if ($properties['compress']) {
2618 $error = '';
2619 $this->jsInline[$name]['code'] = GeneralUtility::minifyJavaScript($properties['code'], $error);
2620 if ($error) {
2621 $this->compressError .= 'Error with minify JS Inline Block "' . $name . '": ' . $error . LF;
2622 }
2623 }
2624 }
2625 }
2626 $this->jsLibs = $this->getCompressor()->compressJsFiles($this->jsLibs);
2627 $this->jsFiles = $this->getCompressor()->compressJsFiles($this->jsFiles);
2628 $this->jsFooterFiles = $this->getCompressor()->compressJsFiles($this->jsFooterFiles);
2629 }
2630 }
2631 }
2632
2633 /**
2634 * Returns instance of \TYPO3\CMS\Core\Resource\ResourceCompressor
2635 *
2636 * @return \TYPO3\CMS\Core\Resource\ResourceCompressor
2637 */
2638 protected function getCompressor() {
2639 if ($this->compressor === NULL) {
2640 $this->compressor = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceCompressor');
2641 }
2642 return $this->compressor;
2643 }
2644
2645 /**
2646 * Processes a Javascript file dependent on the current context
2647 *
2648 * Adds the version number for Frontend, compresses the file for Backend
2649 *
2650 * @param string $filename Filename
2651 * @return string New filename
2652 */
2653 protected function processJsFile($filename) {
2654 switch (TYPO3_MODE) {
2655 case 'FE':
2656 if ($this->compressJavascript) {
2657 $filename = $this->getCompressor()->compressJsFile($filename);
2658 } else {
2659 $filename = GeneralUtility::createVersionNumberedFilename($filename);
2660 }
2661 break;
2662 case 'BE':
2663 if ($this->compressJavascript) {
2664 $filename = $this->getCompressor()->compressJsFile($filename);
2665 }
2666 break;
2667 }
2668 return $filename;
2669 }
2670
2671 /*****************************************************/
2672 /* */
2673 /* Hooks */
2674 /* */
2675 /*****************************************************/
2676 /**
2677 * Execute PreRenderHook for possible manuipulation
2678 *
2679 * @return void
2680 */
2681 protected function executePreRenderHook() {
2682 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'])) {
2683 $params = array(
2684 'jsLibs' => &$this->jsLibs,
2685 'jsFooterLibs' => &$this->jsFooterLibs,
2686 'jsFiles' => &$this->jsFiles,
2687 'jsFooterFiles' => &$this->jsFooterFiles,
2688 'cssFiles' => &$this->cssFiles,
2689 'headerData' => &$this->headerData,
2690 'footerData' => &$this->footerData,
2691 'jsInline' => &$this->jsInline,
2692 'jsFooterInline' => &$this->jsFooterInline,
2693 'cssInline' => &$this->cssInline
2694 );
2695 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'] as $hook) {
2696 GeneralUtility::callUserFunction($hook, $params, $this);
2697 }
2698 }
2699 }
2700
2701 /**
2702 * PostTransform for possible manuipulation of concatenated and compressed files
2703 *
2704 * @return void
2705 */
2706 protected function executeRenderPostTransformHook() {
2707 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform'])) {
2708 $params = array(
2709 'jsLibs' => &$this->jsLibs,
2710 'jsFooterLibs' => &$this->jsFooterLibs,
2711 'jsFiles' => &$this->jsFiles,
2712 'jsFooterFiles' => &$this->jsFooterFiles,
2713 'cssFiles' => &$this->cssFiles,
2714 'headerData' => &$this->headerData,
2715 'footerData' => &$this->footerData,
2716 'jsInline' => &$this->jsInline,
2717 'jsFooterInline' => &$this->jsFooterInline,
2718 'cssInline' => &$this->cssInline
2719 );
2720 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform'] as $hook) {
2721 GeneralUtility::callUserFunction($hook, $params, $this);
2722 }
2723 }
2724 }
2725
2726 /**
2727 * Execute postRenderHook for possible manipulation
2728 *
2729 * @param $jsLibs string
2730 * @param $jsFiles string
2731 * @param $jsFooterFiles string
2732 * @param $cssFiles string
2733 * @param $jsInline string
2734 * @param $cssInline string
2735 * @param $jsFooterInline string
2736 * @param $jsFooterLibs string
2737 * @return void
2738 */
2739 protected function executePostRenderHook(&$jsLibs, &$jsFiles, &$jsFooterFiles, &$cssFiles, &$jsInline, &$cssInline, &$jsFooterInline, &$jsFooterLibs) {
2740 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'])) {
2741 $params = array(
2742 'jsLibs' => &$jsLibs,
2743 'jsFiles' => &$jsFiles,
2744 'jsFooterFiles' => &$jsFooterFiles,
2745 'cssFiles' => &$cssFiles,
2746 'headerData' => &$this->headerData,
2747 'footerData' => &$this->footerData,
2748 'jsInline' => &$jsInline,
2749 'cssInline' => &$cssInline,
2750 'xmlPrologAndDocType' => &$this->xmlPrologAndDocType,
2751 'htmlTag' => &$this->htmlTag,
2752 'headTag' => &$this->headTag,
2753 'charSet' => &$this->charSet,
2754 'metaCharsetTag' => &$this->metaCharsetTag,
2755 'shortcutTag' => &$this->shortcutTag,
2756 'inlineComments' => &$this->inlineComments,
2757 'baseUrl' => &$this->baseUrl,
2758 'baseUrlTag' => &$this->baseUrlTag,
2759 'favIcon' => &$this->favIcon,
2760 'iconMimeType' => &$this->iconMimeType,
2761 'titleTag' => &$this->titleTag,
2762 'title' => &$this->title,
2763 'metaTags' => &$this->metaTags,
2764 'jsFooterInline' => &$jsFooterInline,
2765 'jsFooterLibs' => &$jsFooterLibs,
2766 'bodyContent' => &$this->bodyContent
2767 );
2768 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'] as $hook) {
2769 GeneralUtility::callUserFunction($hook, $params, $this);
2770 }
2771 }
2772 }
2773
2774 }
2775
2776
2777 ?>