Added feature #14247: Add a concatenator for CSS and JS (thanks to Steffen Gebert)
[Packages/TYPO3.CMS.git] / typo3 / template.php
index 9b3d68e..34ea945 100644 (file)
@@ -132,7 +132,8 @@ if (!defined('TYPO3_MODE')) die("Can't include this file directly.");
  * @return     string          Output string (in the old days this was wrapped in <font> tags)
  * @deprecated since TYPO3 3.6
  */
-function fw($str)      {
+function fw($str) {
+       t3lib_div::logDeprecatedFunction();
        return $str;
 }
 
@@ -178,7 +179,6 @@ class template {
        var $form_rowsToStylewidth = 9.58;      // Multiplication factor for formWidth() input size (default is 48* this value).
        var $form_largeComp = 1.33;             // Compensation for large documents (used in class.t3lib_tceforms.php)
        var $endJS=1;                                   // If set, then a JavaScript section will be outputted in the bottom of page which will try and update the top.busy session expiry object.
-       protected $additionalStyleSheets=array();       // Links to additional style sheets
 
                // TYPO3 Colorscheme.
                // If you want to change this, please do so through a skin using the global var $TBE_STYLES
@@ -189,12 +189,25 @@ class template {
        var $bgColor5 = '#ABBBB4';              // light tablerow background, greenish
        var $bgColor6 = '#E7DBA8';              // light tablerow background, yellowish, for section headers. Light.
        var $hoverColor = '#254D7B';
-       var $styleSheetFile = 'stylesheet.css'; // Filename of stylesheet (relative to PATH_typo3)
+       var $styleSheetFile = '';       // Filename of stylesheet (relative to PATH_typo3)
        var $styleSheetFile2 = '';              // Filename of stylesheet #2 - linked to right after the $this->styleSheetFile script (relative to PATH_typo3)
        var $styleSheetFile_post = '';  // Filename of a post-stylesheet - included right after all inline styles.
        var $backGroundImage = '';              // Background image of page (relative to PATH_typo3)
        var $inDocStyles_TBEstyle = ''; // Inline css styling set from TBE_STYLES array
 
+               // Skinning
+               // stylesheets from core
+       protected $stylesheetsCore = array(
+               'structure' => 'stylesheets/structure/',
+               'visual' => 'stylesheets/visual/',
+       );
+
+               // include these CSS directories from skins by default
+       protected $stylesheetsSkins = array(
+               'structure' => 'stylesheets/structure/',
+               'visual' => 'stylesheets/visual/',
+       );
+
                // DEV:
        var $parseTimeFlag = 0;                 // Will output the parsetime of the scripts in milliseconds (for admin-users). Set this to false when releasing TYPO3. Only for dev.
 
@@ -215,6 +228,12 @@ class template {
        protected $pageRenderer;
        protected $pageHeaderFooterTemplateFile = '';   // alternative template file
 
+       /**
+        * Whether flashmessages should be rendered or not
+        *
+        * @var $showFlashMessages
+        */
+       public $showFlashMessages = TRUE;
 
        /**
         * Constructor
@@ -263,6 +282,11 @@ class template {
                if ($TBE_STYLES['styleSheetFile_post']) $this->styleSheetFile_post = $TBE_STYLES['styleSheetFile_post'];
                if ($TBE_STYLES['inDocStyles_TBEstyle'])        $this->inDocStyles_TBEstyle = $TBE_STYLES['inDocStyles_TBEstyle'];
 
+                       // include all stylesheets
+               foreach ($this->getSkinStylesheetDirectories() as $stylesheetDirectory) {
+                       $this->addStylesheetDirectory($stylesheetDirectory);
+               }
+
                        // Background image
                if ($TBE_STYLES['background'])  $this->backGroundImage = $TBE_STYLES['background'];
        }
@@ -270,7 +294,7 @@ class template {
 
        /**
         * Gets instance of PageRenderer
-        * 
+        *
         * @return      t3lib_PageRenderer
         */
        public function getPageRenderer() {
@@ -279,6 +303,8 @@ class template {
                        $this->pageRenderer->setTemplateFile(
                                TYPO3_mainDir . 'templates/template_page_backend.html'
                        );
+                       $this->pageRenderer->setLanguage($GLOBALS['LANG']->lang);
+                       $this->pageRenderer->enableConcatenateFiles();
                }
                return $this->pageRenderer;
        }
@@ -701,32 +727,33 @@ class template {
                if ($this->docType !== 'html_3') {
                                // Put the XML prologue before or after the doctype declaration according to browser
                        if ($browserInfo['browser'] === 'msie' && $browserInfo['version'] < 7) {
-                               $headerStart = $headerStart . chr(10) . $xmlPrologue;
+                               $headerStart = $headerStart . LF . $xmlPrologue;
                        } else {
-                               $headerStart = $xmlPrologue . chr(10) . $headerStart;
+                               $headerStart = $xmlPrologue . LF . $headerStart;
                        }
 
                                // Add the xml stylesheet according to doctype
                        if ($this->docType !== 'xhtml_frames') {
-                               $headerStart = $headerStart . chr(10) . $xmlStylesheet;
+                               $headerStart = $headerStart . LF . $xmlStylesheet;
                        }
                }
 
                $this->pageRenderer->setXmlPrologAndDocType($headerStart);
-               $this->pageRenderer->setHeadTag('<head>' . chr(10). '<!-- TYPO3 Script ID: '.htmlspecialchars($this->scriptID).' -->');
+               $this->pageRenderer->setHeadTag('<head>' . LF. '<!-- TYPO3 Script ID: '.htmlspecialchars($this->scriptID).' -->');
                $this->pageRenderer->setCharSet($this->charset);
                $this->pageRenderer->addMetaTag($this->generator());
+               $this->pageRenderer->addMetaTag($this->xUaCompatible());
                $this->pageRenderer->setTitle($title);
-               
+
                // add docstyles
                $this->docStyle();
 
 
                // add jsCode - has to go to headerData as it may contain the script tags already
                $this->pageRenderer->addHeaderData($this->JScode);
-               
+
                foreach ($this->JScodeArray as $name => $code) {
-                       $this->pageRenderer->addJsInlineCode($name, $code);     
+                       $this->pageRenderer->addJsInlineCode($name, $code);
                }
 
                if (count($this->JScodeLibArray)) {
@@ -747,7 +774,7 @@ class template {
                $this->JScodeArray = array();
 
                $this->endOfPageJsBlock = $this->pageRenderer->render(t3lib_PageRenderer::PART_FOOTER);
-               
+
                if ($this->docType=='xhtml_frames')     {
                        return $str;
                } else
@@ -878,14 +905,17 @@ $str.=$this->docBodyTagBegin().
         * @param       string          Additional attributes to h-tag, eg. ' class=""'
         * @return      string          HTML content
         */
-       function sectionHeader($label,$sH=FALSE,$addAttrib='')  {
-               $tag = ($sH?'h3':'h4');
+       function sectionHeader($label, $sH=FALSE, $addAttrib='') {
+               $tag = ($sH ? 'h3' : 'h4');
+               if ($addAttrib && substr($addAttrib, 0, 1) !== ' ') {
+                       $addAttrib = ' ' . $addAttrib;
+               }
                $str='
 
        <!-- Section header -->
-       <'.$tag.$addAttrib.'>'.$label.'</'.$tag.'>
+       <' . $tag . $addAttrib . '>' . $label . '</' . $tag . '>
 ';
-               return $this->sectionBegin().$str;
+               return $this->sectionBegin() . $str;
        }
 
        /**
@@ -984,7 +1014,7 @@ $str.=$this->docBodyTagBegin().
                $this->inDocStylesArray[] = $this->inDocStyles_TBEstyle;
 
                        // Implode it all:
-               $inDocStyles = implode(chr(10), $this->inDocStylesArray);
+               $inDocStyles = implode(LF, $this->inDocStylesArray);
 
                if ($this->styleSheetFile) {
                        $this->pageRenderer->addCssFile($this->backPath . $this->styleSheetFile);
@@ -993,10 +1023,10 @@ $str.=$this->docBodyTagBegin().
                        $this->pageRenderer->addCssFile($this->backPath . $this->styleSheetFile2);
                }
 
-               $this->pageRenderer->addCssInlineBlock('inDocStyles', $inDocStyles . chr(10) . '/*###POSTCSSMARKER###*/');
+               $this->pageRenderer->addCssInlineBlock('inDocStyles', $inDocStyles . LF . '/*###POSTCSSMARKER###*/');
                if ($this->styleSheetFile_post) {
                        $this->pageRenderer->addCssFile($this->backPath . $this->styleSheetFile_post);
-       }
+               }
 
        }
 
@@ -1015,7 +1045,26 @@ $str.=$this->docBodyTagBegin().
                } else {
                        $file = $this->backPath . $href;
                }
-               $this->pageRenderer->addCssFile($file, $relation, $title);
+               $this->pageRenderer->addCssFile($file, $relation, 'screen', $title);
+       }
+
+       /**
+        * Add all *.css files of the directory $path to the stylesheets
+        *
+        * @param       string          directory to add
+        * @return      void
+        */
+       function addStyleSheetDirectory($path) {
+                       // calculation needed, when TYPO3 source is used via a symlink
+                       // absolute path to the stylesheets
+               $filePath = dirname(t3lib_div::getIndpEnv('SCRIPT_FILENAME')) . '/' . $GLOBALS['BACK_PATH'] . $path;
+                       // clean the path
+               $resolvedPath = t3lib_div::resolveBackPath($filePath);
+                       // read all files in directory and sort them alphabetically
+               $files = t3lib_div::getFilesInDir($resolvedPath, 'css', FALSE, 1);
+               foreach ($files as $file) {
+                       $this->pageRenderer->addCssFile($GLOBALS['BACK_PATH'] . $path . $file, 'stylesheet', 'all');
+               }
        }
 
        /**
@@ -1028,17 +1077,61 @@ $str.=$this->docBodyTagBegin().
        function insertStylesAndJS($content)    {
                        // insert accumulated CSS
                $this->inDocStylesArray[] = $this->inDocStyles;
-               $styles = "\n".implode("\n", $this->inDocStylesArray);
+               $styles = LF.implode(LF, $this->inDocStylesArray);
                $content = str_replace('/*###POSTCSSMARKER###*/',$styles,$content);
 
                        // insert accumulated JS
-               $jscode = $this->JScode."\n".$this->wrapScriptTags(implode("\n", $this->JScodeArray));
+               $jscode = $this->JScode.LF.$this->wrapScriptTags(implode(LF, $this->JScodeArray));
                $content = str_replace('<!--###POSTJSMARKER###-->',$jscode,$content);
 
                return $content;
        }
 
        /**
+        * Returns an array of all stylesheet directories belonging to core and skins
+        *
+        * @return      array   Stylesheet directories
+        */
+       public function getSkinStylesheetDirectories() {
+               $stylesheetDirectories = array();
+
+                       // add default core stylesheets
+               foreach ($this->stylesheetsCore as $stylesheetDir) {
+                       $stylesheetDirectories[] = $stylesheetDir;
+               }
+
+                       // Stylesheets from skins
+                       // merge default css directories ($this->stylesheetsSkin) with additional ones and include them
+               if (is_array($GLOBALS['TBE_STYLES']['skins'])) {
+                               // loop over all registered skins
+                       foreach ($GLOBALS['TBE_STYLES']['skins'] as $skinExtKey => $skin) {
+                               $skinStylesheetDirs = $this->stylesheetsSkins;
+
+                                       // skins can add custom stylesheetDirectories using
+                                       // $TBE_STYLES['skins'][$_EXTKEY]['stylesheetDirectories']
+                               if (is_array($skin['stylesheetDirectories'])) {
+                                       $skinStylesheetDirs = array_merge($skinStylesheetDirs, $skin['stylesheetDirectories']);
+                               }
+
+                                       // add all registered directories
+                               foreach ($skinStylesheetDirs as $stylesheetDir) {
+                                               // for EXT:myskin/stylesheets/ syntax
+                                       if (substr($stylesheetDir, 0, 4) === 'EXT:') {
+                                               list($extKey, $path) = explode('/', substr($stylesheetDir, 4), 2);
+                                               if (strcmp($extKey, '') && t3lib_extMgm::isLoaded($extKey) && strcmp($path, '')) {
+                                                       $stylesheetDirectories[] = t3lib_extMgm::extRelPath($extKey) . $path;
+                                               }
+                                       } else {
+                                               // for relative paths
+                                               $stylesheetDirectories[] = t3lib_extMgm::extRelPath($skinExtKey) . $stylesheetDir;
+                                       }
+                               }
+                       }
+               }
+               return $stylesheetDirectories;
+       }
+
+       /**
         * Initialize the charset.
         * Sets the internal $this->charset variable to the charset defined in $GLOBALS["LANG"] (or the default as set in this class)
         * Returns the meta-tag for the document header
@@ -1062,6 +1155,16 @@ $str.=$this->docBodyTagBegin().
                return '<meta name="generator" content="'.$str .'" />';
        }
 
+       /**
+        * Returns X-UA-Compatible meta tag
+        *
+        * @return      string          <meta http-equiv="X-UA-Compatible" content="???" />
+        */
+       function xUaCompatible() {
+                       // the most recent version if Internet Explorer, in which the Backend works
+               $str = "IE=8";
+               return '<meta http-equiv="X-UA-Compatible" content="' . $str . '" />';
+       }
 
 
 
@@ -1170,14 +1273,14 @@ $str.=$this->docBodyTagBegin().
        function wrapScriptTags($string, $linebreak=TRUE)       {
                if(trim($string)) {
                                // <script wrapped in nl?
-                       $cr = $linebreak? "\n" : '';
+                       $cr = $linebreak? LF : '';
 
                                // remove nl from the beginning
                        $string = preg_replace ('/^\n+/', '', $string);
                                // re-ident to one tab using the first line as reference
                        $match = array();
                        if(preg_match('/^(\t+)/',$string,$match)) {
-                               $string = str_replace($match[1],"\t", $string);
+                               $string = str_replace($match[1],TAB, $string);
                        }
                        $string = $cr.'<script type="text/javascript">
 /*<![CDATA[*/
@@ -1547,7 +1650,7 @@ $str.=$this->docBodyTagBegin().
                                }
 
                                $mouseOverOut = ' onmouseover="DTM_mouseOver(this);" onmouseout="DTM_mouseOut(this);"';
-                               $requiredIcon = '<img name="' . $id . '-' . $index . '-REQ" src="' . $GLOBALS['BACK_PATH'] . 'gfx/clear.gif" width="10" height="10" hspace="4" alt="" />';
+                               $requiredIcon = '<img name="' . $id . '-' . $index . '-REQ" src="' . $GLOBALS['BACK_PATH'] . 'gfx/clear.gif" class="t3-TCEforms-reqTabImg" alt="" />';
 
                                if (!$foldout)  {
                                                // Create TAB cell:
@@ -1892,26 +1995,28 @@ $str.=$this->docBodyTagBegin().
                        $moduleBody = t3lib_parsehtml::substituteSubpart($moduleBody, $marker, $content);
                }
 
-                       // adding flash messages
-               $flashMessages = t3lib_FlashMessageQueue::renderFlashMessages();
-               if (!empty($flashMessages)) {
-                       $flashMessages = '<div id="typo3-messages">' . $flashMessages . '</div>';
-               }
+               if ($this->showFlashMessages) {
+                               // adding flash messages
+                       $flashMessages = t3lib_FlashMessageQueue::renderFlashMessages();
+                       if (!empty($flashMessages)) {
+                               $flashMessages = '<div id="typo3-messages">' . $flashMessages . '</div>';
+                       }
 
-               if (strstr($moduleBody, '###FLASHMESSAGES###')) {
-                               // either replace a dedicated marker for the messages if present
-                       $moduleBody = str_replace(
-                               '###FLASHMESSAGES###',
-                               $flashMessages,
-                               $moduleBody
-                       );
-               } else {
-                               // or force them to appear before the content
-                       $moduleBody = str_replace(
-                               '###CONTENT###',
-                               $flashMessages . '###CONTENT###',
-                               $moduleBody
-                       );
+                       if (strstr($moduleBody, '###FLASHMESSAGES###')) {
+                                       // either replace a dedicated marker for the messages if present
+                               $moduleBody = str_replace(
+                                       '###FLASHMESSAGES###',
+                                       $flashMessages,
+                                       $moduleBody
+                               );
+                       } else {
+                                       // or force them to appear before the content
+                               $moduleBody = str_replace(
+                                       '###CONTENT###',
+                                       $flashMessages . '###CONTENT###',
+                                       $moduleBody
+                               );
+                       }
                }
 
                        // replacing all markers with the finished markers and return the HTML content
@@ -1948,7 +2053,7 @@ $str.=$this->docBodyTagBegin().
                                }
                        }
                                // replace the marker with the template and remove all line breaks (for IE compat)
-                       $markers['BUTTONLIST_' . strtoupper($key)] = str_replace("\n", '', $buttonTemplate);
+                       $markers['BUTTONLIST_' . strtoupper($key)] = str_replace(LF, '', $buttonTemplate);
                }
 
                        // Hook for manipulating docHeaderButtons
@@ -2008,6 +2113,7 @@ $str.=$this->docBodyTagBegin().
                        $iconImg = t3lib_iconWorks::getIconImage('pages', $pageRecord, $this->backPath, 'class="absmiddle" title="'. htmlspecialchars($alttext) . '"');
                                // Make Icon:
                        $theIcon = $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg, 'pages', $pageRecord['uid']);
+                       $pid = $pageRecord['uid'];
                } else {        // On root-level of page tree
                                // Make Icon
                        $iconImg = '<img' . t3lib_iconWorks::skinImg($this->backPath, 'gfx/i/_icon_website.gif') . ' alt="' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] . '" />';
@@ -2016,10 +2122,11 @@ $str.=$this->docBodyTagBegin().
                        } else {
                                $theIcon = $iconImg;
                        }
+                       $pid = '0 (root)';
                }
 
                        // Setting icon with clickmenu + uid
-               $pageInfo = $theIcon . '<em>[pid: ' . $pageRecord['uid'] . ']</em>';
+               $pageInfo = $theIcon . '<em>[pid: ' . $pid . ']</em>';
                return $pageInfo;
        }
 
@@ -2080,6 +2187,18 @@ class mediumDoc extends template {
 class frontendDoc extends template {
 
        /**
+        * Gets instance of PageRenderer
+        *
+        * @return      t3lib_PageRenderer
+        */
+       public function getPageRenderer() {
+               if (!isset($this->pageRenderer)) {
+                       $this->pageRenderer = $GLOBALS['TSFE']->getPageRenderer();
+               }
+               return $this->pageRenderer;
+       }
+
+       /**
         * Used in the frontend context to insert header data via TSFE->additionalHeaderData.
         * Mimics header inclusion from template->startPage().
         *
@@ -2087,37 +2206,18 @@ class frontendDoc extends template {
         */
        public function insertHeaderData() {
 
-               /** @var $pageRenderer t3lib_PageRenderer */
-               $pageRenderer = $GLOBALS['TSFE']->getPageRenderer();
-
                $this->backPath = $GLOBALS['TSFE']->backPath = TYPO3_mainDir;
                $this->pageRenderer->setBackPath($this->backPath);
                $this->docStyle();
 
                        // add applied JS/CSS to $GLOBALS['TSFE']
                if ($this->JScode) {
-                       $pageRenderer->addHeaderData($this->JScode);
+                       $this->pageRenderer->addHeaderData($this->JScode);
                }
                if (count($this->JScodeArray)) {
                        foreach ($this->JScodeArray as $name => $code) {
-                               $pageRenderer->addJsInlineCode($name, $code);   
-       }
-}
-
-               if ($this->addPrototype) {
-                       $pageRenderer->loadPrototype();
-               }
-               if ($this->addScriptaculous) {
-                       $pageRenderer->loadScriptaculous();
-               }
-               if ($this->addExtJS) {
-                       $pageRenderer->loadExtJs();
-               }
-               if ($this->inlineLanguageLabels) {
-                       $pageRenderer->addInlineLanguageLabelArray($this->inlineLanguageLabels);
-               }
-               if ($this->inlineSettings) {
-                       $pageRenderer->addInlineSettingArray($this->inlineSettings);
+                               $this->pageRenderer->addJsInlineCode($name, $code);
+                       }
                }
        }
 }