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