Add basic validation for StyleGlobalValuesForm
authorjoshuaruesweg <ruesweg@woltlab.com>
Tue, 4 Aug 2020 12:52:35 +0000 (14:52 +0200)
committerjoshuaruesweg <ruesweg@woltlab.com>
Tue, 4 Aug 2020 12:52:35 +0000 (14:52 +0200)
wcfsetup/install/files/acp/templates/styleGlobalValues.tpl
wcfsetup/install/files/lib/acp/form/StyleGlobalValuesForm.class.php
wcfsetup/install/files/lib/system/style/StyleCompiler.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 51e53478cb67154ce4f32be80400e29dd2c145a0..aa087b1a1547c96517205443d4d57cd51a6316f5 100644 (file)
@@ -22,7 +22,7 @@
 {/if}
 
 <form method="post" action="{link controller='StyleGlobalValues'}{/link}">
-       <div class="section">
+       <div class="section"{if $errorField == 'styles'} formError{/if}>
                <dl>
                        <dt>{lang}wcf.acp.style.globalValues.input{/lang}</dt>
                        <dd>
                                        <input class="codeMirrorScrollOffset" name="stylesScrollOffset" value="{$stylesScrollOffset}" type="hidden">
                                </div>
                        </dd>
+                       {if $errorField == 'styles'}
+                               <small class="innerError">
+                                       {lang}wcf.acp.style.globalValues.input.error{/lang}
+                               </small>
+                       {/if}
                </dl>
                {include file='codemirror' codemirrorMode='text/x-less' codemirrorSelector='#styles'}
        </div>
index a86b2b551e1dc5415220dbc799f81f024f4a9fab..e7c34efe113f8779a360b1177201f965db393eb4 100644 (file)
@@ -1,10 +1,12 @@
 <?php
 namespace wcf\acp\form;
 use wcf\form\AbstractForm;
+use wcf\system\exception\UserInputException;
 use wcf\system\registry\RegistryHandler;
 use wcf\system\style\StyleCompiler;
 use wcf\system\style\StyleHandler;
 use wcf\system\WCF;
+use wcf\util\FileUtil;
 use wcf\util\StringUtil;
 
 /**
@@ -58,6 +60,33 @@ class StyleGlobalValuesForm extends AbstractForm {
                }
        }
        
+       /**
+        * @inheritDoc
+        */
+       public function validate() {
+               parent::validate();
+               
+               $tmpFile = FileUtil::getTemporaryFilename('styleGlobalValues_', '.scss');
+               file_put_contents($tmpFile, $this->styles);
+               
+               try {
+                       // Due to performance issues we can only compile the default style and check, 
+                       // whether there are syntax issues. 
+                       $defaultStyle = StyleHandler::getInstance()->getDefaultStyle();
+                       $errorMessage = StyleCompiler::getInstance()->testStyle($defaultStyle->apiVersion, $defaultStyle->imagePath, $defaultStyle->getVariables(), $tmpFile);
+                       
+                       if ($errorMessage !== true) {
+                               throw new UserInputException('styles', [
+                                       'message' => $errorMessage,
+                               ]);
+                       }
+               }
+               finally {
+                       unlink($tmpFile);
+               }
+               
+       }
+       
        /**
         * @inheritDoc
         */
index 810dcc42488132638507978c4c993c67942ca08b..6868a9904f7d634398e3185db0da781ebcb3e2ed 100644 (file)
@@ -98,10 +98,11 @@ class StyleCompiler extends SingletonFactory {
         * @param       string          $apiVersion
         * @param       string          $imagePath
         * @param       string[]        $variables
+        * @param       string|null     $customCustomSCSSFile
         * @return      bool|string
         * @since       5.3           
         */
-       public function testStyle($apiVersion, $imagePath, array $variables) {
+       public function testStyle($apiVersion, $imagePath, array $variables, $customCustomSCSSFile = null) {
                $individualScss = '';
                if (isset($variables['individualScss'])) {
                        $individualScss = $variables['individualScss'];
@@ -135,9 +136,19 @@ class StyleCompiler extends SingletonFactory {
                $parameters = ['scss' => ''];
                EventHandler::getInstance()->fireAction($this, 'compile', $parameters);
                
+               $files = $this->getFiles();
+               
+               if ($customCustomSCSSFile !== null) {
+                       if (($customSCSSFileKey = array_search(WCF_DIR . self::FILE_GLOBAL_VALUES, $files)) !== false) {
+                               unset($files[$customSCSSFileKey]);
+                       }
+                       
+                       $files[] = $customCustomSCSSFile;
+               }
+               
                try {
                        $this->compileStylesheetToString(
-                               $this->getFiles(),
+                               $files,
                                $variables,
                                $individualScss . (!empty($parameters['scss']) ? "\n" . $parameters['scss'] : ''),
                                function($content) {
index b99a93427be6d4e18b02afa46aacfe4f1e31da67..ba830060cb7b1f7248bfa8e764cd1bfb396bb925 100644 (file)
@@ -2905,6 +2905,7 @@ Kein Abschnitt darf leer sein und alle Abschnitten dürfen nur folgende Zeichen
                <item name="wcf.acp.style.globalValues"><![CDATA[Stilunabhängiges CSS und SCSS]]></item>
                <item name="wcf.acp.style.globalValues.description"><![CDATA[Das unten stehende CSS und SCSS wird auf alle Stile angewandt, die individuelle Anpassungen in den Stilen sind jedoch höherwertig.]]></item>
                <item name="wcf.acp.style.globalValues.input"><![CDATA[Individuelles CSS und SCSS]]></item>
+               <item name="wcf.acp.style.globalValues.input.error"><![CDATA[Der SCSS-Code ist invalid: {$errorType.message}.]]></item>
                <item name="wcf.acp.style.image"><![CDATA[Vorschaubild]]></item>
                <item name="wcf.acp.style.image.description"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Lade{else}Laden Sie{/if} hier ein Vorschaubild dieses Stiles hoch, als Bildformate sind JPG und PNG zulässig. Es wird empfohlen Vorschaubilder immer mit der Größe 102×64 Pixel anzulegen, größere Grafiken werden automatisch skaliert.]]></item>
                <item name="wcf.acp.style.image2x"><![CDATA[Vorschaubild (HD)]]></item>
index 218dabaef589231ea82458be0c4abf95fb683b66..5efdb4b878781e47217646cbfe9fe76267e04c71 100644 (file)
@@ -2833,6 +2833,7 @@ If you have <strong>already bought the licenses for the listed apps</strong>, th
                <item name="wcf.acp.style.globalValues"><![CDATA[Global CSS and SCSS]]></item>
                <item name="wcf.acp.style.globalValues.description"><![CDATA[The CSS and SCSS entered below is applied to all styles, but custom values in styles take precedence.]]></item>
                <item name="wcf.acp.style.globalValues.input"><![CDATA[Individual CSS and SCSS]]></item>
+               <item name="wcf.acp.style.globalValues.input.error"><![CDATA[The SCSS code is invalid: {$errorType.message}.]]></item>
                <item name="wcf.acp.style.image"><![CDATA[Preview Image]]></item>
                <item name="wcf.acp.style.image.description"><![CDATA[Upload a preview image for this style, acceptable image types are JPG and PNG. Dimensions should be 102×64 pixels, exceeding images will be scaled.]]></item>
                <item name="wcf.acp.style.image2x"><![CDATA[Preview Image (HD)]]></item>