3 namespace wcf\acp\form
;
5 use wcf\data\package\Package
;
6 use wcf\data\style\Style
;
7 use wcf\data\style\StyleAction
;
8 use wcf\data\style\StyleEditor
;
9 use wcf\data\template\group\TemplateGroup
;
10 use wcf\data\user\cover\photo\UserCoverPhoto
;
11 use wcf\form\AbstractForm
;
12 use wcf\system\event\EventHandler
;
13 use wcf\system\exception\SystemException
;
14 use wcf\system\exception\UserInputException
;
15 use wcf\system\file\upload\UploadField
;
16 use wcf\system\file\upload\UploadHandler
;
17 use wcf\system\image\ImageHandler
;
18 use wcf\system\language\I18nHandler
;
20 use wcf\system\request\LinkHandler
;
21 use wcf\system\style\exception\FontDownloadFailed
;
22 use wcf\system\style\FontManager
;
23 use wcf\system\style\StyleCompiler
;
25 use wcf\util\ArrayUtil
;
26 use wcf\util\DateUtil
;
27 use wcf\util\FileUtil
;
28 use wcf\util\StringUtil
;
31 * Shows the style add form.
33 * @author Alexander Ebert
34 * @copyright 2001-2019 WoltLab GmbH
35 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
36 * @package WoltLabSuite\Core\Acp\Form
38 class StyleAddForm
extends AbstractForm
43 public $activeMenuItem = 'wcf.acp.menu.link.style.add';
49 public $authorName = '';
55 public $authorURL = '';
61 public $apiVersion = Style
::API_VERSION
;
64 * list of available font families
67 public $availableFontFamilies = [
68 'Arial, Helvetica, sans-serif' => 'Arial',
69 'Chicago, Impact, Compacta, sans-serif' => 'Chicago',
70 '"Comic Sans MS", sans-serif' => 'Comic Sans',
71 '"Courier New", Courier, monospace' => 'Courier New',
72 'Geneva, Arial, Helvetica, sans-serif' => 'Geneva',
73 'Georgia, "Times New Roman", Times, serif' => 'Georgia',
74 'Helvetica, Verdana, sans-serif' => 'Helvetica',
75 'Impact, Compacta, Chicago, sans-serif' => 'Impact',
76 '"Lucida Sans", "Lucida Grande", Monaco, Geneva, sans-serif' => 'Lucida',
77 '"Segoe UI", "DejaVu Sans", "Lucida Grande", Helvetica, sans-serif' => 'Segoe UI',
79 'Tahoma, Arial, Helvetica, sans-serif' => 'Tahoma',
80 '"Times New Roman", Times, Georgia, serif' => 'Times New Roman',
81 '"Trebuchet MS", Arial, sans-serif' => 'Trebuchet MS',
82 'Verdana, Helvetica, sans-serif' => 'Verdana',
86 * list of available template groups
87 * @var TemplateGroup[]
89 public $availableTemplateGroups = [];
92 * list of available units
95 public $availableUnits = ['px', 'pt', 'rem', 'em', '%'];
100 public $colorCategories = [];
103 * list of color variables
112 public $copyright = '';
115 * list of global variables
118 public $globals = [];
124 public $isTainted = true;
130 public $license = '';
135 public $neededPermissions = ['admin.style.canManageStyle'];
138 * list of variables that were added after 3.0
141 public $newVariables = [
143 'wcfContentContainerBackground' => '3.1',
144 'wcfContentContainerBorder' => '3.1',
145 'wcfEditorButtonBackground' => '3.1',
146 'wcfEditorButtonBackgroundActive' => '3.1',
147 'wcfEditorButtonText' => '3.1',
148 'wcfEditorButtonTextActive' => '3.1',
149 'wcfEditorButtonTextDisabled' => '3.1',
152 'wcfEditorTableBorder' => '5.2',
159 public $packageName = '';
165 public $styleDate = '0000-00-00';
171 public $styleDescription = '';
177 public $styleName = '';
183 public $styleVersion = '';
189 public $templateGroupID = 0;
192 * temporary image hash
195 public $tmpHash = '';
200 public $styleTestFileDir;
203 * list of variables and their value
206 public $variables = [];
209 * list of specialized variables
212 public $specialVariables = [];
215 * current scroll offsets before submitting the form
218 public $scrollOffsets = [];
221 * @var (null|UploadField)[]
224 public $uploads = [];
227 * @var (null|UploadField)[]
230 public $removedUploads = [];
236 public $customAssets = [];
238 public $supportedApiVersionsCompatibility = [
241 '5.2' => '5.2 / 5.3',
247 public function readParameters()
249 parent
::readParameters();
251 I18nHandler
::getInstance()->register('styleDescription');
253 $this->setVariables();
255 $this->rebuildUploadFields();
258 $this->readStyleVariables();
261 $this->availableTemplateGroups
= TemplateGroup
::getSelectList([-1], 1);
263 if (isset($_REQUEST['tmpHash'])) {
264 $this->tmpHash
= StringUtil
::trim($_REQUEST['tmpHash']);
266 if (empty($this->tmpHash
)) {
267 $this->tmpHash
= StringUtil
::getRandomID();
274 protected function getUploadFields()
279 'maxWidth' => Style
::PREVIEW_IMAGE_MAX_WIDTH
,
280 'maxHeight' => Style
::PREVIEW_IMAGE_MAX_WIDTH
,
281 'preserveAspectRatio' => false,
286 'maxWidth' => 2 * Style
::PREVIEW_IMAGE_MAX_WIDTH
,
287 'maxHeight' => 2 * Style
::PREVIEW_IMAGE_MAX_WIDTH
,
288 'preserveAspectRatio' => false,
292 'allowSvgImage' => true,
294 'pageLogoMobile' => [
295 'allowSvgImage' => true,
299 'minWidth' => UserCoverPhoto
::MIN_WIDTH
,
300 'maxWidth' => UserCoverPhoto
::MAX_WIDTH
,
301 'minHeight' => UserCoverPhoto
::MIN_HEIGHT
,
302 'maxHeight' => UserCoverPhoto
::MAX_HEIGHT
,
308 'minWidth' => Style
::FAVICON_IMAGE_WIDTH
,
309 'maxWidth' => Style
::FAVICON_IMAGE_WIDTH
,
310 'minHeight' => Style
::FAVICON_IMAGE_HEIGHT
,
311 'maxHeight' => Style
::FAVICON_IMAGE_HEIGHT
,
320 protected function rebuildUploadFields()
322 $handler = UploadHandler
::getInstance();
323 foreach ($this->getUploadFields() as $name => $options) {
324 if ($handler->isRegisteredFieldId($name)) {
325 $handler->unregisterUploadField($name);
327 $field = new UploadField($name);
328 $field->setImageOnly(true);
329 if (isset($options['allowSvgImage'])) {
330 $field->setAllowSvgImage($options['allowSvgImage']);
332 $field->maxFiles
= 1;
333 $handler->registerUploadField($field);
336 // This field is special cased, because it may contain arbitrary data.
337 $name = 'customAssets';
338 if ($handler->isRegisteredFieldId($name)) {
339 $handler->unregisterUploadField($name);
341 $field = new UploadField($name);
342 $field->setImageOnly(true);
343 $field->setAllowSvgImage(true);
344 $field->maxFiles
= null;
345 $handler->registerUploadField($field);
351 public function readFormParameters()
353 parent
::readFormParameters();
355 I18nHandler
::getInstance()->readValues();
358 foreach ($this->colors
as $categoryName => $variables) {
359 foreach ($variables as $variable) {
360 $colors[] = $categoryName . \
ucfirst($variable);
364 // ignore everything except well-formed rgba()
365 $regEx = new Regex('rgba\(\d{1,3}, \d{1,3}, \d{1,3}, (1|1\.00?|0|0?\.[0-9]{1,2})\)');
366 foreach ($colors as $variableName) {
367 if (isset($_POST[$variableName]) && $regEx->match($_POST[$variableName])) {
368 $this->variables
[$variableName] = $_POST[$variableName];
372 // read variables with units, e.g. 13px
373 foreach ($this->globals
as $variableName) {
374 if (isset($_POST[$variableName]) && \
is_numeric($_POST[$variableName])) {
376 isset($_POST[$variableName . '_unit']) && \
in_array(
377 $_POST[$variableName . '_unit'],
378 $this->availableUnits
381 $this->variables
[$variableName] = \abs
($_POST[$variableName]) . $_POST[$variableName . '_unit'];
385 $this->variables
[$variableName] = '0px';
389 // read specialized variables
390 $integerValues = ['pageLogoHeight', 'pageLogoWidth'];
391 foreach ($this->specialVariables
as $variableName) {
392 if (isset($_POST[$variableName])) {
393 $this->variables
[$variableName] = (\
in_array(
396 )) ? \abs
(\
intval($_POST[$variableName])) : StringUtil
::trim($_POST[$variableName]);
399 $this->variables
['useFluidLayout'] = isset($_POST['useFluidLayout']) ?
1 : 0;
402 if (isset($_POST['authorName'])) {
403 $this->authorName
= StringUtil
::trim($_POST['authorName']);
405 if (isset($_POST['authorURL'])) {
406 $this->authorURL
= StringUtil
::trim($_POST['authorURL']);
408 if (isset($_POST['copyright'])) {
409 $this->copyright
= StringUtil
::trim($_POST['copyright']);
411 if (isset($_POST['license'])) {
412 $this->license
= StringUtil
::trim($_POST['license']);
414 if (isset($_POST['packageName'])) {
415 $this->packageName
= StringUtil
::trim($_POST['packageName']);
417 if (isset($_POST['styleDate'])) {
418 $this->styleDate
= StringUtil
::trim($_POST['styleDate']);
420 if (isset($_POST['styleDescription'])) {
421 $this->styleDescription
= StringUtil
::trim($_POST['styleDescription']);
423 if (isset($_POST['styleName'])) {
424 $this->styleName
= StringUtil
::trim($_POST['styleName']);
426 if (isset($_POST['styleVersion'])) {
427 $this->styleVersion
= StringUtil
::trim($_POST['styleVersion']);
429 if (isset($_POST['templateGroupID'])) {
430 $this->templateGroupID
= \
intval($_POST['templateGroupID']);
432 if (isset($_POST['apiVersion']) && \
in_array($_POST['apiVersion'], Style
::$supportedApiVersions)) {
433 $this->apiVersion
= $_POST['apiVersion'];
436 // codemirror scroll offset
437 if (isset($_POST['scrollOffsets']) && \
is_array($_POST['scrollOffsets'])) {
438 $this->scrollOffsets
= ArrayUtil
::toIntegerArray($_POST['scrollOffsets']);
441 $this->uploads
= $this->removedUploads
= [];
442 foreach (\array_keys
($this->getUploadFields()) as $field) {
443 $removedFiles = UploadHandler
::getInstance()->getRemovedFiledByFieldId($field);
444 if (!empty($removedFiles)) {
445 $this->removedUploads
= \array_merge
($this->removedUploads
, $removedFiles);
448 $files = UploadHandler
::getInstance()->getFilesByFieldId($field);
449 if (!empty($files)) {
450 $this->uploads
[$field] = $files[0];
454 $this->customAssets
= [
455 'removed' => UploadHandler
::getInstance()->getRemovedFiledByFieldId('customAssets'),
456 'added' => UploadHandler
::getInstance()->getFilesByFieldId('customAssets'),
463 protected function downloadGoogleFont()
465 $fontManager = FontManager
::getInstance();
466 $family = $this->variables
['wcfFontFamilyGoogle'];
468 if (!$fontManager->isFamilyDownloaded($family)) {
470 $fontManager->downloadFamily($family);
471 } catch (FontDownloadFailed
$e) {
472 throw new UserInputException(
473 'wcfFontFamilyGoogle',
474 'downloadFailed' . ($e->getReason() ?
'.' . $e->getReason() : '')
484 public function validate()
488 if (empty($this->authorName
)) {
489 throw new UserInputException('authorName');
493 if (empty($this->styleDate
)) {
494 throw new UserInputException('styleDate');
497 DateUtil
::validateDate($this->styleDate
);
498 } catch (SystemException
$e) {
499 throw new UserInputException('styleDate', 'invalid');
503 if (empty($this->styleName
)) {
504 throw new UserInputException('styleName');
508 if (empty($this->styleVersion
)) {
509 throw new UserInputException('styleVersion');
510 } elseif (!Package
::isValidVersion($this->styleVersion
)) {
511 throw new UserInputException('styleVersion', 'invalid');
514 // validate style package name
515 if (!empty($this->packageName
)) {
516 if (!Package
::isValidPackageName($this->packageName
)) {
517 throw new UserInputException('packageName', 'invalid');
520 $this->enforcePackageNameRestriction();
523 // validate template group id
524 if ($this->templateGroupID
) {
525 if (!isset($this->availableTemplateGroups
[$this->templateGroupID
])) {
526 throw new UserInputException('templateGroupID');
530 if (!empty($this->variables
['overrideScss'])) {
531 $this->parseOverrides();
534 $this->downloadGoogleFont();
536 $this->validateIndividualScss();
538 $this->validateApiVersion();
540 $this->validateUploads();
544 * Validates the individual scss.
545 * @throws UserInputException
548 public function validateIndividualScss()
550 $variables = \array_merge
(StyleCompiler
::getDefaultVariables(), $this->variables
);
552 $this->styleTestFileDir
= FileUtil
::getTemporaryFilename('style_');
553 FileUtil
::makePath($this->styleTestFileDir
);
555 $result = StyleCompiler
::getInstance()->testStyle(
556 $this->styleTestFileDir
,
563 if ($result !== null) {
564 \rmdir
($this->styleTestFileDir
);
566 throw new UserInputException('individualScss', [
567 'message' => $result->getMessage(),
573 * Disallow the use of `com.woltlab.*` for package names to avoid accidental collisions.
575 * @throws UserInputException
577 protected function enforcePackageNameRestriction()
579 // 3rd party styles may never have com.woltlab.* as name
580 if (\
strpos($this->packageName
, 'com.woltlab.') !== false) {
581 throw new UserInputException('packageName', 'reserved');
586 * Validates the style API version.
588 * @throws UserInputException
591 protected function validateApiVersion()
593 if (!\
in_array($this->apiVersion
, Style
::$supportedApiVersions)) {
594 throw new UserInputException('apiVersion', 'invalid');
601 protected function validateUploads()
603 foreach ($this->getUploadFields() as $field => $options) {
604 $files = UploadHandler
::getInstance()->getFilesByFieldId($field);
605 if (\
count($files) > 1) {
606 throw new UserInputException($field, 'invalid');
612 if (isset($options['size'])) {
613 $fileLocation = $files[0]->getLocation();
614 if (($imageData = \
getimagesize($fileLocation)) === false) {
615 throw new UserInputException($field, 'invalid');
617 switch ($imageData[2]) {
619 case \IMAGETYPE_JPEG
:
624 throw new UserInputException($field, 'invalid');
627 $maxWidth = $options['size']['maxWidth'] ?? \PHP_INT_MAX
;
628 $maxHeight = $options['size']['maxHeight'] ?? \PHP_INT_MAX
;
629 $minWidth = $options['size']['minWidth'] ??
0;
630 $minHeight = $options['size']['minHeight'] ??
0;
632 if ($options['size']['resize'] ??
true) {
633 if ($imageData[0] > $maxWidth ||
$imageData[1] > $maxHeight) {
634 $adapter = ImageHandler
::getInstance()->getAdapter();
635 $adapter->loadFile($fileLocation);
636 $thumbnail = $adapter->createThumbnail(
639 $options['size']['preserveAspectRatio'] ??
true
641 $adapter->writeImage($thumbnail, $fileLocation);
642 // Clear thumbnail as soon as possible to free up the memory.
646 // Check again after scaling
647 if (($imageData = \
getimagesize($fileLocation)) === false) {
648 throw new UserInputException($field, 'invalid');
652 if ($imageData[0] > $maxWidth) {
653 throw new UserInputException($field, 'maxWidth');
655 if ($imageData[1] > $maxHeight) {
656 throw new UserInputException($field, 'maxHeight');
658 if ($imageData[0] < $minWidth) {
659 throw new UserInputException($field, 'minWidth');
661 if ($imageData[1] < $minHeight) {
662 throw new UserInputException($field, 'minHeight');
669 * Validates LESS-variable overrides.
671 * If an override is invalid, unknown or matches a variable covered by
672 * the style editor itself, it will be silently discarded.
674 * @param string $variableName
675 * @throws UserInputException
677 protected function parseOverrides($variableName = 'overrideScss')
679 static $colorNames = null;
680 if ($colorNames === null) {
682 foreach ($this->colors
as $colorPrefix => $colors) {
683 foreach ($colors as $color) {
684 $colorNames[] = $colorPrefix . \
ucfirst($color);
689 // get available variables
690 $sql = "SELECT variableName
691 FROM wcf" . WCF_N
. "_style_variable";
692 $statement = WCF
::getDB()->prepareStatement($sql);
693 $statement->execute();
694 $variables = $statement->fetchAll(\PDO
::FETCH_COLUMN
);
696 $lines = \
explode("\n", StringUtil
::unifyNewlines($this->variables
[$variableName]));
697 $regEx = new Regex('^\$([a-zA-Z]+):\s*([@a-zA-Z0-9 ,\.\(\)\%\#-]+);$');
699 foreach ($lines as $index => &$line) {
700 $line = StringUtil
::trim($line);
702 // ignore empty lines
704 unset($lines[$index]);
708 if ($regEx->match($line)) {
709 $matches = $regEx->getMatches();
711 // cannot override variables covered by style editor
713 \
in_array($matches[1], $colorNames) || \
in_array(
716 ) || \
in_array($matches[1], $this->specialVariables
)
719 'error' => 'predefined',
720 'text' => $matches[1],
722 } elseif (!\
in_array($matches[1], $variables)) {
723 // unknown style variable
725 'error' => 'unknown',
726 'text' => $matches[1],
729 $this->variables
[$matches[1]] = $matches[2];
734 'error' => 'invalid',
740 $this->variables
[$variableName] = \
implode("\n", $lines);
742 if (!empty($errors)) {
743 throw new UserInputException($variableName, $errors);
750 public function readData()
754 // parse global (unit) variables
755 foreach ($this->globals
as $variableName) {
758 '/(.*?)(' . \
implode('|', $this->availableUnits
) . ')$/',
759 $this->variables
[$variableName],
763 $this->variables
[$variableName] = $match[1];
764 $this->variables
[$variableName . '_unit'] = $match[2];
769 $this->setDefaultValues();
774 * Sets available variables
776 protected function setVariables()
778 $this->colorCategories
= [
779 'wcfHeader' => ['wcfHeader', 'wcfHeaderSearchBox', 'wcfHeaderMenu', 'wcfHeaderMenuDropdown'],
780 'wcfNavigation' => 'wcfNavigation',
781 'wcfSidebar' => ['wcfSidebar', 'wcfSidebarDimmed', 'wcfSidebarHeadline'],
782 'wcfContent' => ['wcfContent', 'wcfContentContainer', 'wcfContentDimmed', 'wcfContentHeadline'],
783 'wcfTabularBox' => 'wcfTabularBox',
784 'wcfInput' => ['wcfInput', 'wcfInputDisabled'],
785 'wcfButton' => ['wcfButton', 'wcfButtonPrimary', 'wcfButtonDisabled'],
786 'wcfEditor' => ['wcfEditorButton', 'wcfEditorTable'],
787 'wcfDropdown' => 'wcfDropdown',
788 'wcfStatus' => ['wcfStatusInfo', 'wcfStatusSuccess', 'wcfStatusWarning', 'wcfStatusError'],
789 'wcfFooterBox' => ['wcfFooterBox', 'wcfFooterBoxHeadline'],
790 'wcfFooter' => ['wcfFooter', 'wcfFooterHeadline', 'wcfFooterCopyright'],
794 'wcfHeader' => ['background', 'text', 'link', 'linkActive'],
795 'wcfHeaderSearchBox' => [
803 'wcfHeaderMenu' => ['background', 'linkBackground', 'linkBackgroundActive', 'link', 'linkActive'],
804 'wcfHeaderMenuDropdown' => ['background', 'link', 'backgroundActive', 'linkActive'],
805 'wcfNavigation' => ['background', 'text', 'link', 'linkActive'],
806 'wcfSidebar' => ['background', 'text', 'link', 'linkActive'],
807 'wcfSidebarDimmed' => ['text', 'link', 'linkActive'],
808 'wcfSidebarHeadline' => ['text', 'link', 'linkActive'],
809 'wcfContent' => ['background', 'border', 'borderInner', 'text', 'link', 'linkActive'],
810 'wcfContentContainer' => ['background', 'border'],
811 'wcfContentDimmed' => ['text', 'link', 'linkActive'],
812 'wcfContentHeadline' => ['border', 'text', 'link', 'linkActive'],
813 'wcfTabularBox' => ['borderInner', 'headline', 'backgroundActive', 'headlineActive'],
825 'wcfInputDisabled' => ['background', 'border', 'text'],
826 'wcfButton' => ['background', 'text', 'backgroundActive', 'textActive'],
827 'wcfButtonPrimary' => ['background', 'text', 'backgroundActive', 'textActive'],
828 'wcfButtonDisabled' => ['background', 'text'],
829 'wcfEditorButton' => ['background', 'backgroundActive', 'text', 'textActive', 'textDisabled'],
830 'wcfEditorTable' => ['border'],
831 'wcfDropdown' => ['background', 'borderInner', 'text', 'link', 'backgroundActive', 'linkActive'],
832 'wcfStatusInfo' => ['background', 'border', 'text', 'link', 'linkActive'],
833 'wcfStatusSuccess' => ['background', 'border', 'text', 'link', 'linkActive'],
834 'wcfStatusWarning' => ['background', 'border', 'text', 'link', 'linkActive'],
835 'wcfStatusError' => ['background', 'border', 'text', 'link', 'linkActive'],
836 'wcfFooterBox' => ['background', 'text', 'link', 'linkActive'],
837 'wcfFooterBoxHeadline' => ['text', 'link', 'linkActive'],
838 'wcfFooter' => ['background', 'text', 'link', 'linkActive'],
839 'wcfFooterHeadline' => ['text', 'link', 'linkActive'],
840 'wcfFooterCopyright' => ['background', 'text', 'link', 'linkActive'],
843 // set global variables
846 'wcfFontSizeDefault',
847 'wcfFontSizeHeadline',
848 'wcfFontSizeSection',
851 'wcfLayoutFixedWidth',
856 // set specialized variables
857 $this->specialVariables
= [
863 'wcfFontFamilyGoogle',
864 'wcfFontFamilyFallback',
867 EventHandler
::getInstance()->fireAction($this, 'setVariables');
871 * Reads style variable values.
873 protected function readStyleVariables()
875 $sql = "SELECT variableName, defaultValue
876 FROM wcf" . WCF_N
. "_style_variable";
877 $statement = WCF
::getDB()->prepareStatement($sql);
878 $statement->execute();
879 $this->variables
= $statement->fetchMap('variableName', 'defaultValue');
885 public function save()
889 // Remove control characters that break the SCSS parser, see https://stackoverflow.com/a/23066553
890 $this->variables
['individualScss'] = \
preg_replace('/[^\PC\s]/u', '', $this->variables
['individualScss']);
892 $this->objectAction
= new StyleAction([], 'create', [
893 'data' => \array_merge
($this->additionalFields
, [
894 'styleName' => $this->styleName
,
895 'templateGroupID' => $this->templateGroupID
,
896 'packageName' => $this->packageName
,
897 'isDisabled' => 1, // styles are disabled by default
899 'styleDescription' => '',
900 'styleVersion' => $this->styleVersion
,
901 'styleDate' => $this->styleDate
,
902 'copyright' => $this->copyright
,
903 'license' => $this->license
,
904 'authorName' => $this->authorName
,
905 'authorURL' => $this->authorURL
,
906 'apiVersion' => $this->apiVersion
,
908 'uploads' => $this->uploads
,
909 'removedUploads' => $this->removedUploads
,
910 'customAssets' => $this->customAssets
,
911 'tmpHash' => $this->tmpHash
,
912 'variables' => $this->variables
,
914 $returnValues = $this->objectAction
->executeAction();
915 $style = $returnValues['returnValues'];
917 // save style description
918 I18nHandler
::getInstance()->save(
920 'wcf.style.styleDescription' . $style->styleID
,
924 $styleEditor = new StyleEditor($style);
925 $styleEditor->update([
926 'styleDescription' => 'wcf.style.styleDescription' . $style->styleID
,
929 // Do not save the compiled style, because the image path was unknown during the style generation.
930 if ($this->styleTestFileDir
) {
931 if (\file_exists
($this->styleTestFileDir
. '/style.css')) {
932 \
unlink($this->styleTestFileDir
. '/style.css');
934 if (\file_exists
($this->styleTestFileDir
. '/style-rtl.css')) {
935 \
unlink($this->styleTestFileDir
. '/style-rtl.css');
937 if (\file_exists
($this->styleTestFileDir
. '/style-preload.json')) {
938 \
unlink($this->styleTestFileDir
. '/style-preload.json');
941 \rmdir
($this->styleTestFileDir
);
948 $this->authorName
= $this->authorURL
= $this->copyright
= $this->packageName
= '';
949 $this->license
= $this->styleDate
= $this->styleDescription
= $this->styleName
= $this->styleVersion
= '';
950 $this->setDefaultValues();
951 $this->isTainted
= true;
952 $this->templateGroupID
= 0;
953 $this->styleTestFilename
= null;
954 $this->rebuildUploadFields();
956 I18nHandler
::getInstance()->reset();
959 $this->readStyleVariables();
961 WCF
::getTPL()->assign([
963 'objectEditLink' => LinkHandler
::getInstance()->getControllerLink(
964 StyleEditForm
::class,
965 ['id' => $style->styleID
]
973 public function assignVariables()
975 parent
::assignVariables();
977 I18nHandler
::getInstance()->assignVariables();
979 WCF
::getTPL()->assign([
981 'apiVersion' => $this->apiVersion
,
982 'authorName' => $this->authorName
,
983 'authorURL' => $this->authorURL
,
984 'availableFontFamilies' => $this->availableFontFamilies
,
985 'availableTemplateGroups' => $this->availableTemplateGroups
,
986 'availableUnits' => $this->availableUnits
,
987 'colorCategories' => $this->colorCategories
,
988 'colors' => $this->colors
,
989 'copyright' => $this->copyright
,
990 'isTainted' => $this->isTainted
,
991 'license' => $this->license
,
992 'packageName' => $this->packageName
,
993 'recommendedApiVersion' => Style
::API_VERSION
,
994 'styleDate' => $this->styleDate
,
995 'styleDescription' => $this->styleDescription
,
996 'styleName' => $this->styleName
,
997 'styleVersion' => $this->styleVersion
,
998 'templateGroupID' => $this->templateGroupID
,
999 'tmpHash' => $this->tmpHash
,
1000 'variables' => $this->variables
,
1001 'supportedApiVersions' => Style
::$supportedApiVersions,
1002 'supportedApiVersionsCompatibility' => $this->supportedApiVersionsCompatibility
,
1003 'newVariables' => $this->newVariables
,
1004 'scrollOffsets' => $this->scrollOffsets
,
1005 'coverPhotoMinHeight' => UserCoverPhoto
::MIN_HEIGHT
,
1006 'coverPhotoMaxHeight' => UserCoverPhoto
::MAX_HEIGHT
,
1007 'coverPhotoMinWidth' => UserCoverPhoto
::MIN_WIDTH
,
1008 'coverPhotoMaxWidth' => UserCoverPhoto
::MAX_WIDTH
,
1012 protected function setDefaultValues()
1014 $this->authorName
= WCF
::getUser()->username
;
1015 $this->styleDate
= \
gmdate('Y-m-d', TIME_NOW
);
1016 $this->styleVersion
= '1.0.0';