[!!!][TASK] Replace ExtJS DateTimePicker with bootstrap alternative
[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 'moment' => 'contrib/moment/moment.min',
1624 'twbs' => 'contrib/twbs/bootstrap.min',
1625 'twbs/bootstrap-datetimepicker' => 'contrib/twbs/bootstrap-datetimepicker.min',
1626 );
1627 // get all extensions that are loaded
1628 $loadedExtensions = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getLoadedExtensionListArray();
1629 foreach ($loadedExtensions as $packageName) {
1630 $fullJsPath = 'EXT:' . $packageName . '/Resources/Public/JavaScript/';
1631 $fullJsPath = GeneralUtility::getFileAbsFileName($fullJsPath);
1632 $fullJsPath = \TYPO3\CMS\Core\Utility\PathUtility::getRelativePath(PATH_typo3, $fullJsPath);
1633 $fullJsPath = rtrim($fullJsPath, '/');
1634 if ($fullJsPath) {
1635 $this->requireJsConfig['paths']['TYPO3/CMS/' . GeneralUtility::underscoredToUpperCamelCase($packageName)] = $this->backPath . $fullJsPath;
1636 }
1637 }
1638
1639 // check if additional AMD modules need to be loaded if a single AMD module is initialized
1640 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules'])) {
1641 $this->addInlineSettingArray('RequireJS.PostInitializationModules', $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules']);
1642 }
1643 }
1644
1645 $this->addRequireJs = TRUE;
1646 }
1647
1648 /**
1649 * Add additional configuration to require js.
1650 *
1651 * Configuration will be merged recursive with overrule.
1652 *
1653 * To add another path mapping deliver the following configuration:
1654 * 'paths' => array(
1655 * 'EXTERN/mybootstrapjs' => 'contrib/twbs/bootstrap.min',
1656 * ),
1657 *
1658 * @author Daniel Siepmann <daniel.siepmann@typo3.org>
1659 *
1660 * @param array $configuration The configuration that will be merged with existing one.
1661 * @return void
1662 */
1663 public function addRequireJsConfiguration(array $configuration) {
1664 \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($this->requireJsConfig, $configuration);
1665 }
1666
1667 /**
1668 * includes a AMD-compatible JS file by resolving the ModuleName, and then requires the file via a requireJS request
1669 *
1670 * this function only works for AMD-ready JS modules, used like "define('TYPO3/CMS/Backend/FormEngine..."
1671 * in the JS file
1672 *
1673 * TYPO3/CMS/Backend/FormEngine =>
1674 * "TYPO3": Vendor Name
1675 * "CMS": Product Name
1676 * "Backend": Extension Name
1677 * "FormEngine": FileName in the Resources/Public/JavaScript folder
1678 *
1679 * @param string $mainModuleName Must be in the form of "TYPO3/CMS/PackageName/ModuleName" e.g. "TYPO3/CMS/Backend/FormEngine"
1680 * @return void
1681 */
1682 public function loadRequireJsModule($mainModuleName) {
1683
1684 // make sure requireJS is initialized
1685 $this->loadRequireJs();
1686
1687 // execute the main module
1688 $this->addJsInlineCode('RequireJS-Module-' . $mainModuleName, 'require(["' . $mainModuleName . '"]);');
1689 }
1690
1691 /**
1692 * Call function if you need the prototype library
1693 *
1694 * @return void
1695 */
1696 public function loadPrototype() {
1697 $this->addPrototype = TRUE;
1698 }
1699
1700 /**
1701 * Call function if you need the Scriptaculous library
1702 *
1703 * @param string $modules Add modules you need. use "all" if you need complete modules
1704 * @return void
1705 */
1706 public function loadScriptaculous($modules = 'all') {
1707 // Scriptaculous require prototype, so load prototype too.
1708 $this->addPrototype = TRUE;
1709 $this->addScriptaculous = TRUE;
1710 if ($modules) {
1711 if ($modules == 'all') {
1712 foreach ($this->addScriptaculousModules as $key => $value) {
1713 $this->addScriptaculousModules[$key] = TRUE;
1714 }
1715 } else {
1716 $mods = GeneralUtility::trimExplode(',', $modules);
1717 foreach ($mods as $mod) {
1718 if (isset($this->addScriptaculousModules[strtolower($mod)])) {
1719 $this->addScriptaculousModules[strtolower($mod)] = TRUE;
1720 }
1721 }
1722 }
1723 }
1724 }
1725
1726 /**
1727 * call this function if you need the extJS library
1728 *
1729 * @param bool $css Flag, if set the ext-css will be loaded
1730 * @param bool $theme Flag, if set the ext-theme "grey" will be loaded
1731 * @param string $adapter Choose alternative adapter, possible values: yui, prototype, jquery
1732 * @return void
1733 */
1734 public function loadExtJS($css = TRUE, $theme = TRUE, $adapter = '') {
1735 if ($adapter) {
1736 // Empty $adapter will always load the ext adapter
1737 switch (GeneralUtility::strtolower(trim($adapter))) {
1738 case self::EXTJS_ADAPTER_YUI:
1739 $this->extJSadapter = 'yui/ext-yui-adapter.js';
1740 break;
1741 case self::EXTJS_ADAPTER_PROTOTYPE:
1742 $this->extJSadapter = 'prototype/ext-prototype-adapter.js';
1743 break;
1744 case self::EXTJS_ADAPTER_JQUERY:
1745 $this->extJSadapter = 'jquery/ext-jquery-adapter.js';
1746 break;
1747 }
1748 }
1749 $this->addExtJS = TRUE;
1750 $this->extJStheme = $theme;
1751 $this->extJScss = $css;
1752 }
1753
1754 /**
1755 * Enables ExtJs QuickTips
1756 * Need extJs loaded
1757 *
1758 * @return void
1759 */
1760 public function enableExtJSQuickTips() {
1761 $this->enableExtJSQuickTips = TRUE;
1762 }
1763
1764 /**
1765 * Call function if you need the ExtCore library
1766 *
1767 * @return void
1768 */
1769 public function loadExtCore() {
1770 $this->addExtCore = TRUE;
1771 }
1772
1773 /**
1774 * Call function if you need the SVG library
1775 *
1776 * @return void
1777 */
1778 public function loadSvg() {
1779 $this->addSvg = TRUE;
1780 }
1781
1782 /**
1783 * Call this function to load debug version of ExtJS. Use this for development only
1784 *
1785 * @return void
1786 */
1787 public function enableSvgDebug() {
1788 $this->enableSvgDebug = TRUE;
1789 }
1790
1791 /**
1792 * Call this function to force flash usage with SVG library
1793 *
1794 * @return void
1795 */
1796 public function svgForceFlash() {
1797 $this->addMetaTag('<meta name="svg.render.forceflash" content="true" />');
1798 }
1799
1800 /**
1801 * Call this function to load debug version of ExtJS. Use this for development only
1802 *
1803 * @return void
1804 */
1805 public function enableExtJsDebug() {
1806 $this->enableExtJsDebug = TRUE;
1807 }
1808
1809 /**
1810 * Call this function to load debug version of ExtCore. Use this for development only
1811 *
1812 * @return void
1813 */
1814 public function enableExtCoreDebug() {
1815 $this->enableExtCoreDebug = TRUE;
1816 }
1817
1818 /**
1819 * Adds Javascript Inline Label. This will occur in TYPO3.lang - object
1820 * The label can be used in scripts with TYPO3.lang.<key>
1821 * Need extJs loaded
1822 *
1823 * @param string $key
1824 * @param string $value
1825 * @return void
1826 */
1827 public function addInlineLanguageLabel($key, $value) {
1828 $this->inlineLanguageLabels[$key] = $value;
1829 }
1830
1831 /**
1832 * Adds Javascript Inline Label Array. This will occur in TYPO3.lang - object
1833 * The label can be used in scripts with TYPO3.lang.<key>
1834 * Array will be merged with existing array.
1835 * Need extJs loaded
1836 *
1837 * @param array $array
1838 * @return void
1839 */
1840 public function addInlineLanguageLabelArray(array $array) {
1841 $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $array);
1842 }
1843
1844 /**
1845 * Gets labels to be used in JavaScript fetched from a locallang file.
1846 *
1847 * @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.
1848 * @param string $selectionPrefix Prefix to select the correct labels (default: '')
1849 * @param string $stripFromSelectionName Sub-prefix to be removed from label names in the result (default: '')
1850 * @param int $errorMode Error mode (when file could not be found): 0 - syslog entry, 1 - do nothing, 2 - throw an exception
1851 * @return void
1852 */
1853 public function addInlineLanguageLabelFile($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0) {
1854 $index = md5($fileRef . $selectionPrefix . $stripFromSelectionName);
1855 if ($fileRef && !isset($this->inlineLanguageLabelFiles[$index])) {
1856 $this->inlineLanguageLabelFiles[$index] = array(
1857 'fileRef' => $fileRef,
1858 'selectionPrefix' => $selectionPrefix,
1859 'stripFromSelectionName' => $stripFromSelectionName,
1860 'errorMode' => $errorMode
1861 );
1862 }
1863 }
1864
1865 /**
1866 * Adds Javascript Inline Setting. This will occur in TYPO3.settings - object
1867 * The label can be used in scripts with TYPO3.setting.<key>
1868 * Need extJs loaded
1869 *
1870 * @param string $namespace
1871 * @param string $key
1872 * @param string $value
1873 * @return void
1874 */
1875 public function addInlineSetting($namespace, $key, $value) {
1876 if ($namespace) {
1877 if (strpos($namespace, '.')) {
1878 $parts = explode('.', $namespace);
1879 $a = &$this->inlineSettings;
1880 foreach ($parts as $part) {
1881 $a = &$a[$part];
1882 }
1883 $a[$key] = $value;
1884 } else {
1885 $this->inlineSettings[$namespace][$key] = $value;
1886 }
1887 } else {
1888 $this->inlineSettings[$key] = $value;
1889 }
1890 }
1891
1892 /**
1893 * Adds Javascript Inline Setting. This will occur in TYPO3.settings - object
1894 * The label can be used in scripts with TYPO3.setting.<key>
1895 * Array will be merged with existing array.
1896 * Need extJs loaded
1897 *
1898 * @param string $namespace
1899 * @param array $array
1900 * @return void
1901 */
1902 public function addInlineSettingArray($namespace, array $array) {
1903 if ($namespace) {
1904 if (strpos($namespace, '.')) {
1905 $parts = explode('.', $namespace);
1906 $a = &$this->inlineSettings;
1907 foreach ($parts as $part) {
1908 $a = &$a[$part];
1909 }
1910 $a = array_merge((array)$a, $array);
1911 } else {
1912 $this->inlineSettings[$namespace] = array_merge((array)$this->inlineSettings[$namespace], $array);
1913 }
1914 } else {
1915 $this->inlineSettings = array_merge($this->inlineSettings, $array);
1916 }
1917 }
1918
1919 /**
1920 * Adds content to body content
1921 *
1922 * @param string $content
1923 * @return void
1924 */
1925 public function addBodyContent($content) {
1926 $this->bodyContent .= $content;
1927 }
1928
1929 /*****************************************************/
1930 /* */
1931 /* Render Functions */
1932 /* */
1933 /*****************************************************/
1934 /**
1935 * Render the section (Header or Footer)
1936 *
1937 * @param int $part Section which should be rendered: self::PART_COMPLETE, self::PART_HEADER or self::PART_FOOTER
1938 * @return string Content of rendered section
1939 */
1940 public function render($part = self::PART_COMPLETE) {
1941 $this->prepareRendering();
1942 list($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs) = $this->renderJavaScriptAndCss();
1943 $metaTags = implode(LF, $this->metaTags);
1944 $markerArray = $this->getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags);
1945 $template = $this->getTemplateForPart($part);
1946
1947 // The page renderer needs a full reset, even when only rendering one part of the page
1948 // This means that you can only register footer files *after* the header has been already rendered.
1949 // In case you render the footer part first, header files can only be added *after* the footer has been rendered
1950 $this->reset();
1951 return trim(\TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($template, $markerArray, '###|###'));
1952 }
1953
1954 /**
1955 * Render the page but not the JavaScript and CSS Files
1956 *
1957 * @param string $substituteHash The hash that is used for the placehoder markers
1958 * @access private
1959 * @return string Content of rendered section
1960 */
1961 public function renderPageWithUncachedObjects($substituteHash) {
1962 $this->prepareRendering();
1963 $markerArray = $this->getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash);
1964 $template = $this->getTemplateForPart(self::PART_COMPLETE);
1965 return trim(\TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($template, $markerArray, '###|###'));
1966 }
1967
1968 /**
1969 * Renders the JavaScript and CSS files that have been added during processing
1970 * of uncached content objects (USER_INT, COA_INT)
1971 *
1972 * @param string $cachedPageContent
1973 * @param string $substituteHash The hash that is used for the placehoder markers
1974 * @access private
1975 * @return string
1976 */
1977 public function renderJavaScriptAndCssForProcessingOfUncachedContentObjects($cachedPageContent, $substituteHash) {
1978 $this->prepareRendering();
1979 list($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs) = $this->renderJavaScriptAndCss();
1980 $title = $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '';
1981 $markerArray = array(
1982 '<!-- ###TITLE' . $substituteHash . '### -->' => $title,
1983 '<!-- ###CSS_LIBS' . $substituteHash . '### -->' => $cssLibs,
1984 '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->' => $cssFiles,
1985 '<!-- ###CSS_INLINE' . $substituteHash . '### -->' => $cssInline,
1986 '<!-- ###JS_INLINE' . $substituteHash . '### -->' => $jsInline,
1987 '<!-- ###JS_INCLUDE' . $substituteHash . '### -->' => $jsFiles,
1988 '<!-- ###JS_LIBS' . $substituteHash . '### -->' => $jsLibs,
1989 '<!-- ###HEADERDATA' . $substituteHash . '### -->' => implode(LF, $this->headerData),
1990 '<!-- ###FOOTERDATA' . $substituteHash . '### -->' => implode(LF, $this->footerData),
1991 '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->' => $jsFooterLibs,
1992 '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->' => $jsFooterFiles,
1993 '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->' => $jsFooterInline
1994 );
1995 foreach ($markerArray as $placeHolder => $content) {
1996 $cachedPageContent = str_replace($placeHolder, $content, $cachedPageContent);
1997 }
1998 $this->reset();
1999 return $cachedPageContent;
2000 }
2001
2002 /**
2003 * Remove ending slashes from static header block
2004 * if the page is beeing rendered as html (not xhtml)
2005 * and define property $this->endingSlash for further use
2006 *
2007 * @return void
2008 */
2009 protected function prepareRendering() {
2010 if ($this->getRenderXhtml()) {
2011 $this->endingSlash = ' /';
2012 } else {
2013 $this->metaCharsetTag = str_replace(' />', '>', $this->metaCharsetTag);
2014 $this->baseUrlTag = str_replace(' />', '>', $this->baseUrlTag);
2015 $this->shortcutTag = str_replace(' />', '>', $this->shortcutTag);
2016 $this->endingSlash = '';
2017 }
2018 }
2019
2020 /**
2021 * Renders all JavaScript and CSS
2022 *
2023 * @return array<string>
2024 */
2025 protected function renderJavaScriptAndCss() {
2026 $this->executePreRenderHook();
2027 $mainJsLibs = $this->renderMainJavaScriptLibraries();
2028 if ($this->concatenateFiles || $this->concatenateJavascript || $this->concatenateCss) {
2029 // Do the file concatenation
2030 $this->doConcatenate();
2031 }
2032 if ($this->compressCss || $this->compressJavascript) {
2033 // Do the file compression
2034 $this->doCompress();
2035 }
2036 $this->executeRenderPostTransformHook();
2037 $cssLibs = $this->renderCssLibraries();
2038 $cssFiles = $this->renderCssFiles();
2039 $cssInline = $this->renderCssInline();
2040 list($jsLibs, $jsFooterLibs) = $this->renderAdditionalJavaScriptLibraries();
2041 list($jsFiles, $jsFooterFiles) = $this->renderJavaScriptFiles();
2042 list($jsInline, $jsFooterInline) = $this->renderInlineJavaScript();
2043 $jsLibs = $mainJsLibs . $jsLibs;
2044 if ($this->moveJsFromHeaderToFooter) {
2045 $jsFooterLibs = $jsLibs . LF . $jsFooterLibs;
2046 $jsLibs = '';
2047 $jsFooterFiles = $jsFiles . LF . $jsFooterFiles;
2048 $jsFiles = '';
2049 $jsFooterInline = $jsInline . LF . $jsFooterInline;
2050 $jsInline = '';
2051 }
2052 $this->executePostRenderHook($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs);
2053 return array($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs);
2054 }
2055
2056 /**
2057 * Fills the marker array with the given strings and trims each value
2058 *
2059 * @param $jsLibs string
2060 * @param $jsFiles string
2061 * @param $jsFooterFiles string
2062 * @param $cssLibs string
2063 * @param $cssFiles string
2064 * @param $jsInline string
2065 * @param $cssInline string
2066 * @param $jsFooterInline string
2067 * @param $jsFooterLibs string
2068 * @param $metaTags string
2069 * @return array Marker array
2070 */
2071 protected function getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags) {
2072 $markerArray = array(
2073 'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
2074 'HTMLTAG' => $this->htmlTag,
2075 'HEADTAG' => $this->headTag,
2076 'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
2077 'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
2078 'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
2079 'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
2080 'CSS_LIBS' => $cssLibs,
2081 'CSS_INCLUDE' => $cssFiles,
2082 'CSS_INLINE' => $cssInline,
2083 'JS_INLINE' => $jsInline,
2084 'JS_INCLUDE' => $jsFiles,
2085 'JS_LIBS' => $jsLibs,
2086 'TITLE' => $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '',
2087 'META' => $metaTags,
2088 'HEADERDATA' => $this->headerData ? implode(LF, $this->headerData) : '',
2089 'FOOTERDATA' => $this->footerData ? implode(LF, $this->footerData) : '',
2090 'JS_LIBS_FOOTER' => $jsFooterLibs,
2091 'JS_INCLUDE_FOOTER' => $jsFooterFiles,
2092 'JS_INLINE_FOOTER' => $jsFooterInline,
2093 'BODY' => $this->bodyContent
2094 );
2095 $markerArray = array_map('trim', $markerArray);
2096 return $markerArray;
2097 }
2098
2099 /**
2100 * Fills the marker array with the given strings and trims each value
2101 *
2102 * @param string $substituteHash The hash that is used for the placehoder markers
2103 * @return array Marker array
2104 */
2105 protected function getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash) {
2106 $markerArray = array(
2107 'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
2108 'HTMLTAG' => $this->htmlTag,
2109 'HEADTAG' => $this->headTag,
2110 'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
2111 'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
2112 'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
2113 'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
2114 'META' => implode(LF, $this->metaTags),
2115 'BODY' => $this->bodyContent,
2116 'TITLE' => '<!-- ###TITLE' . $substituteHash . '### -->',
2117 'CSS_LIBS' => '<!-- ###CSS_LIBS' . $substituteHash . '### -->',
2118 'CSS_INCLUDE' => '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->',
2119 'CSS_INLINE' => '<!-- ###CSS_INLINE' . $substituteHash . '### -->',
2120 'JS_INLINE' => '<!-- ###JS_INLINE' . $substituteHash . '### -->',
2121 'JS_INCLUDE' => '<!-- ###JS_INCLUDE' . $substituteHash . '### -->',
2122 'JS_LIBS' => '<!-- ###JS_LIBS' . $substituteHash . '### -->',
2123 'HEADERDATA' => '<!-- ###HEADERDATA' . $substituteHash . '### -->',
2124 'FOOTERDATA' => '<!-- ###FOOTERDATA' . $substituteHash . '### -->',
2125 'JS_LIBS_FOOTER' => '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->',
2126 'JS_INCLUDE_FOOTER' => '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->',
2127 'JS_INLINE_FOOTER' => '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->'
2128 );
2129 $markerArray = array_map('trim', $markerArray);
2130 return $markerArray;
2131 }
2132
2133 /**
2134 * Reads the template file and returns the requested part as string
2135 *
2136 * @param int $part
2137 * @return string
2138 */
2139 protected function getTemplateForPart($part) {
2140 $templateFile = GeneralUtility::getFileAbsFileName($this->templateFile, TRUE);
2141 $template = GeneralUtility::getUrl($templateFile);
2142 if ($this->removeLineBreaksFromTemplate) {
2143 $template = strtr($template, array(LF => '', CR => ''));
2144 }
2145 if ($part !== self::PART_COMPLETE) {
2146 $templatePart = explode('###BODY###', $template);
2147 $template = $templatePart[$part - 1];
2148 }
2149 return $template;
2150 }
2151
2152 /**
2153 * Helper function for render the main JavaScript libraries,
2154 * currently: RequireJS, jQuery, PrototypeJS, Scriptaculous, SVG, ExtJs
2155 *
2156 * @return string Content with JavaScript libraries
2157 */
2158 protected function renderMainJavaScriptLibraries() {
2159 $out = '';
2160
2161 // Include RequireJS
2162 if ($this->addRequireJs) {
2163 // load the paths of the requireJS configuration
2164 $out .= GeneralUtility::wrapJS('var require = ' . json_encode($this->requireJsConfig)) . LF;
2165 // directly after that, include the require.js file
2166 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->requireJsPath . 'require.js')) . '" type="text/javascript"></script>' . LF;
2167 }
2168
2169 if ($this->addSvg) {
2170 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->svgPath . 'svg.js')) . '" data-path="' . $this->backPath . $this->svgPath . '"' . ($this->enableSvgDebug ? ' data-debug="true"' : '') . '></script>' . LF;
2171 }
2172 // Include jQuery Core for each namespace, depending on the version and source
2173 if (!empty($this->jQueryVersions)) {
2174 foreach ($this->jQueryVersions as $namespace => $jQueryVersion) {
2175 $out .= $this->renderJqueryScriptTag($jQueryVersion['version'], $jQueryVersion['source'], $namespace);
2176 }
2177 }
2178 if ($this->addPrototype) {
2179 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->prototypePath . 'prototype.js')) . '" type="text/javascript"></script>' . LF;
2180 unset($this->jsFiles[$this->backPath . $this->prototypePath . 'prototype.js']);
2181 }
2182 if ($this->addScriptaculous) {
2183 $mods = array();
2184 foreach ($this->addScriptaculousModules as $key => $value) {
2185 if ($this->addScriptaculousModules[$key]) {
2186 $mods[] = $key;
2187 }
2188 }
2189 // Resolve dependencies
2190 if (in_array('dragdrop', $mods) || in_array('controls', $mods)) {
2191 $mods = array_merge(array('effects'), $mods);
2192 }
2193 if (count($mods)) {
2194 foreach ($mods as $module) {
2195 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->scriptaculousPath . $module . '.js')) . '" type="text/javascript"></script>' . LF;
2196 unset($this->jsFiles[$this->backPath . $this->scriptaculousPath . $module . '.js']);
2197 }
2198 }
2199 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->scriptaculousPath . 'scriptaculous.js')) . '" type="text/javascript"></script>' . LF;
2200 unset($this->jsFiles[$this->backPath . $this->scriptaculousPath . 'scriptaculous.js']);
2201 }
2202 // Include extCore, but only if ExtJS is not included
2203 if ($this->addExtCore && !$this->addExtJS) {
2204 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->extCorePath . 'ext-core' . ($this->enableExtCoreDebug ? '-debug' : '') . '.js')) . '" type="text/javascript"></script>' . LF;
2205 unset($this->jsFiles[$this->backPath . $this->extCorePath . 'ext-core' . ($this->enableExtCoreDebug ? '-debug' : '') . '.js']);
2206 }
2207 // Include extJS
2208 if ($this->addExtJS) {
2209 // Use the base adapter all the time
2210 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->extJsPath . 'adapter/' . ($this->enableExtJsDebug ? str_replace('.js', '-debug.js', $this->extJSadapter) : $this->extJSadapter))) . '" type="text/javascript"></script>' . LF;
2211 $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->extJsPath . 'ext-all' . ($this->enableExtJsDebug ? '-debug' : '') . '.js')) . '" type="text/javascript"></script>' . LF;
2212 // Add extJS localization
2213 // Load standard ISO mapping and modify for use with ExtJS
2214 $localeMap = $this->locales->getIsoMapping();
2215 $localeMap[''] = 'en';
2216 $localeMap['default'] = 'en';
2217 // Greek
2218 $localeMap['gr'] = 'el_GR';
2219 // Norwegian Bokmaal
2220 $localeMap['no'] = 'no_BO';
2221 // Swedish
2222 $localeMap['se'] = 'se_SV';
2223 $extJsLang = isset($localeMap[$this->lang]) ? $localeMap[$this->lang] : $this->lang;
2224 // @todo autoconvert file from UTF8 to current BE charset if necessary!!!!
2225 $extJsLocaleFile = $this->extJsPath . 'locale/ext-lang-' . $extJsLang . '.js';
2226 if (file_exists(PATH_typo3 . $extJsLocaleFile)) {
2227 $out .= '<script src="' . $this->processJsFile(($this->backPath . $extJsLocaleFile)) . '" type="text/javascript" charset="utf-8"></script>' . LF;
2228 }
2229 // Remove extjs from JScodeLibArray
2230 unset($this->jsFiles[$this->backPath . $this->extJsPath . 'ext-all.js'], $this->jsFiles[$this->backPath . $this->extJsPath . 'ext-all-debug.js']);
2231 }
2232 if (count($this->inlineLanguageLabelFiles)) {
2233 foreach ($this->inlineLanguageLabelFiles as $languageLabelFile) {
2234 $this->includeLanguageFileForInline($languageLabelFile['fileRef'], $languageLabelFile['selectionPrefix'], $languageLabelFile['stripFromSelectionName'], $languageLabelFile['$errorMode']);
2235 }
2236 }
2237 $this->inlineLanguageLabelFiles = array();
2238 // Convert labels/settings back to UTF-8 since json_encode() only works with UTF-8:
2239 if ($this->getCharSet() !== 'utf-8') {
2240 if ($this->inlineLanguageLabels) {
2241 $this->csConvObj->convArray($this->inlineLanguageLabels, $this->getCharSet(), 'utf-8');
2242 }
2243 if ($this->inlineSettings) {
2244 $this->csConvObj->convArray($this->inlineSettings, $this->getCharSet(), 'utf-8');
2245 }
2246 }
2247 if (TYPO3_MODE === 'BE') {
2248 $this->addAjaxUrlsToInlineSettings();
2249 }
2250 $inlineSettings = $this->inlineLanguageLabels ? 'TYPO3.lang = ' . json_encode($this->inlineLanguageLabels) . ';' : '';
2251 $inlineSettings .= $this->inlineSettings ? 'TYPO3.settings = ' . json_encode($this->inlineSettings) . ';' : '';
2252 if ($this->addExtCore || $this->addExtJS) {
2253 // Set clear.gif, move it on top, add handler code
2254 $code = '';
2255 if (count($this->extOnReadyCode)) {
2256 foreach ($this->extOnReadyCode as $block) {
2257 $code .= $block;
2258 }
2259 }
2260 $out .= $this->inlineJavascriptWrap[0] . '
2261 Ext.ns("TYPO3");
2262 Ext.BLANK_IMAGE_URL = "' . htmlspecialchars(GeneralUtility::locationHeaderUrl(($this->backPath . 'gfx/clear.gif'))) . '";
2263 Ext.SSL_SECURE_URL = "' . htmlspecialchars(GeneralUtility::locationHeaderUrl(($this->backPath . 'gfx/clear.gif'))) . '";' . LF
2264 . $inlineSettings
2265 . 'Ext.onReady(function() {'
2266 . ($this->enableExtJSQuickTips ? 'Ext.QuickTips.init();' . LF : '')
2267 . $code
2268 . ' });'
2269 . $this->inlineJavascriptWrap[1];
2270 $this->extOnReadyCode = array();
2271 // Include TYPO3.l10n object
2272 if (TYPO3_MODE === 'BE') {
2273 $out .= '<script src="' . $this->processJsFile(($this->backPath . 'sysext/lang/Resources/Public/JavaScript/Typo3Lang.js')) . '" type="text/javascript" charset="utf-8"></script>' . LF;
2274 }
2275 if ($this->extJScss) {
2276 if (isset($GLOBALS['TBE_STYLES']['extJS']['all'])) {
2277 $this->addCssLibrary($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['all'], 'stylesheet', 'all', '', TRUE);
2278 } else {
2279 $this->addCssLibrary($this->backPath . $this->extJsPath . 'resources/css/ext-all-notheme.css', 'stylesheet', 'all', '', TRUE);
2280 }
2281 }
2282 if ($this->extJStheme) {
2283 if (isset($GLOBALS['TBE_STYLES']['extJS']['theme'])) {
2284 $this->addCssLibrary($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['theme'], 'stylesheet', 'all', '', TRUE);
2285 } else {
2286 $this->addCssLibrary($this->backPath . $this->extJsPath . 'resources/css/xtheme-blue.css', 'stylesheet', 'all', '', TRUE);
2287 }
2288 }
2289 } else {
2290 // no extJS loaded, but still inline settings
2291 if ($inlineSettings !== '') {
2292 // make sure the global TYPO3 is available
2293 $inlineSettings = 'var TYPO3 = TYPO3 || {};' . CRLF . $inlineSettings;
2294 $out .= $this->inlineJavascriptWrap[0] . $inlineSettings . $this->inlineJavascriptWrap[1];
2295 }
2296 }
2297 return $out;
2298 }
2299
2300 /**
2301 * Make URLs to all backend ajax handlers available as inline setting.
2302 */
2303 protected function addAjaxUrlsToInlineSettings() {
2304 $ajaxUrls = array();
2305 foreach (array_keys($GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX']) as $ajaxHandler) {
2306 $ajaxUrls[$ajaxHandler] = BackendUtility::getAjaxUrl($ajaxHandler);
2307 }
2308 $this->inlineSettings['ajaxUrls'] = $ajaxUrls;
2309 }
2310
2311 /**
2312 * Renders the HTML script tag for the given jQuery version.
2313 *
2314 * @param string $version The jQuery version that should be included, either "latest" or any available version
2315 * @param string $source The location of the jQuery source, can be "local", "google", "msn" or "jquery
2316 * @param string $namespace The namespace in which the jQuery object of the specific version should be stored
2317 * @return string
2318 */
2319 protected function renderJqueryScriptTag($version, $source, $namespace) {
2320 switch (TRUE) {
2321 case isset($this->jQueryCdnUrls[$source]):
2322 if ($this->enableJqueryDebug) {
2323 $minifyPart = '';
2324 } else {
2325 $minifyPart = '.min';
2326 }
2327 $jQueryFileName = sprintf($this->jQueryCdnUrls[$source], $version, $minifyPart);
2328 break;
2329 case $source === 'local':
2330 $jQueryFileName = $this->backPath . $this->jQueryPath . 'jquery-' . rawurlencode($version);
2331 if ($this->enableJqueryDebug) {
2332 $jQueryFileName .= '.js';
2333 } else {
2334 $jQueryFileName .= '.min.js';
2335 }
2336 break;
2337 default:
2338 $jQueryFileName = $source;
2339 }
2340 // Include the jQuery Core
2341 $scriptTag = '<script src="' . htmlspecialchars($jQueryFileName) . '" type="text/javascript"></script>' . LF;
2342 // Set the noConflict mode to be available via "TYPO3.jQuery" in all installations
2343 switch ($namespace) {
2344 case self::JQUERY_NAMESPACE_DEFAULT_NOCONFLICT:
2345 $scriptTag .= GeneralUtility::wrapJS('jQuery.noConflict();') . LF;
2346 break;
2347 case self::JQUERY_NAMESPACE_NONE:
2348 break;
2349 case self::JQUERY_NAMESPACE_DEFAULT:
2350
2351 default:
2352 $scriptTag .= GeneralUtility::wrapJS('var TYPO3 = TYPO3 || {}; TYPO3.' . $namespace . ' = jQuery.noConflict(true);') . LF;
2353 }
2354 return $scriptTag;
2355 }
2356
2357 /**
2358 * Render CSS library files
2359 *
2360 * @return string
2361 */
2362 protected function renderCssLibraries() {
2363 $cssFiles = '';
2364 if (count($this->cssLibs)) {
2365 foreach ($this->cssLibs as $file => $properties) {
2366 $file = GeneralUtility::resolveBackPath($file);
2367 $file = GeneralUtility::createVersionNumberedFilename($file);
2368 $tag = '<link rel="' . htmlspecialchars($properties['rel'])
2369 . '" type="text/css" href="' . htmlspecialchars($file)
2370 . '" media="' . htmlspecialchars($properties['media']) . '"'
2371 . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '')
2372 . $this->endingSlash . '>';
2373 if ($properties['allWrap']) {
2374 $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2375 $tag = $wrapArr[0] . $tag . $wrapArr[1];
2376 }
2377 $tag .= LF;
2378 if ($properties['forceOnTop']) {
2379 $cssFiles = $tag . $cssFiles;
2380 } else {
2381 $cssFiles .= $tag;
2382 }
2383 }
2384 }
2385 return $cssFiles;
2386 }
2387
2388 /**
2389 * Render CSS files
2390 *
2391 * @return string
2392 */
2393 protected function renderCssFiles() {
2394 $cssFiles = '';
2395 if (count($this->cssFiles)) {
2396 foreach ($this->cssFiles as $file => $properties) {
2397 $file = GeneralUtility::resolveBackPath($file);
2398 $file = GeneralUtility::createVersionNumberedFilename($file);
2399 $tag = '<link rel="' . htmlspecialchars($properties['rel'])
2400 . '" type="text/css" href="' . htmlspecialchars($file)
2401 . '" media="' . htmlspecialchars($properties['media']) . '"'
2402 . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '')
2403 . $this->endingSlash . '>';
2404 if ($properties['allWrap']) {
2405 $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2406 $tag = $wrapArr[0] . $tag . $wrapArr[1];
2407 }
2408 $tag .= LF;
2409 if ($properties['forceOnTop']) {
2410 $cssFiles = $tag . $cssFiles;
2411 } else {
2412 $cssFiles .= $tag;
2413 }
2414 }
2415 }
2416 return $cssFiles;
2417 }
2418
2419 /**
2420 * Render inline CSS
2421 *
2422 * @return string
2423 */
2424 protected function renderCssInline() {
2425 $cssInline = '';
2426 if (count($this->cssInline)) {
2427 foreach ($this->cssInline as $name => $properties) {
2428 $cssCode = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2429 if ($properties['forceOnTop']) {
2430 $cssInline = $cssCode . $cssInline;
2431 } else {
2432 $cssInline .= $cssCode;
2433 }
2434 }
2435 $cssInline = $this->inlineCssWrap[0] . $cssInline . $this->inlineCssWrap[1];
2436 }
2437 return $cssInline;
2438 }
2439
2440 /**
2441 * Render JavaScipt libraries
2442 *
2443 * @return array<string> jsLibs and jsFooterLibs strings
2444 */
2445 protected function renderAdditionalJavaScriptLibraries() {
2446 $jsLibs = '';
2447 $jsFooterLibs = '';
2448 if (count($this->jsLibs)) {
2449 foreach ($this->jsLibs as $properties) {
2450 $properties['file'] = GeneralUtility::resolveBackPath($properties['file']);
2451 $properties['file'] = GeneralUtility::createVersionNumberedFilename($properties['file']);
2452 $tag = '<script src="' . htmlspecialchars($properties['file']) . '" type="' . htmlspecialchars($properties['type']) . '"></script>';
2453 if ($properties['allWrap']) {
2454 $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2455 $tag = $wrapArr[0] . $tag . $wrapArr[1];
2456 }
2457 $tag .= LF;
2458 if ($properties['forceOnTop']) {
2459 if ($properties['section'] === self::PART_HEADER) {
2460 $jsLibs = $tag . $jsLibs;
2461 } else {
2462 $jsFooterLibs = $tag . $jsFooterLibs;
2463 }
2464 } else {
2465 if ($properties['section'] === self::PART_HEADER) {
2466 $jsLibs .= $tag;
2467 } else {
2468 $jsFooterLibs .= $tag;
2469 }
2470 }
2471 }
2472 }
2473 if ($this->moveJsFromHeaderToFooter) {
2474 $jsFooterLibs = $jsLibs . LF . $jsFooterLibs;
2475 $jsLibs = '';
2476 }
2477 return array($jsLibs, $jsFooterLibs);
2478 }
2479
2480 /**
2481 * Render JavaScript files
2482 *
2483 * @return array<string> jsFiles and jsFooterFiles strings
2484 */
2485 protected function renderJavaScriptFiles() {
2486 $jsFiles = '';
2487 $jsFooterFiles = '';
2488 if (count($this->jsFiles)) {
2489 foreach ($this->jsFiles as $file => $properties) {
2490 $file = GeneralUtility::resolveBackPath($file);
2491 $file = GeneralUtility::createVersionNumberedFilename($file);
2492 $tag = '<script src="' . htmlspecialchars($file) . '" type="' . htmlspecialchars($properties['type']) . '"></script>';
2493 if ($properties['allWrap']) {
2494 $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2495 $tag = $wrapArr[0] . $tag . $wrapArr[1];
2496 }
2497 $tag .= LF;
2498 if ($properties['forceOnTop']) {
2499 if ($properties['section'] === self::PART_HEADER) {
2500 $jsFiles = $tag . $jsFiles;
2501 } else {
2502 $jsFooterFiles = $tag . $jsFooterFiles;
2503 }
2504 } else {
2505 if ($properties['section'] === self::PART_HEADER) {
2506 $jsFiles .= $tag;
2507 } else {
2508 $jsFooterFiles .= $tag;
2509 }
2510 }
2511 }
2512 }
2513 if ($this->moveJsFromHeaderToFooter) {
2514 $jsFooterFiles = $jsFiles . $jsFooterFiles;
2515 $jsFiles = '';
2516 }
2517 return array($jsFiles, $jsFooterFiles);
2518 }
2519
2520 /**
2521 * Render inline JavaScript
2522 *
2523 * @return array<string> jsInline and jsFooterInline string
2524 */
2525 protected function renderInlineJavaScript() {
2526 $jsInline = '';
2527 $jsFooterInline = '';
2528 if (count($this->jsInline)) {
2529 foreach ($this->jsInline as $name => $properties) {
2530 $jsCode = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2531 if ($properties['forceOnTop']) {
2532 if ($properties['section'] === self::PART_HEADER) {
2533 $jsInline = $jsCode . $jsInline;
2534 } else {
2535 $jsFooterInline = $jsCode . $jsFooterInline;
2536 }
2537 } else {
2538 if ($properties['section'] === self::PART_HEADER) {
2539 $jsInline .= $jsCode;
2540 } else {
2541 $jsFooterInline .= $jsCode;
2542 }
2543 }
2544 }
2545 }
2546 if ($jsInline) {
2547 $jsInline = $this->inlineJavascriptWrap[0] . $jsInline . $this->inlineJavascriptWrap[1];
2548 }
2549 if ($jsFooterInline) {
2550 $jsFooterInline = $this->inlineJavascriptWrap[0] . $jsFooterInline . $this->inlineJavascriptWrap[1];
2551 }
2552 if ($this->moveJsFromHeaderToFooter) {
2553 $jsFooterInline = $jsInline . $jsFooterInline;
2554 $jsInline = '';
2555 }
2556 return array($jsInline, $jsFooterInline);
2557 }
2558
2559 /**
2560 * Include language file for inline usage
2561 *
2562 * @param string $fileRef
2563 * @param string $selectionPrefix
2564 * @param string $stripFromSelectionName
2565 * @param int $errorMode
2566 * @return void
2567 * @throws \RuntimeException
2568 */
2569 protected function includeLanguageFileForInline($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0) {
2570 if (!isset($this->lang) || !isset($this->charSet)) {
2571 throw new \RuntimeException('Language and character encoding are not set.', 1284906026);
2572 }
2573 $labelsFromFile = array();
2574 $allLabels = $this->readLLfile($fileRef, $errorMode);
2575 // Regular expression to strip the selection prefix and possibly something from the label name:
2576 $labelPattern = '#^' . preg_quote($selectionPrefix, '#') . '(' . preg_quote($stripFromSelectionName, '#') . ')?#';
2577 if ($allLabels !== FALSE) {
2578 // Merge language specific translations:
2579 if ($this->lang !== 'default' && isset($allLabels[$this->lang])) {
2580 $labels = array_merge($allLabels['default'], $allLabels[$this->lang]);
2581 } else {
2582 $labels = $allLabels['default'];
2583 }
2584 // Iterate through all locallang labels:
2585 foreach ($labels as $label => $value) {
2586 if ($selectionPrefix === '') {
2587 $labelsFromFile[$label] = $value;
2588 } elseif (strpos($label, $selectionPrefix) === 0) {
2589 preg_replace($labelPattern, '', $label);
2590 $labelsFromFile[$label] = $value;
2591 }
2592 }
2593 $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $labelsFromFile);
2594 }
2595 }
2596
2597 /**
2598 * Reads a locallang file.
2599 *
2600 * @param string $fileRef Reference to a relative filename to include.
2601 * @param int $errorMode Error mode (when file could not be found): 0 - syslog entry, 1 - do nothing, 2 - throw an exception
2602 * @return array Returns the $LOCAL_LANG array found in the file. If no array found, returns empty array.
2603 */
2604 protected function readLLfile($fileRef, $errorMode = 0) {
2605 if ($this->lang !== 'default') {
2606 $languages = array_reverse($this->languageDependencies);
2607 // At least we need to have English
2608 if (empty($languages)) {
2609 $languages[] = 'default';
2610 }
2611 } else {
2612 $languages = array('default');
2613 }
2614
2615 $localLanguage = array();
2616 foreach ($languages as $language) {
2617 $tempLL = GeneralUtility::readLLfile($fileRef, $language, $this->charSet, $errorMode);
2618 $localLanguage['default'] = $tempLL['default'];
2619 if (!isset($localLanguage[$this->lang])) {
2620 $localLanguage[$this->lang] = $localLanguage['default'];
2621 }
2622 if ($this->lang !== 'default' && isset($tempLL[$language])) {
2623 // Merge current language labels onto labels from previous language
2624 // This way we have a labels with fall back applied
2625 \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($localLanguage[$this->lang], $tempLL[$language], TRUE, FALSE);
2626 }
2627 }
2628
2629 return $localLanguage;
2630 }
2631
2632
2633 /*****************************************************/
2634 /* */
2635 /* Tools */
2636 /* */
2637 /*****************************************************/
2638 /**
2639 * Concatenate files into one file
2640 * registered handler
2641 *
2642 * @return void
2643 */
2644 protected function doConcatenate() {
2645 $this->doConcatenateCss();
2646 $this->doConcatenateJavaScript();
2647 }
2648
2649 /**
2650 * Concatenate JavaScript files according to the configuration.
2651 *
2652 * @return void
2653 */
2654 protected function doConcatenateJavaScript() {
2655 if ($this->concatenateFiles || $this->concatenateJavascript) {
2656 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsConcatenateHandler'])) {
2657 // use external concatenation routine
2658 $params = array(
2659 'jsLibs' => &$this->jsLibs,
2660 'jsFiles' => &$this->jsFiles,
2661 'jsFooterFiles' => &$this->jsFooterFiles,
2662 'headerData' => &$this->headerData,
2663 'footerData' => &$this->footerData
2664 );
2665 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsConcatenateHandler'], $params, $this);
2666 } else {
2667 $this->jsLibs = $this->getCompressor()->concatenateJsFiles($this->jsLibs);
2668 $this->jsFiles = $this->getCompressor()->concatenateJsFiles($this->jsFiles);
2669 $this->jsFooterFiles = $this->getCompressor()->concatenateJsFiles($this->jsFooterFiles);
2670 }
2671 }
2672 }
2673
2674 /**
2675 * Concatenate CSS files according to configuration.
2676 *
2677 * @return void
2678 */
2679 protected function doConcatenateCss() {
2680 if ($this->concatenateFiles || $this->concatenateCss) {
2681 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssConcatenateHandler'])) {
2682 // use external concatenation routine
2683 $params = array(
2684 'cssFiles' => &$this->cssFiles,
2685 'headerData' => &$this->headerData,
2686 'footerData' => &$this->footerData
2687 );
2688 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssConcatenateHandler'], $params, $this);
2689 } else {
2690 $cssOptions = array();
2691 if (TYPO3_MODE === 'BE') {
2692 $cssOptions = array('baseDirectories' => $GLOBALS['TBE_TEMPLATE']->getSkinStylesheetDirectories());
2693 }
2694 $this->cssFiles = $this->getCompressor()->concatenateCssFiles($this->cssFiles, $cssOptions);
2695 }
2696 }
2697 }
2698
2699 /**
2700 * Compresses inline code
2701 *
2702 * @return void
2703 */
2704 protected function doCompress() {
2705 $this->doCompressJavaScript();
2706 $this->doCompressCss();
2707 }
2708
2709 /**
2710 * Compresses CSS according to configuration.
2711 *
2712 * @return void
2713 */
2714 protected function doCompressCss() {
2715 if ($this->compressCss) {
2716 // Use external compression routine
2717 $params = array(
2718 'cssInline' => &$this->cssInline,
2719 'cssFiles' => &$this->cssFiles,
2720 'headerData' => &$this->headerData,
2721 'footerData' => &$this->footerData
2722 );
2723 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'])) {
2724 // use external concatenation routine
2725 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'], $params, $this);
2726 } else {
2727 $this->cssFiles = $this->getCompressor()->compressCssFiles($this->cssFiles);
2728 }
2729 }
2730 }
2731
2732 /**
2733 * Compresses JavaScript according to configuration.
2734 *
2735 * @return void
2736 */
2737 protected function doCompressJavaScript() {
2738 if ($this->compressJavascript) {
2739 if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'])) {
2740 // Use external compression routine
2741 $params = array(
2742 'jsInline' => &$this->jsInline,
2743 'jsFooterInline' => &$this->jsFooterInline,
2744 'jsLibs' => &$this->jsLibs,
2745 'jsFiles' => &$this->jsFiles,
2746 'jsFooterFiles' => &$this->jsFooterFiles,
2747 'headerData' => &$this->headerData,
2748 'footerData' => &$this->footerData
2749 );
2750 GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'], $params, $this);
2751 } else {
2752 // Traverse the arrays, compress files
2753 if (count($this->jsInline)) {
2754 foreach ($this->jsInline as $name => $properties) {
2755 if ($properties['compress']) {
2756 $error = '';
2757 $this->jsInline[$name]['code'] = GeneralUtility::minifyJavaScript($properties['code'], $error);
2758 if ($error) {
2759 $this->compressError .= 'Error with minify JS Inline Block "' . $name . '": ' . $error . LF;
2760 }
2761 }
2762 }
2763 }
2764 $this->jsLibs = $this->getCompressor()->compressJsFiles($this->jsLibs);
2765 $this->jsFiles = $this->getCompressor()->compressJsFiles($this->jsFiles);
2766 $this->jsFooterFiles = $this->getCompressor()->compressJsFiles($this->jsFooterFiles);
2767 }
2768 }
2769 }
2770
2771 /**
2772 * Returns instance of \TYPO3\CMS\Core\Resource\ResourceCompressor
2773 *
2774 * @return \TYPO3\CMS\Core\Resource\ResourceCompressor
2775 */
2776 protected function getCompressor() {
2777 if ($this->compressor === NULL) {
2778 $this->compressor = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\ResourceCompressor::class);
2779 }
2780 return $this->compressor;
2781 }
2782
2783 /**
2784 * Processes a Javascript file dependent on the current context
2785 *
2786 * Adds the version number for Frontend, compresses the file for Backend
2787 *
2788 * @param string $filename Filename
2789 * @return string New filename
2790 */
2791 protected function processJsFile($filename) {
2792 switch (TYPO3_MODE) {
2793 case 'FE':
2794 if ($this->compressJavascript) {
2795 $filename = $this->getCompressor()->compressJsFile($filename);
2796 } else {
2797 $filename = GeneralUtility::createVersionNumberedFilename($filename);
2798 }
2799 break;
2800 case 'BE':
2801 if ($this->compressJavascript) {
2802 $filename = $this->getCompressor()->compressJsFile($filename);
2803 }
2804 break;
2805 }
2806 return $filename;
2807 }
2808
2809 /*****************************************************/
2810 /* */
2811 /* Hooks */
2812 /* */
2813 /*****************************************************/
2814 /**
2815 * Execute PreRenderHook for possible manipulation
2816 *
2817 * @return void
2818 */
2819 protected function executePreRenderHook() {
2820 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'])) {
2821 $params = array(
2822 'jsLibs' => &$this->jsLibs,
2823 'jsFooterLibs' => &$this->jsFooterLibs,
2824 'jsFiles' => &$this->jsFiles,
2825 'jsFooterFiles' => &$this->jsFooterFiles,
2826 'cssFiles' => &$this->cssFiles,
2827 'headerData' => &$this->headerData,
2828 'footerData' => &$this->footerData,
2829 'jsInline' => &$this->jsInline,
2830 'jsFooterInline' => &$this->jsFooterInline,
2831 'cssInline' => &$this->cssInline
2832 );
2833 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'] as $hook) {
2834 GeneralUtility::callUserFunction($hook, $params, $this);
2835 }
2836 }
2837 }
2838
2839 /**
2840 * PostTransform for possible manipulation of concatenated and compressed files
2841 *
2842 * @return void
2843 */
2844 protected function executeRenderPostTransformHook() {
2845 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform'])) {
2846 $params = array(
2847 'jsLibs' => &$this->jsLibs,
2848 'jsFooterLibs' => &$this->jsFooterLibs,
2849 'jsFiles' => &$this->jsFiles,
2850 'jsFooterFiles' => &$this->jsFooterFiles,
2851 'cssFiles' => &$this->cssFiles,
2852 'headerData' => &$this->headerData,
2853 'footerData' => &$this->footerData,
2854 'jsInline' => &$this->jsInline,
2855 'jsFooterInline' => &$this->jsFooterInline,
2856 'cssInline' => &$this->cssInline
2857 );
2858 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform'] as $hook) {
2859 GeneralUtility::callUserFunction($hook, $params, $this);
2860 }
2861 }
2862 }
2863
2864 /**
2865 * Execute postRenderHook for possible manipulation
2866 *
2867 * @param $jsLibs string
2868 * @param $jsFiles string
2869 * @param $jsFooterFiles string
2870 * @param $cssLibs string
2871 * @param $cssFiles string
2872 * @param $jsInline string
2873 * @param $cssInline string
2874 * @param $jsFooterInline string
2875 * @param $jsFooterLibs string
2876 * @return void
2877 */
2878 protected function executePostRenderHook(&$jsLibs, &$jsFiles, &$jsFooterFiles, &$cssLibs, &$cssFiles, &$jsInline, &$cssInline, &$jsFooterInline, &$jsFooterLibs) {
2879 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'])) {
2880 $params = array(
2881 'jsLibs' => &$jsLibs,
2882 'jsFiles' => &$jsFiles,
2883 'jsFooterFiles' => &$jsFooterFiles,
2884 'cssLibs' => &$cssLibs,
2885 'cssFiles' => &$cssFiles,
2886 'headerData' => &$this->headerData,
2887 'footerData' => &$this->footerData,
2888 'jsInline' => &$jsInline,
2889 'cssInline' => &$cssInline,
2890 'xmlPrologAndDocType' => &$this->xmlPrologAndDocType,
2891 'htmlTag' => &$this->htmlTag,
2892 'headTag' => &$this->headTag,
2893 'charSet' => &$this->charSet,
2894 'metaCharsetTag' => &$this->metaCharsetTag,
2895 'shortcutTag' => &$this->shortcutTag,
2896 'inlineComments' => &$this->inlineComments,
2897 'baseUrl' => &$this->baseUrl,
2898 'baseUrlTag' => &$this->baseUrlTag,
2899 'favIcon' => &$this->favIcon,
2900 'iconMimeType' => &$this->iconMimeType,
2901 'titleTag' => &$this->titleTag,
2902 'title' => &$this->title,
2903 'metaTags' => &$this->metaTags,
2904 'jsFooterInline' => &$jsFooterInline,
2905 'jsFooterLibs' => &$jsFooterLibs,
2906 'bodyContent' => &$this->bodyContent
2907 );
2908 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'] as $hook) {
2909 GeneralUtility::callUserFunction($hook, $params, $this);
2910 }
2911 }
2912 }
2913
2914 }