use wcf\system\WCF;
use wcf\util\ArrayUtil;
use wcf\util\DateUtil;
+use wcf\util\FileUtil;
use wcf\util\StringUtil;
/**
*/
public $tmpHash = '';
+ /**
+ * @var string
+ */
+ public $styleTestFileDir;
+
/**
* list of variables and their value
* @var string[]
public function validateIndividualScss() {
$variables = array_merge(StyleCompiler::getDefaultVariables(), $this->variables);
- $result = StyleCompiler::getInstance()->testStyle($this->apiVersion, false, $variables);
+ $this->styleTestFileDir = FileUtil::getTemporaryFilename('style_');
+ FileUtil::makePath($this->styleTestFileDir);
- if ($result !== true) {
+ $result = StyleCompiler::getInstance()->testStyle($this->styleTestFileDir, $this->apiVersion, false, $variables);
+
+ if ($result !== null) {
throw new UserInputException('individualScss', [
- 'message' => $result,
+ 'message' => $result->getMessage(),
]);
}
}
'styleDescription' => 'wcf.style.styleDescription'.$style->styleID
]);
+ // save compiled style
+ if ($this->styleTestFileDir && file_exists($this->styleTestFileDir . '/style.css') && file_exists($this->styleTestFileDir . '/style-rtl.css')) {
+ $styleFilename = StyleCompiler::getFilenameForStyle($style);
+ rename($this->styleTestFileDir . '/style.css', $styleFilename . '.css');
+ rename($this->styleTestFileDir . '/style-rtl.css', $styleFilename . '-rtl.css');
+
+ rmdir($this->styleTestFileDir);
+ }
+
// call saved event
$this->saved();
$this->setDefaultValues();
$this->isTainted = true;
$this->templateGroupID = 0;
+ $this->styleTestFilename = null;
$this->rebuildUploadFields();
I18nHandler::getInstance()->reset();
use wcf\system\language\I18nHandler;
use wcf\system\style\StyleCompiler;
use wcf\system\WCF;
+use wcf\util\FileUtil;
/**
* Shows the style edit form.
$variables = array_merge(StyleCompiler::getDefaultVariables(), $variables);
- $result = StyleCompiler::getInstance()->testStyle($this->apiVersion, $this->style->imagePath, $variables);
+ $this->styleTestFileDir = FileUtil::getTemporaryFilename('style_');
+ FileUtil::makePath($this->styleTestFileDir);
- if ($result !== true) {
+ $result = StyleCompiler::getInstance()->testStyle($this->styleTestFileDir, $this->apiVersion, false, $variables);
+
+ if ($result !== null) {
throw new UserInputException('individualScss', [
- 'message' => $result,
+ 'message' => $result->getMessage(),
]);
}
}
]);
$this->objectAction->executeAction();
+ // save compiled style
+ if ($this->styleTestFileDir && file_exists($this->styleTestFileDir . '/style.css') && file_exists($this->styleTestFileDir . '/style-rtl.css')) {
+ $styleFilename = StyleCompiler::getFilenameForStyle($this->style);
+ rename($this->styleTestFileDir . '/style.css', $styleFilename . '.css');
+ rename($this->styleTestFileDir . '/style-rtl.css', $styleFilename . '-rtl.css');
+
+ rmdir($this->styleTestFileDir);
+ }
+
// save description
I18nHandler::getInstance()->save('styleDescription', $this->style->styleDescription, 'wcf.style');
*/
public $stylesScrollOffset = 0;
+ /**
+ * @var string
+ */
+ public $styleTestFileDir;
+
/**
* @inheritDoc
*/
// 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,
- ]);
+ if ($defaultStyle !== null) {
+ $this->styleTestFileDir = FileUtil::getTemporaryFilename('style_');
+ FileUtil::makePath($this->styleTestFileDir);
+
+ $errorMessage = StyleCompiler::getInstance()->testStyle($this->styleTestFileDir, $defaultStyle->apiVersion, $defaultStyle->imagePath, $defaultStyle->getVariables(), $tmpFile);
+
+ if ($errorMessage !== null) {
+ throw new UserInputException('styles', [
+ 'message' => $errorMessage->getMessage(),
+ ]);
+ }
}
}
finally {
// reset stylesheets
StyleHandler::resetStylesheets(false);
+ // save compiled style
+ $defaultStyle = StyleHandler::getInstance()->getDefaultStyle();
+ if ($defaultStyle !== null && $this->styleTestFileDir && file_exists($this->styleTestFileDir . '/style.css') && file_exists($this->styleTestFileDir . '/style-rtl.css')) {
+ $styleFilename = StyleCompiler::getFilenameForStyle($defaultStyle);
+ rename($this->styleTestFileDir . '/style.css', $styleFilename . '.css');
+ rename($this->styleTestFileDir . '/style-rtl.css', $styleFilename . '-rtl.css');
+
+ rmdir($this->styleTestFileDir);
+ }
+
WCF::getTPL()->assign('success', true);
}
/**
* Test a style with the given apiVersion, imagePath and variables. If the style is valid and does not throw an
- * error, true is returned. Otherwise a string with the error message.
+ * error, null is returned. Otherwise the exception is returned (!).
*
- * @param string $apiVersion
- * @param string $imagePath
- * @param string[] $variables
- * @param string|null $customCustomSCSSFile
- * @return bool|string
+ * @param string $testFileDir
+ * @param string $apiVersion
+ * @param string $imagePath
+ * @param string[] $variables
+ * @param string|null $customCustomSCSSFile
+ * @return null|\Exception
* @since 5.3
*/
- public function testStyle($apiVersion, $imagePath, array $variables, $customCustomSCSSFile = null) {
+ public function testStyle($testFileDir, $apiVersion, $imagePath, array $variables, $customCustomSCSSFile = null) {
$individualScss = '';
if (isset($variables['individualScss'])) {
$individualScss = $variables['individualScss'];
}
try {
- $this->compileStylesheetToString(
+ $this->compileStylesheet(
+ FileUtil::addTrailingSlash($testFileDir) . 'style',
$files,
$variables,
$individualScss . (!empty($parameters['scss']) ? "\n" . $parameters['scss'] : ''),
function($content) {
- return $content;
+ return "/* stylesheet, generated on ".gmdate('r')." -- DO NOT EDIT */\n\n" . $content;
}
);
}
catch (\Exception $e) {
- return $e->getMessage();
+ return $e;
}
- return true;
+ return null;
}
/**
EventHandler::getInstance()->fireAction($this, 'compile', $parameters);
$this->compileStylesheet(
- WCF_DIR.'style/style-'.$style->styleID,
+ $this->getFilenameForStyle($style),
$this->getFiles(),
$variables,
$individualScss . (!empty($parameters['scss']) ? "\n" . $parameters['scss'] : ''),
* @param callable $callback
*/
protected function compileStylesheet($filename, array $files, array $variables, $individualScss, callable $callback) {
- $content = $this->compileStylesheetToString($files, $variables, $individualScss, $callback);
-
- // write stylesheet
- file_put_contents($filename.'.css', $content['ltr']);
- FileUtil::makeWritable($filename.'.css');
-
- // write stylesheet for RTL
- file_put_contents($filename.'-rtl.css', $content['rtl']);
- FileUtil::makeWritable($filename.'-rtl.css');
- }
-
- /**
- * Compiles SCSS stylesheets and returns them as an array for the `ltr` and the `rtl` version.
- *
- * @param string[] $files
- * @param string[] $variables
- * @param string $individualScss
- * @param callable $callback
- * @return String[]
- * @since 5.3
- */
- public function compileStylesheetToString(array $files, array $variables, $individualScss, callable $callback) {
foreach ($variables as &$value) {
if (StringUtil::startsWith($value, '../')) {
$value = '~"'.$value.'"';
throw new SystemException("Could not compile SCSS: ".$e->getMessage(), 0, '', $e);
}
- $data['ltr'] = $callback($content);
+ $content = $callback($content);
+
+ // write stylesheet
+ file_put_contents($filename.'.css', $content);
+ FileUtil::makeWritable($filename.'.css');
// convert stylesheet to RTL
- $data['rtl'] = StyleUtil::convertCSSToRTL($content);
+ $content = StyleUtil::convertCSSToRTL($content);
// force code boxes to be always LTR
- $data['rtl'] .= "\n/* RTL fix for code boxes */\n";
- $data['rtl'] .= '.codeBox > div > ol > li > span:last-child, .redactor-layer pre { direction: ltr; text-align: left; } .codeBox > div > ol > li > span:last-child { display: block; }';
+ $content .= "\n/* RTL fix for code boxes */\n";
+ $content .= '.codeBox > div > ol > li > span:last-child, .redactor-layer pre { direction: ltr; text-align: left; } .codeBox > div > ol > li > span:last-child { display: block; }';
- return $data;
+ // write stylesheet for RTL
+ file_put_contents($filename.'-rtl.css', $content);
+ FileUtil::makeWritable($filename.'-rtl.css');
+ }
+
+ /**
+ * Returns the name of the CSS file for a specific style.
+ *
+ * @param Style $style
+ * @return string
+ * @since 5.3
+ */
+ public static function getFilenameForStyle(Style $style) {
+ return WCF_DIR.'style/style-'.$style->styleID;
}
}