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