[TASK] Upgrade jQuery to 1.11.0
[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 text file 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.11.0';
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 * @param string $splitChar The char used to split the allWrap value, default is "|"
1199 * @return void
1200 */
1201 public function addJsLibrary($name, $file, $type = 'text/javascript', $compress = FALSE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|') {
1202 if (!$type) {
1203 $type = 'text/javascript';
1204 }
1205 if (!in_array(strtolower($name), $this->jsLibs)) {
1206 $this->jsLibs[strtolower($name)] = array(
1207 'file' => $file,
1208 'type' => $type,
1209 'section' => self::PART_HEADER,
1210 'compress' => $compress,
1211 'forceOnTop' => $forceOnTop,
1212 'allWrap' => $allWrap,
1213 'excludeFromConcatenation' => $excludeFromConcatenation,
1214 'splitChar' => $splitChar
1215 );
1216 }
1217 }
1218
1219 /**
1220 * Adds JS Library to Footer. JS Library block is rendered on top of the Footer JS files.
1221 *
1222 * @param string $name Arbitrary identifier
1223 * @param string $file File name
1224 * @param string $type Content Type
1225 * @param boolean $compress Flag if library should be compressed
1226 * @param boolean $forceOnTop Flag if added library should be inserted at begin of this block
1227 * @param string $allWrap
1228 * @param boolean $excludeFromConcatenation
1229 * @param string $splitChar The char used to split the allWrap value, default is "|"
1230 * @return void
1231 */
1232 public function addJsFooterLibrary($name, $file, $type = 'text/javascript', $compress = FALSE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|') {
1233 if (!$type) {
1234 $type = 'text/javascript';
1235 }
1236 if (!in_array(strtolower($name), $this->jsLibs)) {
1237 $this->jsLibs[strtolower($name)] = array(
1238 'file' => $file,
1239 'type' => $type,
1240 'section' => self::PART_FOOTER,
1241 'compress' => $compress,
1242 'forceOnTop' => $forceOnTop,
1243 'allWrap' => $allWrap,
1244 'excludeFromConcatenation' => $excludeFromConcatenation,
1245 'splitChar' => $splitChar
1246 );
1247 }
1248 }
1249
1250 /**
1251 * Adds JS file
1252 *
1253 * @param string $file File name
1254 * @param string $type Content Type
1255 * @param boolean $compress
1256 * @param boolean $forceOnTop
1257 * @param string $allWrap
1258 * @param boolean $excludeFromConcatenation
1259 * @param string $splitChar The char used to split the allWrap value, default is "|"
1260 * @return void
1261 */
1262 public function addJsFile($file, $type = 'text/javascript', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|') {
1263 if (!$type) {
1264 $type = 'text/javascript';
1265 }
1266 if (!isset($this->jsFiles[$file])) {
1267 if (strpos($file, 'ajax.php?') !== FALSE) {
1268 $compress = FALSE;
1269 }
1270 $this->jsFiles[$file] = array(
1271 'file' => $file,
1272 'type' => $type,
1273 'section' => self::PART_HEADER,
1274 'compress' => $compress,
1275 'forceOnTop' => $forceOnTop,
1276 'allWrap' => $allWrap,
1277 'excludeFromConcatenation' => $excludeFromConcatenation,
1278 'splitChar' => $splitChar
1279 );
1280 }
1281 }
1282
1283 /**
1284 * Adds JS file to footer
1285 *
1286 * @param string $file File name
1287 * @param string $type Content Type
1288 * @param boolean $compress
1289 * @param boolean $forceOnTop
1290 * @param string $allWrap
1291 * @param boolean $excludeFromConcatenation
1292 * @param string $splitChar The char used to split the allWrap value, default is "|"
1293 * @return void
1294 */
1295 public function addJsFooterFile($file, $type = 'text/javascript', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|') {
1296 if (!$type) {
1297 $type = 'text/javascript';
1298 }
1299 if (!isset($this->jsFiles[$file])) {
1300 if (strpos($file, 'ajax.php?') !== FALSE) {
1301 $compress = FALSE;
1302 }
1303 $this->jsFiles[$file] = array(
1304 'file' => $file,
1305 'type' => $type,
1306 'section' => self::PART_FOOTER,
1307 'compress' => $compress,
1308 'forceOnTop' => $forceOnTop,
1309 'allWrap' => $allWrap,
1310 'excludeFromConcatenation' => $excludeFromConcatenation,
1311 'splitChar' => $splitChar
1312 );
1313 }
1314 }
1315
1316 /**
1317 * Adds JS inline code
1318 *
1319 * @param string $name
1320 * @param string $block
1321 * @param boolean $compress
1322 * @param boolean $forceOnTop
1323 * @return void
1324 */
1325 public function addJsInlineCode($name, $block, $compress = TRUE, $forceOnTop = FALSE) {
1326 if (!isset($this->jsInline[$name]) && !empty($block)) {
1327 $this->jsInline[$name] = array(
1328 'code' => $block . LF,
1329 'section' => self::PART_HEADER,
1330 'compress' => $compress,
1331 'forceOnTop' => $forceOnTop
1332 );
1333 }
1334 }
1335
1336 /**
1337 * Adds JS inline code to footer
1338 *
1339 * @param string $name
1340 * @param string $block
1341 * @param boolean $compress
1342 * @param boolean $forceOnTop
1343 * @return void
1344 */
1345 public function addJsFooterInlineCode($name, $block, $compress = TRUE, $forceOnTop = FALSE) {
1346 if (!isset($this->jsInline[$name]) && !empty($block)) {
1347 $this->jsInline[$name] = array(
1348 'code' => $block . LF,
1349 'section' => self::PART_FOOTER,
1350 'compress' => $compress,
1351 'forceOnTop' => $forceOnTop
1352 );
1353 }
1354 }
1355
1356 /**
1357 * Adds Ext.onready code, which will be wrapped in Ext.onReady(function() {...});
1358 *
1359 * @param string $block Javascript code
1360 * @param boolean $forceOnTop Position of the javascript code (TRUE for putting it on top, default is FALSE = bottom)
1361 * @return void
1362 */
1363 public function addExtOnReadyCode($block, $forceOnTop = FALSE) {
1364 if (!in_array($block, $this->extOnReadyCode)) {
1365 if ($forceOnTop) {
1366 array_unshift($this->extOnReadyCode, $block);
1367 } else {
1368 $this->extOnReadyCode[] = $block;
1369 }
1370 }
1371 }
1372
1373 /**
1374 * Adds the ExtDirect code
1375 *
1376 * @param array $filterNamespaces Limit the output to defined namespaces. If empty, all namespaces are generated
1377 * @return void
1378 */
1379 public function addExtDirectCode(array $filterNamespaces = array()) {
1380 if ($this->extDirectCodeAdded) {
1381 return;
1382 }
1383 $this->extDirectCodeAdded = TRUE;
1384 if (count($filterNamespaces) === 0) {
1385 $filterNamespaces = array('TYPO3');
1386 }
1387 // For ExtDirect we need flash message support
1388 $this->addJsFile(GeneralUtility::resolveBackPath($this->backPath . 'sysext/backend/Resources/Public/JavaScript/flashmessages.js'));
1389 // Add language labels for ExtDirect
1390 if (TYPO3_MODE === 'FE') {
1391 $this->addInlineLanguageLabelArray(array(
1392 'extDirect_timeoutHeader' => $GLOBALS['TSFE']->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutHeader'),
1393 'extDirect_timeoutMessage' => $GLOBALS['TSFE']->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutMessage')
1394 ));
1395 } else {
1396 $this->addInlineLanguageLabelArray(array(
1397 'extDirect_timeoutHeader' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutHeader'),
1398 'extDirect_timeoutMessage' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutMessage')
1399 ));
1400 }
1401 $token = ($api = '');
1402 if (TYPO3_MODE === 'BE') {
1403 $formprotection = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get();
1404 $token = $formprotection->generateToken('extDirect');
1405 }
1406 /** @var $extDirect \TYPO3\CMS\Core\ExtDirect\ExtDirectApi */
1407 $extDirect = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\ExtDirect\\ExtDirectApi');
1408 $api = $extDirect->getApiPhp($filterNamespaces);
1409 if ($api) {
1410 $this->addJsInlineCode('TYPO3ExtDirectAPI', $api, FALSE);
1411 }
1412 // Note: we need to iterate thru the object, because the addProvider method
1413 // does this only with multiple arguments
1414 $this->addExtOnReadyCode('
1415 (function() {
1416 TYPO3.ExtDirectToken = "' . $token . '";
1417 for (var api in Ext.app.ExtDirectAPI) {
1418 var provider = Ext.Direct.addProvider(Ext.app.ExtDirectAPI[api]);
1419 provider.on("beforecall", function(provider, transaction, meta) {
1420 if (transaction.data) {
1421 transaction.data[transaction.data.length] = TYPO3.ExtDirectToken;
1422 } else {
1423 transaction.data = [TYPO3.ExtDirectToken];
1424 }
1425 });
1426
1427 provider.on("call", function(provider, transaction, meta) {
1428 if (transaction.isForm) {
1429 transaction.params.securityToken = TYPO3.ExtDirectToken;
1430 }
1431 });
1432 }
1433 })();
1434
1435 var extDirectDebug = function(message, header, group) {
1436 var TYPO3ViewportInstance = null;
1437
1438 if (top && top.TYPO3 && typeof top.TYPO3.Backend === "object") {
1439 TYPO3ViewportInstance = top.TYPO3.Backend;
1440 } else if (typeof TYPO3 === "object" && typeof TYPO3.Backend === "object") {
1441 TYPO3ViewportInstance = TYPO3.Backend;
1442 }
1443
1444 if (TYPO3ViewportInstance !== null) {
1445 TYPO3ViewportInstance.DebugConsole.addTab(message, header, group);
1446 } else if (typeof console === "object") {
1447 console.log(message);
1448 } else {
1449 document.write(message);
1450 }
1451 };
1452
1453 Ext.Direct.on("exception", function(event) {
1454 if (event.code === Ext.Direct.exceptions.TRANSPORT && !event.where) {
1455 TYPO3.Flashmessage.display(
1456 TYPO3.Severity.error,
1457 TYPO3.l10n.localize("extDirect_timeoutHeader"),
1458 TYPO3.l10n.localize("extDirect_timeoutMessage"),
1459 30
1460 );
1461 } else {
1462 var backtrace = "";
1463 if (event.code === "parse") {
1464 extDirectDebug(
1465 "<p>" + event.xhr.responseText + "<\\/p>",
1466 event.type,
1467 "ExtDirect - Exception"
1468 );
1469 } else if (event.code === "router") {
1470 TYPO3.Flashmessage.display(
1471 TYPO3.Severity.error,
1472 event.code,
1473 event.message,
1474 30
1475 );
1476 } else if (event.where) {
1477 backtrace = "<p style=\\"margin-top: 20px;\\">" +
1478 "<strong>Backtrace:<\\/strong><br \\/>" +
1479 event.where.replace(/#/g, "<br \\/>#") +
1480 "<\\/p>";
1481 extDirectDebug(
1482 "<p>" + event.message + "<\\/p>" + backtrace,
1483 event.method,
1484 "ExtDirect - Exception"
1485 );
1486 }
1487
1488
1489 }
1490 });
1491
1492 Ext.Direct.on("event", function(event, provider) {
1493 if (typeof event.debug !== "undefined" && event.debug !== "") {
1494 extDirectDebug(event.debug, event.method, "ExtDirect - Debug");
1495 }
1496 });
1497 ', TRUE);
1498 }
1499
1500 /**
1501 * Adds CSS file
1502 *
1503 * @param string $file
1504 * @param string $rel
1505 * @param string $media
1506 * @param string $title
1507 * @param boolean $compress
1508 * @param boolean $forceOnTop
1509 * @param string $allWrap
1510 * @param boolean $excludeFromConcatenation
1511 * @param string $splitChar The char used to split the allWrap value, default is "|"
1512 * @return void
1513 */
1514 public function addCssFile($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|') {
1515 if (!isset($this->cssFiles[$file])) {
1516 $this->cssFiles[$file] = array(
1517 'file' => $file,
1518 'rel' => $rel,
1519 'media' => $media,
1520 'title' => $title,
1521 'compress' => $compress,
1522 'forceOnTop' => $forceOnTop,
1523 'allWrap' => $allWrap,
1524 'excludeFromConcatenation' => $excludeFromConcatenation,
1525 'splitChar' => $splitChar
1526 );
1527 }
1528 }
1529
1530 /**
1531 * Adds CSS inline code
1532 *
1533 * @param string $name
1534 * @param string $block
1535 * @param boolean $compress
1536 * @param boolean $forceOnTop
1537 * @return void
1538 */
1539 public function addCssInlineBlock($name, $block, $compress = FALSE, $forceOnTop = FALSE) {
1540 if (!isset($this->cssInline[$name]) && !empty($block)) {
1541 $this->cssInline[$name] = array(
1542 'code' => $block,
1543 'compress' => $compress,
1544 'forceOnTop' => $forceOnTop
1545 );
1546 }
1547 }
1548
1549 /**
1550 * Call this function if you need to include the jQuery library
1551 *
1552 * @param null|string $version The jQuery version that should be included, either "latest" or any available version
1553 * @param null|string $source The location of the jQuery source, can be "local", "google", "msn", "jquery" or just an URL to your jQuery lib
1554 * @param string $namespace The namespace in which the jQuery object of the specific version should be stored.
1555 * @return void
1556 * @throws \UnexpectedValueException
1557 */
1558 public function loadJquery($version = NULL, $source = NULL, $namespace = self::JQUERY_NAMESPACE_DEFAULT) {
1559 // Set it to the version that is shipped with the TYPO3 core
1560 if ($version === NULL || $version === 'latest') {
1561 $version = self::JQUERY_VERSION_LATEST;
1562 }
1563 // Check if the source is set, otherwise set it to "default"
1564 if ($source === NULL) {
1565 $source = 'local';
1566 }
1567 if ($source === 'local' && !in_array($version, $this->availableLocalJqueryVersions)) {
1568 throw new \UnexpectedValueException('The requested jQuery version is not available in the local filesystem.', 1341505305);
1569 }
1570 if (!preg_match('/^[a-zA-Z0-9]+$/', $namespace)) {
1571 throw new \UnexpectedValueException('The requested namespace contains non alphanumeric characters.', 1341571604);
1572 }
1573 $this->jQueryVersions[$namespace] = array(
1574 'version' => $version,
1575 'source' => $source
1576 );
1577 }
1578
1579 /**
1580 * Call function if you need the requireJS library
1581 * this automatically adds the JavaScript path of all loaded extensions in the requireJS path option
1582 * so it resolves names like TYPO3/CMS/MyExtension/MyJsFile to EXT:MyExtension/Resources/Public/JavaScript/MyJsFile.js
1583 * when using requireJS
1584 *
1585 * @return void
1586 */
1587 public function loadRequireJs() {
1588
1589 // load all paths to map to package names / namespaces
1590 if (count($this->requireJsConfig) === 0) {
1591 // first, load all paths for the namespaces
1592 $this->requireJsConfig['paths'] = array();
1593 // get all extensions that are loaded
1594 $loadedExtensions = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getLoadedExtensionListArray();
1595 foreach ($loadedExtensions as $packageName) {
1596 $fullJsPath = 'EXT:' . $packageName . '/Resources/Public/JavaScript/';
1597 $fullJsPath = GeneralUtility::getFileAbsFileName($fullJsPath);
1598 $fullJsPath = \TYPO3\CMS\Core\Utility\PathUtility::getRelativePath(PATH_typo3, $fullJsPath);
1599 $fullJsPath = rtrim($fullJsPath, '/');
1600 if ($fullJsPath) {
1601 $this->requireJsConfig['paths']['TYPO3/CMS/' . GeneralUtility::underscoredToUpperCamelCase($packageName)] = $this->backPath . $fullJsPath;
1602 }
1603 }
1604
1605 // check if additional AMD modules need to be loaded if a single AMD module is initialized
1606 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules'])) {
1607 $this->addInlineSettingArray('RequireJS.PostInitializationModules', $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules']);
1608 }
1609 }
1610
1611 $this->addRequireJs = TRUE;
1612 }
1613
1614 /**
1615 * includes a AMD-compatible JS file by resolving the ModuleName, and then requires the file via a requireJS request
1616 *
1617 * this function only works for AMD-ready JS modules, used like "define('TYPO3/CMS/Backend/FormEngine..."
1618 * in the JS file
1619 *
1620 * TYPO3/CMS/Backend/FormEngine =>
1621 * "TYPO3": Vendor Name
1622 * "CMS": Product Name
1623 * "Backend": Extension Name
1624 * "FormEngine": FileName in the Resources/Public/JavaScript folder
1625 *
1626 * @param $mainModuleName must be in the form of "TYPO3/CMS/PackageName/ModuleName" e.g. "TYPO3/CMS/Backend/FormEngine"
1627 * @return void
1628 */
1629 public function loadRequireJsModule($mainModuleName) {
1630
1631 // make sure requireJS is initialized
1632 $this->loadRequireJs();
1633
1634 // execute the main module
1635 $this->addJsInlineCode('RequireJS-Module-' . $mainModuleName, 'require(["' . $mainModuleName . '"]);');
1636 }
1637
1638 /**
1639 * Call function if you need the prototype library
1640 *
1641 * @return void
1642 */
1643 public function loadPrototype() {
1644 $this->addPrototype = TRUE;
1645 }
1646
1647 /**
1648 * Call function if you need the Scriptaculous library
1649 *
1650 * @param string $modules Add modules you need. use "all" if you need complete modules
1651 * @return void
1652 */
1653 public function loadScriptaculous($modules = 'all') {
1654 // Scriptaculous require prototype, so load prototype too.
1655 $this->addPrototype = TRUE;
1656 $this->addScriptaculous = TRUE;
1657 if ($modules) {
1658 if ($modules == 'all') {
1659 foreach ($this->addScriptaculousModules as $key => $value) {
1660 $this->addScriptaculousModules[$key] = TRUE;
1661 }
1662 } else {
1663 $mods = GeneralUtility::trimExplode(',', $modules);
1664 foreach ($mods as $mod) {
1665 if (isset($this->addScriptaculousModules[strtolower($mod)])) {
1666 $this->addScriptaculousModules[strtolower($mod)] = TRUE;
1667 }
1668 }
1669 }
1670 }
1671 }
1672
1673 /**
1674 * call this function if you need the extJS library
1675 *
1676 * @param boolean $css Flag, if set the ext-css will be loaded
1677 * @param boolean $theme Flag, if set the ext-theme "grey" will be loaded
1678 * @param string $adapter Choose alternative adapter, possible values: yui, prototype, jquery
1679 * @return void
1680 */
1681 public function loadExtJS($css = TRUE, $theme = TRUE, $adapter = '') {
1682 if ($adapter) {
1683 // Empty $adapter will always load the ext adapter
1684 switch (GeneralUtility::strtolower(trim($adapter))) {
1685 case self::EXTJS_ADAPTER_YUI:
1686 $this->extJSadapter = 'yui/ext-yui-adapter.js';
1687 break;
1688 case self::EXTJS_ADAPTER_PROTOTYPE:
1689 $this->extJSadapter = 'prototype/ext-prototype-adapter.js';
1690 break;
1691 case self::EXTJS_ADAPTER_JQUERY:
1692 $this->extJSadapter = 'jquery/ext-jquery-adapter.js';
1693 break;
1694 }
1695 }
1696 $this->addExtJS = TRUE;
1697 $this->extJStheme = $theme;
1698 $this->extJScss = $css;
1699 }
1700
1701 /**
1702 * Enables ExtJs QuickTips
1703 * Need extJs loaded
1704 *
1705 * @return void
1706 */
1707 public function enableExtJSQuickTips() {
1708 $this->enableExtJSQuickTips = TRUE;
1709 }
1710
1711 /**
1712 * Call function if you need the ExtCore library
1713 *
1714 * @return void
1715 */
1716 public function loadExtCore() {
1717 $this->addExtCore = TRUE;
1718 }
1719
1720 /**
1721 * Call function if you need the SVG library
1722 *
1723 * @return void
1724 */
1725 public function loadSvg() {
1726 $this->addSvg = TRUE;
1727 }
1728
1729 /**
1730 * Call this function to load debug version of ExtJS. Use this for development only
1731 *
1732 * @return void
1733 */
1734 public function enableSvgDebug() {
1735 $this->enableSvgDebug = TRUE;
1736 }
1737
1738 /**
1739 * Call this function to force flash usage with SVG library
1740 *
1741 * @return void
1742 */
1743 public function svgForceFlash() {
1744 $this->addMetaTag('<meta name="svg.render.forceflash" content="true" />');
1745 }
1746
1747 /**
1748 * Call this function to load debug version of ExtJS. Use this for development only
1749 *
1750 * @return void
1751 */
1752 public function enableExtJsDebug() {
1753 $this->enableExtJsDebug = TRUE;
1754 }
1755
1756 /**
1757 * Call this function to load debug version of ExtCore. Use this for development only
1758 *
1759 * @return void
1760 */
1761 public function enableExtCoreDebug() {
1762 $this->enableExtCoreDebug = TRUE;
1763 }
1764
1765 /**
1766 * Adds Javascript Inline Label. This will occur in TYPO3.lang - object
1767 * The label can be used in scripts with TYPO3.lang.<key>
1768 * Need extJs loaded
1769 *
1770 * @param string $key
1771 * @param string $value
1772 * @return void
1773 */
1774 public function addInlineLanguageLabel($key, $value) {
1775 $this->inlineLanguageLabels[$key] = $value;
1776 }
1777
1778 /**
1779 * Adds Javascript Inline Label Array. This will occur in TYPO3.lang - object
1780 * The label can be used in scripts with TYPO3.lang.<key>
1781 * Array will be merged with existing array.
1782 * Need extJs loaded
1783 *
1784 * @param array $array
1785 * @return void
1786 */
1787 public function addInlineLanguageLabelArray(array $array) {
1788 $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $array);
1789 }
1790
1791 /**
1792 * Gets labels to be used in JavaScript fetched from a locallang file.
1793 *
1794 * @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.
1795 * @param string $selectionPrefix Prefix to select the correct labels (default: '')
1796 * @param string $stripFromSelectionName Sub-prefix to be removed from label names in the result (default: '')
1797 * @param integer $errorMode Error mode (when file could not be found): 0 - syslog entry, 1 - do nothing, 2 - throw an exception
1798 * @return void
1799 */
1800 public function addInlineLanguageLabelFile($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0) {
1801 $index = md5($fileRef . $selectionPrefix . $stripFromSelectionName);
1802 if ($fileRef && !isset($this->inlineLanguageLabelFiles[$index])) {
1803 $this->inlineLanguageLabelFiles[$index] = array(
1804 'fileRef' => $fileRef,
1805 'selectionPrefix' => $selectionPrefix,
1806 'stripFromSelectionName' => $stripFromSelectionName,
1807 'errorMode' => $errorMode
1808 );
1809 }
1810 }
1811
1812 /**
1813 * Adds Javascript Inline Setting. This will occur in TYPO3.settings - object
1814 * The label can be used in scripts with TYPO3.setting.<key>
1815 * Need extJs loaded
1816 *
1817 * @param string $namespace
1818 * @param string $key
1819 * @param string $value
1820 * @return void
1821 */
1822 public function addInlineSetting($namespace, $key, $value) {
1823 if ($namespace) {
1824 if (strpos($namespace, '.')) {
1825 $parts = explode('.', $namespace);
1826 $a = &$this->inlineSettings;
1827 foreach ($parts as $part) {
1828 $a = &$a[$part];
1829 }
1830 $a[$key] = $value;
1831 } else {
1832 $this->inlineSettings[$namespace][$key] = $value;
1833 }
1834 } else {
1835 $this->inlineSettings[$key] = $value;
1836 }
1837 }
1838
1839 /**
1840 * Adds Javascript Inline Setting. This will occur in TYPO3.settings - object
1841 * The label can be used in scripts with TYPO3.setting.<key>
1842 * Array will be merged with existing array.
1843 * Need extJs loaded
1844 *
1845 * @param string $namespace
1846 * @param array $array
1847 * @return void
1848 */
1849 public function addInlineSettingArray($namespace, array $array) {
1850 if ($namespace) {
1851 if (strpos($namespace, '.')) {
1852 $parts = explode('.', $namespace);
1853 $a = &$this->inlineSettings;
1854 foreach ($parts as $part) {
1855 $a = &$a[$part];
1856 }
1857 $a = array_merge((array) $a, $array);
1858 } else {
1859 $this->inlineSettings[$namespace] = array_merge((array) $this->inlineSettings[$namespace], $array);
1860 }
1861 } else {
1862 $this->inlineSettings = array_merge($this->inlineSettings, $array);
1863 }
1864 }
1865
1866 /**
1867 * Adds content to body content
1868 *
1869 * @param string $content
1870 * @return void
1871 */
1872 public function addBodyContent($content) {
1873 $this->bodyContent .= $content;
1874 }
1875
1876 /*****************************************************/
1877 /* */
1878 /* Render Functions */
1879 /* */
1880 /*****************************************************/
1881 /**
1882 * Render the section (Header or Footer)
1883 *
1884 * @param integer $part Section which should be rendered: self::PART_COMPLETE, self::PART_HEADER or self::PART_FOOTER
1885 * @return string Content of rendered section
1886 */
1887 public function render($part = self::PART_COMPLETE) {
1888 $this->prepareRendering();
1889 list($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs) = $this->renderJavaScriptAndCss();
1890 $metaTags = implode(LF, $this->metaTags);
1891 $markerArray = $this->getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags);
1892 $template = $this->getTemplateForPart($part);
1893 $this->reset();
1894 return trim(\TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($template, $markerArray, '###|###'));
1895 }
1896
1897 /**
1898 * Render the page but not the JavaScript and CSS Files
1899 *
1900 * @param string $substituteHash The hash that is used for the placehoder markers
1901 * @access private
1902 * @return string Content of rendered section
1903 */
1904 public function renderPageWithUncachedObjects($substituteHash) {
1905 $this->prepareRendering();
1906 $markerArray = $this->getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash);
1907 $template = $this->getTemplateForPart(self::PART_COMPLETE);
1908 return trim(\TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($template, $markerArray, '###|###'));
1909 }
1910
1911 /**
1912 * Renders the JavaScript and CSS files that have been added during processing
1913 * of uncached content objects (USER_INT, COA_INT)
1914 *
1915 * @param string $cachedPageContent
1916 * @param string $substituteHash The hash that is used for the placehoder markers
1917 * @access private
1918 * @return string
1919 */
1920 public function renderJavaScriptAndCssForProcessingOfUncachedContentObjects($cachedPageContent, $substituteHash) {
1921 $this->prepareRendering();
1922 list($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs) = $this->renderJavaScriptAndCss();
1923 $markerArray = array(
1924 '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->' => $cssFiles,
1925 '<!-- ###CSS_INLINE' . $substituteHash . '### -->' => $cssInline,
1926 '<!-- ###JS_INLINE' . $substituteHash . '### -->' => $jsInline,
1927 '<!-- ###JS_INCLUDE' . $substituteHash . '### -->' => $jsFiles,
1928 '<!-- ###JS_LIBS' . $substituteHash . '### -->' => $jsLibs,
1929 '<!-- ###HEADERDATA' . $substituteHash . '### -->' => implode(LF, $this->headerData),
1930 '<!-- ###FOOTERDATA' . $substituteHash . '### -->' => implode(LF, $this->footerData),
1931 '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->' => $jsFooterLibs,
1932 '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->' => $jsFooterFiles,
1933 '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->' => $jsFooterInline
1934 );
1935 foreach ($markerArray as $placeHolder => $content) {
1936 $cachedPageContent = str_replace($placeHolder, $content, $cachedPageContent);
1937 }
1938 $this->reset();
1939 return $cachedPageContent;
1940 }
1941
1942 /**
1943 * Remove ending slashes from static header block
1944 * if the page is beeing rendered as html (not xhtml)
1945 * and define property $this->endingSlash for further use
1946 *
1947 * @return void
1948 */
1949 protected function prepareRendering() {
1950 if ($this->getRenderXhtml()) {
1951 $this->endingSlash = ' /';
1952 } else {
1953 $this->metaCharsetTag = str_replace(' />', '>', $this->metaCharsetTag);
1954 $this->baseUrlTag = str_replace(' />', '>', $this->baseUrlTag);
1955 $this->shortcutTag = str_replace(' />', '>', $this->shortcutTag);
1956 $this->endingSlash = '';
1957 }
1958 }
1959
1960 /**
1961 * Renders all JavaScript and CSS
1962 *
1963 * @return array<string>
1964 */
1965 protected function renderJavaScriptAndCss() {
1966 $this->executePreRenderHook();
1967 $mainJsLibs = $this->renderMainJavaScriptLibraries();
1968 if ($this->concatenateFiles || $this->concatenateJavascript || $this->concatenateCss) {
1969 // Do the file concatenation
1970 $this->doConcatenate();
1971 }
1972 if ($this->compressCss || $this->compressJavascript) {
1973 // Do the file compression
1974 $this->doCompress();
1975 }
1976 $this->executeRenderPostTransformHook();
1977 $cssFiles = $this->renderCssFiles();
1978 $cssInline = $this->renderCssInline();
1979 list($jsLibs, $jsFooterLibs) = $this->renderAdditionalJavaScriptLibraries();
1980 list($jsFiles, $jsFooterFiles) = $this->renderJavaScriptFiles();
1981 list($jsInline, $jsFooterInline) = $this->renderInlineJavaScript();
1982 $jsLibs = $mainJsLibs . $jsLibs;
1983 if ($this->moveJsFromHeaderToFooter) {
1984 $jsFooterLibs = $jsLibs . LF . $jsFooterLibs;
1985 $jsLibs = '';
1986 $jsFooterFiles = $jsFiles . LF . $jsFooterFiles;
1987 $jsFiles = '';
1988 $jsFooterInline = $jsInline . LF . $jsFooterInline;
1989 $jsInline = '';
1990 }
1991 $this->executePostRenderHook($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs);
1992 return array($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs);
1993 }
1994
1995 /**
1996 * Fills the marker array with the given strings and trims each value
1997 *
1998 * @param $jsLibs string
1999 * @param $jsFiles string
2000 * @param $jsFooterFiles string
2001 * @param $cssFiles string
2002 * @param $jsInline string
2003 * @param $cssInline string
2004 * @param $jsFooterInline string
2005 * @param $jsFooterLibs string
2006 * @param $metaTags string
2007 * @return array Marker array
2008 */
2009 protected function getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags) {
2010 $markerArray = array(
2011 'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
2012 'HTMLTAG' => $this->htmlTag,
2013 'HEADTAG' => $this->headTag,
2014 'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
2015 'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
2016 'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
2017 'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
2018 'CSS_INCLUDE' => $cssFiles,
2019 'CSS_INLINE' => $cssInline,
2020 'JS_INLINE' => $jsInline,
2021 'JS_INCLUDE' => $jsFiles,
2022 'JS_LIBS' => $jsLibs,
2023 'TITLE' => $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '',
2024 'META' => $metaTags,
2025 'HEADERDATA' => $this->headerData ? implode(LF, $this->headerData) : '',
2026 'FOOTERDATA' => $this->footerData ? implode(LF, $this->footerData) : '',
2027 'JS_LIBS_FOOTER' => $jsFooterLibs,
2028 'JS_INCLUDE_FOOTER' => $jsFooterFiles,
2029 'JS_INLINE_FOOTER' => $jsFooterInline,
2030 'BODY' => $this->bodyContent
2031 );
2032 $markerArray = array_map('trim', $markerArray);
2033 return $markerArray;
2034 }
2035
2036 /**
2037 * Fills the marker array with the given strings and trims each value
2038 *
2039 * @param string $substituteHash The hash that is used for the placehoder markers
2040 * @return array Marker array
2041 */
2042 protected function getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash) {
2043 $markerArray = array(
2044 'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
2045 'HTMLTAG' => $this->htmlTag,
2046 'HEADTAG' => $this->headTag,
2047 'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
2048 'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
2049 'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
2050 'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
2051 'TITLE' => $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '',
2052 'META' => implode(LF, $this->metaTags),
2053 'BODY' => $this->bodyContent,
2054 'CSS_INCLUDE' => '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->',
2055 'CSS_INLINE' => '<!-- ###CSS_INLINE' . $substituteHash . '### -->',
2056 'JS_INLINE' => '<!-- ###JS_INLINE' . $substituteHash . '### -->',
2057 'JS_INCLUDE' => '<!-- ###JS_INCLUDE' . $substituteHash . '### -->',
2058 'JS_LIBS' => '<!-- ###JS_LIBS' . $substituteHash . '### -->',
2059 'HEADERDATA' => '<!-- ###HEADERDATA' . $substituteHash . '### -->',
2060 'FOOTERDATA' => '<!-- ###FOOTERDATA' . $substituteHash . '### -->',
2061 'JS_LIBS_FOOTER' => '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->',
2062 'JS_INCLUDE_FOOTER' => '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->',
2063 'JS_INLINE_FOOTER' => '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->'
2064 );
2065 $markerArray = array_map('trim', $markerArray);
2066 return $markerArray;
2067 }
2068
2069 /**
2070 * Reads the template file and returns the requested part as string
2071 *
2072 * @param integer $part
2073 * @return string
2074 */
2075 protected function getTemplateForPart($part) {
2076 $templateFile = GeneralUtility::getFileAbsFileName($this->templateFile, TRUE);
2077 $template = GeneralUtility::getUrl($templateFile);
2078 if ($this->removeLineBreaksFromTemplate) {
2079 $template = strtr($template, array(LF => '', CR => ''));
2080 }
2081 if ($part != self::PART_COMPLETE) {
2082 $templatePart = explode('###BODY###', $template);
2083 $template = $templatePart[$part - 1];
2084 }
2085 return $template;
2086 }
2087
2088 /**
2089 * Helper function for render the main JavaScript libraries,
2090 * currently: RequireJS, jQuery, PrototypeJS, Scriptaculous, SVG, ExtJs
2091 *
2092 * @return string Content with JavaScript libraries
2093 */
2094 protected function renderMainJavaScriptLibraries() {
2095 $out = '';
2096
2097 // Include RequireJS
2098 if ($this->addRequireJs) {
2099 // load the paths of the requireJS configuration
2100 $out .= GeneralUtility::wrapJS('var require = ' . json_encode($this->requireJsConfig)) . LF;
2101 // directly after that, include the require.js file
2102 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->requireJsPath . 'require.js')) . '" type="text/javascript"></script>' . LF;
2103 }
2104
2105 if ($this->addSvg) {
2106 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->svgPath . 'svg.js')) . '" data-path="' . $this->backPath . $this->svgPath . '"' . ($this->enableSvgDebug ? ' data-debug="true"' : '') . '></script>' . LF;
2107 }
2108 // Include jQuery Core for each namespace, depending on the version and source
2109 if (!empty($this->jQueryVersions)) {
2110 foreach ($this->jQueryVersions as $namespace => $jQueryVersion) {
2111 $out .= $this->renderJqueryScriptTag($jQueryVersion['version'], $jQueryVersion['source'], $namespace);
2112 }
2113 }
2114 if ($this->addPrototype) {
2115 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->prototypePath . 'prototype.js')) . '" type="text/javascript"></script>' . LF;
2116 unset($this->jsFiles[$this->backPath . $this->prototypePath . 'prototype.js']);
2117 }
2118 if ($this->addScriptaculous) {
2119 $mods = array();
2120 foreach ($this->addScriptaculousModules as $key => $value) {
2121 if ($this->addScriptaculousModules[$key]) {
2122 $mods[] = $key;
2123 }
2124 }
2125 // Resolve dependencies
2126 if (in_array('dragdrop', $mods) || in_array('controls', $mods)) {
2127 $mods = array_merge(array('effects'), $mods);
2128 }
2129 if (count($mods)) {
2130 foreach ($mods as $module) {
2131 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->scriptaculousPath . $module . '.js')) . '" type="text/javascript"></script>' . LF;
2132 unset($this->jsFiles[$this->backPath . $this->scriptaculousPath . $module . '.js']);
2133 }
2134 }
2135 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->scriptaculousPath . 'scriptaculous.js')) . '" type="text/javascript"></script>' . LF;
2136 unset($this->jsFiles[$this->backPath . $this->scriptaculousPath . 'scriptaculous.js']);
2137 }
2138 // Include extCore, but only if ExtJS is not included
2139 if ($this->addExtCore && !$this->addExtJS) {
2140 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->extCorePath . 'ext-core' . ($this->enableExtCoreDebug ? '-debug' : '') . '.js')) . '" type="text/javascript"></script>' . LF;
2141 unset($this->jsFiles[$this->backPath . $this->extCorePath . 'ext-core' . ($this->enableExtCoreDebug ? '-debug' : '') . '.js']);
2142 }
2143 // Include extJS
2144 if ($this->addExtJS) {
2145 // Use the base adapter all the time
2146 $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;
2147 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->extJsPath . 'ext-all' . ($this->enableExtJsDebug ? '-debug' : '') . '.js')) . '" type="text/javascript"></script>' . LF;
2148 // Add extJS localization
2149 // Load standard ISO mapping and modify for use with ExtJS
2150 $localeMap = $this->locales->getIsoMapping();
2151 $localeMap[''] = 'en';
2152 $localeMap['default'] = 'en';
2153 // Greek
2154 $localeMap['gr'] = 'el_GR';
2155 // Norwegian Bokmaal
2156 $localeMap['no'] = 'no_BO';
2157 // Swedish
2158 $localeMap['se'] = 'se_SV';
2159 $extJsLang = isset($localeMap[$this->lang]) ? $localeMap[$this->lang] : $this->lang;
2160 // TODO autoconvert file from UTF8 to current BE charset if necessary!!!!
2161 $extJsLocaleFile = $this->extJsPath . 'locale/ext-lang-' . $extJsLang . '.js';
2162 if (file_exists(PATH_typo3 . $extJsLocaleFile)) {
2163 $out .= '<script src="' . $this->processJsFile(($this->backPath . $extJsLocaleFile)) . '" type="text/javascript" charset="utf-8"></script>' . LF;
2164 }
2165 // Remove extjs from JScodeLibArray
2166 unset($this->jsFiles[$this->backPath . $this->extJsPath . 'ext-all.js'], $this->jsFiles[$this->backPath . $this->extJsPath . 'ext-all-debug.js']);
2167 }
2168 if (count($this->inlineLanguageLabelFiles)) {
2169 foreach ($this->inlineLanguageLabelFiles as $languageLabelFile) {
2170 $this->includeLanguageFileForInline($languageLabelFile['fileRef'], $languageLabelFile['selectionPrefix'], $languageLabelFile['stripFromSelectionName'], $languageLabelFile['$errorMode']);
2171 }
2172 }
2173 unset($this->inlineLanguageLabelFiles);
2174 // Convert labels/settings back to UTF-8 since json_encode() only works with UTF-8:
2175 if ($this->getCharSet() !== 'utf-8') {
2176 if ($this->inlineLanguageLabels) {
2177 $this->csConvObj->convArray($this->inlineLanguageLabels, $this->getCharSet(), 'utf-8');
2178 }
2179 if ($this->inlineSettings) {
2180 $this->csConvObj->convArray($this->inlineSettings, $this->getCharSet(), 'utf-8');
2181 }
2182 }
2183 $inlineSettings = $this->inlineLanguageLabels ? 'TYPO3.lang = ' . json_encode($this->inlineLanguageLabels) . ';' : '';
2184 $inlineSettings .= $this->inlineSettings ? 'TYPO3.settings = ' . json_encode($this->inlineSettings) . ';' : '';
2185 if ($this->addExtCore || $this->addExtJS) {
2186 // Set clear.gif, move it on top, add handler code
2187 $code = '';
2188 if (count($this->extOnReadyCode)) {
2189 foreach ($this->extOnReadyCode as $block) {
2190 $code .= $block;
2191 }
2192 }
2193 $out .= $this->inlineJavascriptWrap[0] . '
2194 Ext.ns("TYPO3");
2195 Ext.BLANK_IMAGE_URL = "' . htmlspecialchars(GeneralUtility::locationHeaderUrl(($this->backPath . 'gfx/clear.gif'))) . '";' . LF
2196 . $inlineSettings
2197 . 'Ext.onReady(function() {'
2198 . ($this->enableExtJSQuickTips ? 'Ext.QuickTips.init();' . LF : '')
2199 . $code
2200 . ' });'
2201 . $this->inlineJavascriptWrap[1];
2202 unset($this->extOnReadyCode);
2203 // Include TYPO3.l10n object
2204 if (TYPO3_MODE === 'BE') {
2205 $out .= '<script src="' . $this->processJsFile(($this->backPath . 'sysext/lang/Resources/Public/JavaScript/Typo3Lang.js')) . '" type="text/javascript" charset="utf-8"></script>' . LF;
2206 }
2207 if ($this->extJStheme) {
2208 if (isset($GLOBALS['TBE_STYLES']['extJS']['theme'])) {
2209 $this->addCssFile($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['theme'], 'stylesheet', 'all', '', TRUE, TRUE);
2210 } else {
2211 $this->addCssFile($this->backPath . $this->extJsPath . 'resources/css/xtheme-blue.css', 'stylesheet', 'all', '', TRUE, TRUE);
2212 }
2213 }
2214 if ($this->extJScss) {
2215 if (isset($GLOBALS['TBE_STYLES']['extJS']['all'])) {
2216 $this->addCssFile($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['all'], 'stylesheet', 'all', '', TRUE, TRUE);
2217 } else {
2218 $this->addCssFile($this->backPath . $this->extJsPath . 'resources/css/ext-all-notheme.css', 'stylesheet', 'all', '', TRUE, TRUE);
2219 }
2220 }
2221 } else {
2222 // no extJS loaded, but still inline settings
2223 if ($inlineSettings !== '') {
2224 // make sure the global TYPO3 is available
2225 $inlineSettings = 'var TYPO3 = TYPO3 || {};' . CRLF . $inlineSettings;
2226 $out .= $this->inlineJavascriptWrap[0] . $inlineSettings . $this->inlineJavascriptWrap[1];
2227 }
2228 }
2229 return $out;
2230 }
2231
2232 /**
2233 * Renders the HTML script tag for the given jQuery version.
2234 *
2235 * @param string $version The jQuery version that should be included, either "latest" or any available version
2236 * @param string $source The location of the jQuery source, can be "local", "google", "msn" or "jquery
2237 * @param string $namespace The namespace in which the jQuery object of the specific version should be stored
2238 * @return string
2239 */
2240 protected function renderJqueryScriptTag($version, $source, $namespace) {
2241 switch (TRUE) {
2242 case isset($this->jQueryCdnUrls[$source]):
2243 if ($this->enableJqueryDebug) {
2244 $minifyPart = '';
2245 } else {
2246 $minifyPart = '.min';
2247 }
2248 $jQueryFileName = sprintf($this->jQueryCdnUrls[$source], $version, $minifyPart);
2249 break;
2250 case $source === 'local':
2251 $jQueryFileName = $this->backPath . $this->jQueryPath . 'jquery-' . rawurlencode($version);
2252 if ($this->enableJqueryDebug) {
2253 $jQueryFileName .= '.js';
2254 } else {
2255 $jQueryFileName .= '.min.js';
2256 }
2257 break;
2258 default:
2259 $jQueryFileName = $source;
2260 }
2261 // Include the jQuery Core
2262 $scriptTag = '<script src="' . htmlspecialchars($jQueryFileName) . '" type="text/javascript"></script>' . LF;
2263 // Set the noConflict mode to be available via "TYPO3.jQuery" in all installations
2264 switch ($namespace) {
2265 case self::JQUERY_NAMESPACE_DEFAULT_NOCONFLICT:
2266 $scriptTag .= GeneralUtility::wrapJS('jQuery.noConflict();') . LF;
2267 break;
2268 case self::JQUERY_NAMESPACE_NONE:
2269 break;
2270 case self::JQUERY_NAMESPACE_DEFAULT:
2271
2272 default:
2273 $scriptTag .= GeneralUtility::wrapJS('var TYPO3 = TYPO3 || {}; TYPO3.' . $namespace . ' = jQuery.noConflict(true);') . LF;
2274 }
2275 return $scriptTag;
2276 }
2277
2278 /**
2279 * Render CSS files
2280 *
2281 * @return string
2282 */
2283 protected function renderCssFiles() {
2284 $cssFiles = '';
2285 if (count($this->cssFiles)) {
2286 foreach ($this->cssFiles as $file => $properties) {
2287 $file = GeneralUtility::resolveBackPath($file);
2288 $file = GeneralUtility::createVersionNumberedFilename($file);
2289 $tag = '<link rel="' . htmlspecialchars($properties['rel'])
2290 . '" type="text/css" href="' . htmlspecialchars($file)
2291 . '" media="' . htmlspecialchars($properties['media']) . '"'
2292 . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '')
2293 . $this->endingSlash . '>';
2294 if ($properties['allWrap']) {
2295 $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2296 $tag = $wrapArr[0] . $tag . $wrapArr[1];
2297 }
2298 if ($properties['forceOnTop']) {
2299 $cssFiles = $tag . LF . $cssFiles;
2300 } else {
2301 $cssFiles .= LF . $tag;
2302 }
2303 }
2304 }
2305 return $cssFiles;
2306 }
2307
2308 /**
2309 * Render inline CSS
2310 *
2311 * @return string
2312 */
2313 protected function renderCssInline() {
2314 $cssInline = '';
2315 if (count($this->cssInline)) {
2316 foreach ($this->cssInline as $name => $properties) {
2317 if ($properties['forceOnTop']) {
2318 $cssInline = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF . $cssInline;
2319 } else {
2320 $cssInline .= '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2321 }
2322 }
2323 $cssInline = $this->inlineCssWrap[0] . $cssInline . $this->inlineCssWrap[1];
2324 }
2325 return $cssInline;
2326 }
2327
2328 /**
2329 * Render JavaScipt libraries
2330 *
2331 * @return array<string> jsLibs and jsFooterLibs strings
2332 */
2333 protected function renderAdditionalJavaScriptLibraries() {
2334 $jsLibs = '';
2335 $jsFooterLibs = '';
2336 if (count($this->jsLibs)) {
2337 foreach ($this->jsLibs as $properties) {
2338 $properties['file'] = GeneralUtility::resolveBackPath($properties['file']);
2339 $properties['file'] = GeneralUtility::createVersionNumberedFilename($properties['file']);
2340 $tag = '<script src="' . htmlspecialchars($properties['file']) . '" type="' . htmlspecialchars($properties['type']) . '"></script>';
2341 if ($properties['allWrap']) {
2342 $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2343 $tag = $wrapArr[0] . $tag . $wrapArr[1];
2344 }
2345 if ($properties['forceOnTop']) {
2346 if ($properties['section'] === self::PART_HEADER) {
2347 $jsLibs = $tag . LF . $jsLibs;
2348 } else {
2349 $jsFooterLibs = $tag . LF . $jsFooterLibs;
2350 }
2351 } else {
2352 if ($properties['section'] === self::PART_HEADER) {
2353 $jsLibs .= LF . $tag;
2354 } else {
2355 $jsFooterLibs .= LF . $tag;
2356 }
2357 }
2358 }
2359 }
2360 if ($this->moveJsFromHeaderToFooter) {
2361 $jsFooterLibs = $jsLibs . LF . $jsFooterLibs;
2362 $jsLibs = '';
2363 }
2364 return array($jsLibs, $jsFooterLibs);
2365 }
2366
2367 /**
2368 * Render JavaScript files
2369 *
2370 * @return array<string> jsFiles and jsFooterFiles strings
2371 */
2372 protected function renderJavaScriptFiles() {
2373 $jsFiles = '';
2374 $jsFooterFiles = '';
2375 if (count($this->jsFiles)) {
2376 foreach ($this->jsFiles as $file => $properties) {
2377 $file = GeneralUtility::resolveBackPath($file);
2378 $file = GeneralUtility::createVersionNumberedFilename($file);
2379 $tag = '<script src="' . htmlspecialchars($file) . '" type="' . htmlspecialchars($properties['type']) . '"></script>';
2380 if ($properties['allWrap']) {
2381 $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2382 $tag = $wrapArr[0] . $tag . $wrapArr[1];
2383 }
2384 if ($properties['forceOnTop']) {
2385 if ($properties['section'] === self::PART_HEADER) {
2386 $jsFiles = $tag . LF . $jsFiles;
2387 } else {
2388 $jsFooterFiles = $tag . LF . $jsFooterFiles;
2389 }
2390 } else {
2391 if ($properties['section'] === self::PART_HEADER) {
2392 $jsFiles .= LF . $tag;
2393 } else {
2394 $jsFooterFiles .= LF . $tag;
2395 }
2396 }
2397 }
2398 }
2399 if ($this->moveJsFromHeaderToFooter) {
2400 $jsFooterFiles = $jsFiles . LF . $jsFooterFiles;
2401 $jsFiles = '';
2402 }
2403 return array($jsFiles, $jsFooterFiles);
2404 }
2405
2406 /**
2407 * Render inline JavaScript
2408 *
2409 * @return array<string> jsInline and jsFooterInline string
2410 */
2411 protected function renderInlineJavaScript() {
2412 $jsInline = '';
2413 $jsFooterInline = '';
2414 if (count($this->jsInline)) {
2415 foreach ($this->jsInline as $name => $properties) {
2416 if ($properties['forceOnTop']) {
2417 if ($properties['section'] === self::PART_HEADER) {
2418 $jsInline = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF . $jsInline;
2419 } else {
2420 $jsFooterInline = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF . $jsFooterInline;
2421 }
2422 } else {
2423 if ($properties['section'] === self::PART_HEADER) {
2424 $jsInline .= '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2425 } else {
2426 $jsFooterInline .= '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2427 }
2428 }
2429 }
2430 }
2431 if ($jsInline) {
2432 $jsInline = $this->inlineJavascriptWrap[0] . $jsInline . $this->inlineJavascriptWrap[1];
2433 }
2434 if ($jsFooterInline) {
2435 $jsFooterInline = $this->inlineJavascriptWrap[0] . $jsFooterInline . $this->inlineJavascriptWrap[1];
2436 }
2437 if ($this->moveJsFromHeaderToFooter) {
2438 $jsFooterInline = $jsInline . LF . $jsFooterInline;
2439 $jsInline = '';
2440 }
2441 return array($jsInline, $jsFooterInline);
2442 }
2443
2444 /**
2445 * Include language file for inline usage
2446 *
2447 * @param string $fileRef
2448 * @param string $selectionPrefix
2449 * @param string $stripFromSelectionName
2450 * @param integer $errorMode
2451 * @return void
2452 * @throws \RuntimeException
2453 */
2454 protected function includeLanguageFileForInline($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0) {
2455 if (!isset($this->lang) || !isset($this->charSet)) {
2456 throw new \RuntimeException('Language and character encoding are not set.', 1284906026);
2457 }
2458 $labelsFromFile = array();
2459 $allLabels = $this->readLLfile($fileRef, $errorMode);
2460 // Regular expression to strip the selection prefix and possibly something from the label name:
2461 $labelPattern = '#^' . preg_quote($selectionPrefix, '#') . '(' . preg_quote($stripFromSelectionName, '#') . ')?#';
2462 if ($allLabels !== FALSE) {
2463 // Merge language specific translations:
2464 if ($this->lang !== 'default' && isset($allLabels[$this->lang])) {
2465 $labels = array_merge($allLabels['default'], $allLabels[$this->lang]);
2466 } else {
2467 $labels = $allLabels['default'];
2468 }
2469 // Iterate through all locallang labels:
2470 foreach ($labels as $label => $value) {
2471 if ($selectionPrefix === '') {
2472 $labelsFromFile[$label] = $value;
2473 } elseif (strpos($label, $selectionPrefix) === 0) {
2474 preg_replace($labelPattern, '', $label);
2475 $labelsFromFile[$label] = $value;
2476 }
2477 }
2478 $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $labelsFromFile);
2479 }
2480 }
2481
2482 /**
2483 * Reads a locallang file.
2484 *
2485 * @param string $fileRef Reference to a relative filename to include.
2486 * @param integer $errorMode Error mode (when file could not be found): 0 - syslog entry, 1 - do nothing, 2 - throw an exception
2487 * @return array Returns the $LOCAL_LANG array found in the file. If no array found, returns empty array.
2488 */
2489 protected function readLLfile($fileRef, $errorMode = 0) {
2490 if ($this->lang !== 'default') {
2491 $languages = array_reverse($this->languageDependencies);
2492 // At least we need to have English
2493 if (empty($languages)) {
2494 $languages[] = 'default';
2495 }
2496 } else {
2497 $languages = array('default');
2498 }
2499
2500 $localLanguage = array();
2501 foreach ($languages as $language) {
2502 $tempLL = GeneralUtility::readLLfile($fileRef, $language, $this->charSet, $errorMode);
2503 $localLanguage['default'] = $tempLL['default'];
2504 if (!isset($localLanguage[$this->lang])) {
2505 $localLanguage[$this->lang] = $localLanguage['default'];
2506 }
2507 if ($this->lang !== 'default' && isset($tempLL[$language])) {
2508 // Merge current language labels onto labels from previous language
2509 // This way we have a labels with fall back applied
2510 \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($localLanguage[$this->lang], $tempLL[$language], TRUE, FALSE);
2511 }
2512 }
2513
2514 return $localLanguage;
2515 }
2516
2517
2518 /*****************************************************/
2519 /* */
2520 /* Tools */
2521 /* */
2522 /*****************************************************/
2523 /**
2524 * Concatenate files into one file
2525 * registered handler
2526 *
2527 * @return void
2528 */
2529 protected function doConcatenate() {
2530 $this->doConcatenateCss();
2531 $this->doConcatenateJavaScript();
2532 }
2533
2534 /**
2535 * Concatenate JavaScript files according to the configuration.
2536 *
2537 * @return void
2538 */
2539 protected function doConcatenateJavaScript() {
2540 if ($this->concatenateFiles || $this->concatenateJavascript) {
2541 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsConcatenateHandler'])) {
2542 // use external concatenation routine
2543 $params = array(
2544 'jsLibs' => &$this->jsLibs,
2545 'jsFiles' => &$this->jsFiles,
2546 'jsFooterFiles' => &$this->jsFooterFiles,
2547 'headerData' => &$this->headerData,
2548 'footerData' => &$this->footerData
2549 );
2550 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsConcatenateHandler'], $params, $this);
2551 } else {
2552 $this->jsLibs = $this->getCompressor()->concatenateJsFiles($this->jsLibs);
2553 $this->jsFiles = $this->getCompressor()->concatenateJsFiles($this->jsFiles);
2554 $this->jsFooterFiles = $this->getCompressor()->concatenateJsFiles($this->jsFooterFiles);
2555 }
2556 }
2557 }
2558
2559 /**
2560 * Concatenate CSS files according to configuration.
2561 *
2562 * @return void
2563 */
2564 protected function doConcatenateCss() {
2565 if ($this->concatenateFiles || $this->concatenateCss) {
2566 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssConcatenateHandler'])) {
2567 // use external concatenation routine
2568 $params = array(
2569 'cssFiles' => &$this->cssFiles,
2570 'headerData' => &$this->headerData,
2571 'footerData' => &$this->footerData
2572 );
2573 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssConcatenateHandler'], $params, $this);
2574 } else {
2575 $cssOptions = array();
2576 if (TYPO3_MODE === 'BE') {
2577 $cssOptions = array('baseDirectories' => $GLOBALS['TBE_TEMPLATE']->getSkinStylesheetDirectories());
2578 }
2579 $this->cssFiles = $this->getCompressor()->concatenateCssFiles($this->cssFiles, $cssOptions);
2580 }
2581 }
2582 }
2583
2584 /**
2585 * Compresses inline code
2586 *
2587 * @return void
2588 */
2589 protected function doCompress() {
2590 $this->doCompressJavaScript();
2591 $this->doCompressCss();
2592 }
2593
2594 /**
2595 * Compresses CSS according to configuration.
2596 *
2597 * @return void
2598 */
2599 protected function doCompressCss() {
2600 if ($this->compressCss) {
2601 // Use external compression routine
2602 $params = array(
2603 'cssInline' => &$this->cssInline,
2604 'cssFiles' => &$this->cssFiles,
2605 'headerData' => &$this->headerData,
2606 'footerData' => &$this->footerData
2607 );
2608 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'])) {
2609 // use external concatenation routine
2610 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'], $params, $this);
2611 } else {
2612 $this->cssFiles = $this->getCompressor()->compressCssFiles($this->cssFiles);
2613 }
2614 }
2615 }
2616
2617 /**
2618 * Compresses JavaScript according to configuration.
2619 *
2620 * @return void
2621 */
2622 protected function doCompressJavaScript() {
2623 if ($this->compressJavascript) {
2624 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'])) {
2625 // Use external compression routine
2626 $params = array(
2627 'jsInline' => &$this->jsInline,
2628 'jsFooterInline' => &$this->jsFooterInline,
2629 'jsLibs' => &$this->jsLibs,
2630 'jsFiles' => &$this->jsFiles,
2631 'jsFooterFiles' => &$this->jsFooterFiles,
2632 'headerData' => &$this->headerData,
2633 'footerData' => &$this->footerData
2634 );
2635 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'], $params, $this);
2636 } else {
2637 // Traverse the arrays, compress files
2638 if (count($this->jsInline)) {
2639 foreach ($this->jsInline as $name => $properties) {
2640 if ($properties['compress']) {
2641 $error = '';
2642 $this->jsInline[$name]['code'] = GeneralUtility::minifyJavaScript($properties['code'], $error);
2643 if ($error) {
2644 $this->compressError .= 'Error with minify JS Inline Block "' . $name . '": ' . $error . LF;
2645 }
2646 }
2647 }
2648 }
2649 $this->jsLibs = $this->getCompressor()->compressJsFiles($this->jsLibs);
2650 $this->jsFiles = $this->getCompressor()->compressJsFiles($this->jsFiles);
2651 $this->jsFooterFiles = $this->getCompressor()->compressJsFiles($this->jsFooterFiles);
2652 }
2653 }
2654 }
2655
2656 /**
2657 * Returns instance of \TYPO3\CMS\Core\Resource\ResourceCompressor
2658 *
2659 * @return \TYPO3\CMS\Core\Resource\ResourceCompressor
2660 */
2661 protected function getCompressor() {
2662 if ($this->compressor === NULL) {
2663 $this->compressor = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceCompressor');
2664 }
2665 return $this->compressor;
2666 }
2667
2668 /**
2669 * Processes a Javascript file dependent on the current context
2670 *
2671 * Adds the version number for Frontend, compresses the file for Backend
2672 *
2673 * @param string $filename Filename
2674 * @return string New filename
2675 */
2676 protected function processJsFile($filename) {
2677 switch (TYPO3_MODE) {
2678 case 'FE':
2679 if ($this->compressJavascript) {
2680 $filename = $this->getCompressor()->compressJsFile($filename);
2681 } else {
2682 $filename = GeneralUtility::createVersionNumberedFilename($filename);
2683 }
2684 break;
2685 case 'BE':
2686 if ($this->compressJavascript) {
2687 $filename = $this->getCompressor()->compressJsFile($filename);
2688 }
2689 break;
2690 }
2691 return $filename;
2692 }
2693
2694 /*****************************************************/
2695 /* */
2696 /* Hooks */
2697 /* */
2698 /*****************************************************/
2699 /**
2700 * Execute PreRenderHook for possible manipulation
2701 *
2702 * @return void
2703 */
2704 protected function executePreRenderHook() {
2705 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'])) {
2706 $params = array(
2707 'jsLibs' => &$this->jsLibs,
2708 'jsFooterLibs' => &$this->jsFooterLibs,
2709 'jsFiles' => &$this->jsFiles,
2710 'jsFooterFiles' => &$this->jsFooterFiles,
2711 'cssFiles' => &$this->cssFiles,
2712 'headerData' => &$this->headerData,
2713 'footerData' => &$this->footerData,
2714 'jsInline' => &$this->jsInline,
2715 'jsFooterInline' => &$this->jsFooterInline,
2716 'cssInline' => &$this->cssInline
2717 );
2718 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'] as $hook) {
2719 GeneralUtility::callUserFunction($hook, $params, $this);
2720 }
2721 }
2722 }
2723
2724 /**
2725 * PostTransform for possible manipulation of concatenated and compressed files
2726 *
2727 * @return void
2728 */
2729 protected function executeRenderPostTransformHook() {
2730 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform'])) {
2731 $params = array(
2732 'jsLibs' => &$this->jsLibs,
2733 'jsFooterLibs' => &$this->jsFooterLibs,
2734 'jsFiles' => &$this->jsFiles,
2735 'jsFooterFiles' => &$this->jsFooterFiles,
2736 'cssFiles' => &$this->cssFiles,
2737 'headerData' => &$this->headerData,
2738 'footerData' => &$this->footerData,
2739 'jsInline' => &$this->jsInline,
2740 'jsFooterInline' => &$this->jsFooterInline,
2741 'cssInline' => &$this->cssInline
2742 );
2743 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform'] as $hook) {
2744 GeneralUtility::callUserFunction($hook, $params, $this);
2745 }
2746 }
2747 }
2748
2749 /**
2750 * Execute postRenderHook for possible manipulation
2751 *
2752 * @param $jsLibs string
2753 * @param $jsFiles string
2754 * @param $jsFooterFiles string
2755 * @param $cssFiles string
2756 * @param $jsInline string
2757 * @param $cssInline string
2758 * @param $jsFooterInline string
2759 * @param $jsFooterLibs string
2760 * @return void
2761 */
2762 protected function executePostRenderHook(&$jsLibs, &$jsFiles, &$jsFooterFiles, &$cssFiles, &$jsInline, &$cssInline, &$jsFooterInline, &$jsFooterLibs) {
2763 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'])) {
2764 $params = array(
2765 'jsLibs' => &$jsLibs,
2766 'jsFiles' => &$jsFiles,
2767 'jsFooterFiles' => &$jsFooterFiles,
2768 'cssFiles' => &$cssFiles,
2769 'headerData' => &$this->headerData,
2770 'footerData' => &$this->footerData,
2771 'jsInline' => &$jsInline,
2772 'cssInline' => &$cssInline,
2773 'xmlPrologAndDocType' => &$this->xmlPrologAndDocType,
2774 'htmlTag' => &$this->htmlTag,
2775 'headTag' => &$this->headTag,
2776 'charSet' => &$this->charSet,
2777 'metaCharsetTag' => &$this->metaCharsetTag,
2778 'shortcutTag' => &$this->shortcutTag,
2779 'inlineComments' => &$this->inlineComments,
2780 'baseUrl' => &$this->baseUrl,
2781 'baseUrlTag' => &$this->baseUrlTag,
2782 'favIcon' => &$this->favIcon,
2783 'iconMimeType' => &$this->iconMimeType,
2784 'titleTag' => &$this->titleTag,
2785 'title' => &$this->title,
2786 'metaTags' => &$this->metaTags,
2787 'jsFooterInline' => &$jsFooterInline,
2788 'jsFooterLibs' => &$jsFooterLibs,
2789 'bodyContent' => &$this->bodyContent
2790 );
2791 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'] as $hook) {
2792 GeneralUtility::callUserFunction($hook, $params, $this);
2793 }
2794 }
2795 }
2796
2797 }