Fixed stylesheet handling within ACP
authorAlexander Ebert <ebert@woltlab.com>
Thu, 20 Sep 2012 14:43:24 +0000 (16:43 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Thu, 20 Sep 2012 14:43:24 +0000 (16:43 +0200)
wcfsetup/install/files/acp/templates/header.tpl
wcfsetup/install/files/lib/system/style/StyleCompiler.class.php
wcfsetup/install/files/lib/system/style/StyleHandler.class.php
wcfsetup/install/files/lib/util/StyleUtil.class.php
wcfsetup/install/files/style/bootstrap/mixins.less [new file with mode: 0644]
wcfsetup/install/files/style/bootstrap/reset.less [new file with mode: 0644]
wcfsetup/install/files/style/bootstrap/variables.less [new file with mode: 0644]

index b18d338f0bf7b7c8750249b773b900b0b7f228c0..adf055a9e2811963fd711703a7c8b07aa05783ae 100644 (file)
@@ -28,7 +28,8 @@
        {event name='javascriptInclude'}
        
        <!-- Stylesheets -->
-       {@$__wcf->getStyleHandler()->getStylesheet()}
+       {* work-around for unknown core-object during WCFSetup *}
+       {if PACKAGE_ID}{@$__wcf->getStyleHandler()->getStylesheet(true)}{/if}
        
        {*
        {if $specialStyles|isset}
index f6534391f09badfa8783b11de35ad7b10c90484a..3073e16f021d9f39bf5c1b4d8de1db43fca614c6 100644 (file)
@@ -4,6 +4,7 @@ use wcf\data\style\Style;
 use wcf\system\application\ApplicationHandler;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
 use wcf\system\exception\SystemException;
+use wcf\system\Callback;
 use wcf\system\SingletonFactory;
 use wcf\system\WCF;
 use wcf\util\FileUtil;
@@ -80,31 +81,38 @@ class StyleCompiler extends SingletonFactory {
                        }
                }
                
-               $less = $this->bootstrap($variables, $individualLess);
-               foreach ($files as $file) {
-                       $less .= $this->prepareFile($file);
-               }
-               
-               // append individual CSS/LESS
-               if ($individualCss) {
-                       $less .= $individualCss;
-               }
-               
-               try {
-                       $content = $this->compiler->compile($less);
-               }
-               catch (\Exception $e) {
-                       throw new SystemException("Could not compile LESS: ".$e->getMessage(), 0, '', $e);
-               }
-               
-               // write stylesheet
-               file_put_contents(WCF_DIR.'style/style-'.ApplicationHandler::getInstance()->getPrimaryApplication()->packageID.'-'.$style->styleID.'.css', $content);
-               
-               // convert stylesheet to RTL
-               $content = StyleUtil::convertCSSToRTL($content);
+               $this->compileStylesheet(
+                       WCF_DIR.'style/style-'.ApplicationHandler::getInstance()->getPrimaryApplication()->packageID.'-'.$style->styleID,
+                       $files,
+                       $variables,
+                       $individualCss,
+                       $individualLess,
+                       new Callback(function($content) use ($style) {
+                               return "/* stylesheet for '".$style->styleName."', generated on ".gmdate('r')." -- DO NOT EDIT */\n\n" . $content;
+                       })
+               );
+       }
+       
+       /**
+        * Compiles LESS stylesheets for ACP usage.
+        */
+       public function compileACP() {
+               $files = glob(WCF_DIR.'style/*.less');
                
-               // write stylesheet for RTL
-               file_put_contents(WCF_DIR.'style/style-'.ApplicationHandler::getInstance()->getPrimaryApplication()->packageID.'-'.$style->styleID.'-rtl.css', $content);
+               $this->compileStylesheet(
+                       WCF_DIR.'acp/style/style',
+                       $files,
+                       array(),
+                       '',
+                       '',
+                       new Callback(function($content) {
+                               // fix relative paths
+                               $content = str_replace('../icon/', '../../icon/', $content);
+                               $content = str_replace('../images/', '../../images/', $content);
+                               
+                               return "/* stylesheet for ACP, generated on ".gmdate('r')." -- DO NOT EDIT */\n\n" . $content;
+                       })
+               );
        }
        
        /**
@@ -115,7 +123,7 @@ class StyleCompiler extends SingletonFactory {
         * @param       string                  $individualLess
         * @return      string
         */
-       protected function bootstrap(array &$variables, $individualLess = '') {
+       protected function bootstrap(array $variables, $individualLess = '') {
                // add reset like a boss
                $content = $this->prepareFile(WCF_DIR.'style/bootstrap/reset.less');
                
@@ -162,4 +170,46 @@ class StyleCompiler extends SingletonFactory {
                $filename = FileUtil::getRelativePath(WCF_DIR, dirname($filename)) . basename($filename);
                return '@import "'.$filename.'";'."\n";
        }
+       
+       /**
+        * Compiles LESS stylesheets into one CSS-stylesheet and writes them
+        * to filesystem. Please be aware not to append '.css' within $filename!
+        * 
+        * @param       string                  $filename
+        * @param       array<string>           $files
+        * @param       array<string>           $variables
+        * @param       string                  $individualCss
+        * @param       string                  $individualLess
+        * @param       wcf\system\Callback     $callback
+        */
+       protected function compileStylesheet($filename, array $files, array $variables, $individualCss, $individualLess, Callback $callback) {
+               // build LESS bootstrap
+               $less = $this->bootstrap($variables, $individualLess);
+               foreach ($files as $file) {
+                       $less .= $this->prepareFile($file);
+               }
+               
+               // append individual CSS/LESS
+               if ($individualCss) {
+                       $less .= $individualCss;
+               }
+               
+               try {
+                       $content = $this->compiler->compile($less);
+               }
+               catch (\Exception $e) {
+                       throw new SystemException("Could not compile LESS: ".$e->getMessage(), 0, '', $e);
+               }
+               
+               $content = $callback($content);
+               
+               // write stylesheet
+               file_put_contents($filename.'.css', $content);
+               
+               // convert stylesheet to RTL
+               $content = StyleUtil::convertCSSToRTL($content);
+               
+               // write stylesheet for RTL
+               file_put_contents($filename.'-rtl.css', $content);
+       }
 }
index 2835b42fc9bf6b9141fd0a1795f8ae95522c7f33..2772c8ad5ddcadd5727e8c92c4518edc0898e68c 100644 (file)
@@ -119,12 +119,23 @@ class StyleHandler extends SingletonFactory {
         * 
         * @todo        Add RTL support
         * 
+        * @param       boolean         $isACP
         * @return      string
         */
-       public function getStylesheet() {
-               $filename = 'style/style-'.ApplicationHandler::getInstance()->getPrimaryApplication()->packageID.'-'.$this->getStyle()->styleID.'.css';
-               if (!file_exists(WCF_DIR.$filename)) {
-                       StyleCompiler::getInstance()->compile($this->getStyle());
+       public function getStylesheet($isACP = false) {
+               if ($isACP) {
+                       // ACP
+                       $filename = 'acp/style/style.css';
+                       if (!file_exists(WCF_DIR.$filename)) {
+                               StyleCompiler::getInstance()->compileACP();
+                       }
+               }
+               else {
+                       // frontend
+                       $filename = 'style/style-'.ApplicationHandler::getInstance()->getPrimaryApplication()->packageID.'-'.$this->getStyle()->styleID.'.css';
+                       if (!file_exists(WCF_DIR.$filename)) {
+                               StyleCompiler::getInstance()->compile($this->getStyle());
+                       }
                }
                
                return '<link rel="stylesheet" type="text/css" href="'.WCF::getPath().$filename.'" />';
index 222665c79d97c8531a1d518e91cea8f1ad0c6ed2..1c9feee436038da8fe7c5adf77ba1014b76aef75 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 namespace wcf\util;
 use wcf\system\io\File;
+use wcf\system\style\StyleCompiler;
 
 /**
  * Contains Style-related functions.
@@ -100,67 +101,7 @@ final class StyleUtil {
         * Updates the acp style file.
         */
        public static function updateStyleFile() {
-               throw new \wcf\system\exception\SystemException("updateStyleFile()");
-               // get file handle
-               $file = new File(WCF_DIR . 'acp/style/style-ltr.css', 'wb');
-               
-               // include static styles
-               $staticStyles = glob(WCF_DIR.'style/*.css');
-               if ($staticStyles) {
-                       foreach ($staticStyles as $staticStyle) {
-                               if (!preg_match('/style-\d+(?:-rtl)?\.css/', $staticStyle)) {
-                                       // get style
-                                       $contents = file_get_contents($staticStyle);
-                                       // compress style
-                                       $contents = StyleUtil::compressCSS($contents);
-                                       // fix icon/image path
-                                       $contents = str_replace('../icon/', '../../icon/', $contents);
-                                       $contents = str_replace('../images/', '../../images/', $contents);
-                                       // write style
-                                       $file->write("/* static: ".basename($staticStyle)." */\n");
-                                       $file->write(StringUtil::trim($contents)."\n");
-                               }
-                       }
-               }
-               // include static acp styles
-               $staticStyles = glob(WCF_DIR.'acp/style/*.css');
-               if ($staticStyles) {
-                       foreach ($staticStyles as $staticStyle) {
-                               if (!preg_match('/style-(?:ltr|rtl)\.css/', $staticStyle) && !preg_match('/ie\dFix\.css/', $staticStyle)) {
-                                       $contents = file_get_contents($staticStyle);
-                                       $contents = StyleUtil::compressCSS($contents);
-                                       $file->write("/* static: acp/".basename($staticStyle)." */\n");
-                                       $file->write(StringUtil::trim($contents)."\n");
-                               }
-                       }
-               }
-               // close file
-               $file->close();
-               @chmod(WCF_DIR . 'acp/style/style-ltr.css', 0777);
-               
-               // update rtl version
-               self::updateStyleFileRTL();
-       }
-       
-       /**
-        * Converts the file of this style to a RTL ("right-to-left") version. 
-        */
-       public static function updateStyleFileRTL() {
-               throw new \wcf\system\exception\SystemException("updateStyleFileRTL()");
-               
-               // get contents of LTR version
-               $contents = file_get_contents(WCF_DIR . 'acp/style/style-ltr.css');
-               
-               // convert ltr to rtl
-               $contents = StyleUtil::convertCSSToRTL($contents);
-               
-               // write file
-               $file = new File(WCF_DIR . 'acp/style/style-rtl.css');
-               $file->write($contents);
-               
-               // close file
-               $file->close();
-               @chmod(WCF_DIR . 'acp/style/style-rtl.css', 0777);
+               StyleCompiler::getInstance()->compileACP();
        }
        
        private function __construct() { }
diff --git a/wcfsetup/install/files/style/bootstrap/mixins.less b/wcfsetup/install/files/style/bootstrap/mixins.less
new file mode 100644 (file)
index 0000000..bd79c77
--- /dev/null
@@ -0,0 +1,101 @@
+/* shortcuts */
+// clearing floats like a boss h5bp.com/q
+.clearfix {
+       // trigger 'hasLayout'
+       *zoom: 1;
+       
+       &:before,
+       &:after {
+               display: table;
+               content: "";
+       }
+       
+       &:after {
+               clear: both;
+       }
+}
+
+.square(@size) {
+       height: @size;
+       width: @size;
+}
+
+
+// sets default text shadows depending on background color
+.textShadow(@backgroundColor) when (lightness(@backgroundColor) >= 40%) {
+       text-shadow: 0 1px 0 rgba(255, 255, 255, .5);
+}
+.textShadow(@backgroundColor) when (lightness(@backgroundColor) < 60%) {
+       text-shadow: 0 -1px 0 rgba(0, 0, 0, .5);
+}
+
+/* CSS 3 */
+.linearGradient(@backgroundColor, @gradientColor1, @gradientColor2) {
+       background-color: @backgroundColor;
+       background-image: -webkit-linear-gradient(@gradientColor1, @gradientColor2);
+       background-image: -moz-linear-gradient(@gradientColor1, @gradientColor2);
+       background-image: -o-linear-gradient(@gradientColor1, @gradientColor2);
+       background-image: -ms-linear-gradient(@gradientColor1, @gradientColor2);
+       background-image: linear-gradient(@gradientColor1, @gradientColor2);
+}
+
+.linearGradient(@backgroundColor, @gradientColor1, @gradientColor2, @gradientColor3, @direction: top) {
+       background-color: @backgroundColor;
+       background-image: -webkit-linear-gradient(@direction, @gradientColor1, @gradientColor2, @gradientColor3);
+       background-image: -moz-linear-gradient(@direction, @gradientColor1, @gradientColor2, @gradientColor3);
+       background-image: -o-linear-gradient(@direction, @gradientColor1, @gradientColor2, @gradientColor3);
+       background-image: -ms-linear-gradient(@direction, @gradientColor1, @gradientColor2, @gradientColor3);
+       background-image: linear-gradient(@direction, @gradientColor1, @gradientColor2, @gradientColor3);
+}
+
+.linearGradientNative(@parameters) {
+       background-image: -webkit-linear-gradient(@parameters);
+       background-image: -moz-linear-gradient(@parameters);
+       background-image: -o-linear-gradient(@parameters);
+       background-image: -ms-linear-gradient(@parameters);
+       background-image: linear-gradient(@parameters);
+}
+
+.transition(@property, @duration, @type: linear) {
+       -webkit-transition: @arguments;
+       -moz-transition: @arguments;
+       -ms-transition: @arguments;
+       -o-transition: @arguments;
+       transition: @arguments;
+}
+
+.boxShadow(@topOffset, @leftOffset, @color, @blurriness: 5px, @shadowHeight: 0) {
+       -webkit-box-shadow: @topOffset @leftOffset @blurriness @shadowHeight @color;
+       -moz-box-shadow: @topOffset @leftOffset @blurriness @shadowHeight @color;
+       -ms-box-shadow: @topOffset @leftOffset @blurriness @shadowHeight @color;
+       -o-box-shadow: @topOffset @leftOffset @blurriness @shadowHeight @color;
+       box-shadow: @topOffset @leftOffset @blurriness @shadowHeight @color;
+}
+
+.boxShadowInset(@topOffset, @leftOffset, @color, @blurriness: 5px, @shadowHeight: 0) {
+       -webkit-box-shadow: inset @topOffset @leftOffset @blurriness @shadowHeight @color;
+       -moz-box-shadow: inset @topOffset @leftOffset @blurriness @shadowHeight @color;
+       -ms-box-shadow: inset @topOffset @leftOffset @blurriness @shadowHeight @color;
+       -o-box-shadow: inset @topOffset @leftOffset @blurriness @shadowHeight @color;
+       box-shadow: inset @topOffset @leftOffset @blurriness @shadowHeight @color;
+}
+
+.boxShadowNative(@parameters) {
+       -webkit-box-shadow: @parameters;
+       -moz-box-shadow: @parameters;
+       -ms-box-shadow: @parameters;
+       -o-box-shadow: @parameters;
+       box-shadow: @parameters;
+}
+
+.borderRadius(@borderRadius: @wcfContainerBorderRadius) {
+       .borderRadius(@borderRadius, @borderRadius, @borderRadius, @borderRadius);
+}
+
+.borderRadius(@borderTopRadius, @borderBottomRadius) {
+       .borderRadius(@borderTopRadius, @borderTopRadius, @borderBottomRadius, @borderBottomRadius);
+}
+
+.borderRadius(@borderTopLeftRadius, @borderTopRightRadius, @borderBottomRightRadius, @borderBottomLeftRadius) {
+       border-radius: @arguments;
+}
\ No newline at end of file
diff --git a/wcfsetup/install/files/style/bootstrap/reset.less b/wcfsetup/install/files/style/bootstrap/reset.less
new file mode 100644 (file)
index 0000000..2088a00
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * Parts taken from
+ * http://meyerweb.com/eric/tools/css/reset/ 
+ * v2.0 | 20110126
+ * License: none (public domain)
+ * modifyed to meet the needs of WoltLab
+ */
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed, 
+figure, figcaption, footer, header, hgroup, 
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+       margin: 0;
+       padding: 0;
+       border: 0;
+       font-size: 100%;
+}
+
+h1, h2, h3, h4, h5, h6 {
+       font-weight: normal;
+}
+
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure, 
+footer, header, hgroup, menu, nav, section {
+       display: block;
+}
+
+ol, ul {
+       list-style: none;
+}
+
+blockquote, q {
+       quotes: none;
+}
+
+blockquote:before,
+blockquote:after,
+q:before,
+q:after {
+       content: '';
+       content: none;
+}
\ No newline at end of file
diff --git a/wcfsetup/install/files/style/bootstrap/variables.less b/wcfsetup/install/files/style/bootstrap/variables.less
new file mode 100644 (file)
index 0000000..daf068a
--- /dev/null
@@ -0,0 +1,136 @@
+/* ###### sxf values ###### */
+/* these values will be defined by the style editor (don't it touch here) */
+
+/* ### general (content) ### */
+@wcfContentBackgroundColor: #fff; // bg color for main content area
+@wcfColor: #666; // default text color
+@wcfLinkColor: #369; // default link color
+@wcfLinkHoverColor: #036; // link hover color
+
+/* ### containers ### */
+/* containers use the default text / link color, so the container bg color should be similar to the content bg color */
+@wcfContainerBackgroundColor: rgba(252, 253, 254, 1); // bg color for containers
+@wcfContainerAccentBackgroundColor: rgba(241, 245, 250, 1); // light variantion of the container bg color
+@wcfContainerHoverBackgroundColor: rgba(216, 231, 245, 1); // bg color for hover effects
+@wcfContainerBorderColor: #ccc; //#bcd; // border color for containers
+@wcfContainerBorderRadius: 6px; // border radius
+
+/* ### box header (table header) ### */
+@wcfTabularBoxBackgroundColor: #369; // bg color
+@wcfTabularBoxColor: #fff; // text / link color
+@wcfTabularBoxHoverColor: #fff; // link hover color
+
+/* ### user panel ### */
+@wcfUserPanelBackgroundColor: rgba(0, 0, 0, .5); // bg color
+@wcfUserPanelColor: #fff; // text / link color
+@wcfUserPanelHoverColor: #fff; // link hover color
+
+/* ### buttons ### */
+/* default */
+@wcfButtonBackgroundColor: #e3e3e3;
+@wcfButtonBorderColor: #bbb;
+@wcfButtonColor: #999;
+
+/* primary */
+@wcfButtonPrimaryBackgroundColor: rgba(216, 231, 245, 1);
+@wcfButtonPrimaryBorderColor: #69C;
+@wcfButtonPrimaryColor: #69C;
+
+/* hover */
+@wcfButtonHoverBackgroundColor: rgba(255, 229, 200, 1);
+@wcfButtonHoverBorderColor: #fa2;
+@wcfButtonHoverColor: #666;
+
+/* ### form elements ### */
+@wcfInputBackgroundColor: #fff;
+@wcfInputColor: #666;
+@wcfInputBorderColor: #ccc;
+@wcfInputHoverBackgroundColor: rgba(255, 249, 244, 1);
+@wcfInputHoverBorderColor: #fa2;
+
+/* ### fonts ### */
+@wcfBaseFontSize: 13px;
+@wcfBaseFontFamily: "Trebuchet MS", Arial, sans-serif;
+
+/* ### layouts ### */
+@wcfLayoutFluidGap: 21px;
+@wcfLayoutFixedWidth: 1200px;
+
+
+/* ###### additional variables ###### */
+/* values are taken from sxf variables; but you can overwrite them by individual less */
+
+/* ### outer page bg ### */
+@wcfPageBackgroundColor: @wcfContentBackgroundColor;
+@wcfPageColor: @wcfColor;
+@wcfPageLinkColor: @wcfLinkColor;
+@wcfPageLinkHoverColor: @wcfLinkHoverColor;
+
+/* ### sidebar ### */
+@wcfSidebarBackgroundColor: @wcfContentBackgroundColor;
+
+/* ### additional text variables ### */
+@wcfDimmedColor: lighten(@wcfColor, 10%);
+@wcfLabelColor: @wcfColor;
+@wcfHeadlineColor: @wcfColor;
+@wcfHeadlineFontFamily: @wcfBaseFontFamily;
+
+/* ### dropdown ### */
+@wcfDropdownBackgroundColor: @wcfContentBackgroundColor;
+@wcfDropdownColor: @wcfColor;
+@wcfDropdownBorderColor: @wcfContainerBorderColor;
+@wcfDropdownHoverBackgroundColor: @wcfContainerHoverBackgroundColor;
+
+
+/* ###### hardcoded values ###### */
+/* values are hardcoded; you can overwrite them by individual less */
+
+/* ### font size ### */
+@wcfBaseLineHeight: 1.27;
+@wcfHeadlineFontSize: 170%;
+@wcfSubHeadlineFontSize: 140%;
+@wcfTitleFontSize: 120%;
+@wcfSmallFontSize: 85%;
+
+/* ### form states and alerts ### */
+/* warning (orange) */
+@wcfWarningColor: #fff;
+@wcfWarningBackgroundColor: #ffb800;
+@wcfWarningBackgroundColor2: #a67800;
+
+/* error (red) */
+@wcfErrorColor: #fff;
+@wcfErrorBackgroundColor: #c95145;
+@wcfErrorBackgroundColor2: #913d37;
+
+/* success (green) */
+@wcfSuccessColor: #fff;
+@wcfSuccessBackgroundColor: #74a446;
+@wcfSuccessBackgroundColor2: #4d7730;
+
+/* info (blue) */
+@wcfInfoColor: #fff;
+@wcfInfoBackgroundColor: #4674a4;
+@wcfInfoBackgroundColor2: #304d77;
+
+/* ### tooltip ### */
+@wcfTooltipBackgroundColor: rgba(0, 0, 0, .8);
+@wcfTooltipColor: white;
+
+/* ### gap ### */
+@wcfGapTiny: 4px;
+@wcfGapSmall: 7px;
+@wcfGapMedium: 14px;
+@wcfGapLarge: 21px;
+
+
+/* ###### individual less values ###### */
+/* overwrite additional variables for blue sunrise */
+@wcfPageBackgroundColor: @wcfTabularBoxBackgroundColor;
+@wcfSidebarBackgroundColor: @wcfContainerHoverBackgroundColor;
+@wcfPageLinkColor: lighten(@wcfLinkColor, 10%);
+@wcfPageLinkHoverColor: @wcfUserPanelHoverColor;
+@wcfLabelColor: @wcfLinkColor;
+
+/* additional variables for blue sunrise */
+@wcfNavigationBackgroundColor: lighten(@wcfSidebarBackgroundColor, 3%);
\ No newline at end of file