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