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