Commit | Line | Data |
---|---|---|
6c80f0df AE |
1 | <?php |
2 | namespace wcf\acp\form; | |
3 | use wcf\data\style\Style; | |
4 | use wcf\data\style\StyleAction; | |
5 | use wcf\form\AbstractForm; | |
6 | use wcf\system\exception\IllegalLinkException; | |
268a850d | 7 | use wcf\system\exception\UserInputException; |
1b6a0dfc TD |
8 | use wcf\system\file\upload\UploadFile; |
9 | use wcf\system\file\upload\UploadHandler; | |
aa5fecb3 | 10 | use wcf\system\language\I18nHandler; |
268a850d | 11 | use wcf\system\style\StyleCompiler; |
6c80f0df | 12 | use wcf\system\WCF; |
5c7386a0 | 13 | use wcf\util\FileUtil; |
6c80f0df AE |
14 | |
15 | /** | |
16 | * Shows the style edit form. | |
17 | * | |
18 | * @author Alexander Ebert | |
7b7b9764 | 19 | * @copyright 2001-2019 WoltLab GmbH |
6c80f0df | 20 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> |
e71525e4 | 21 | * @package WoltLabSuite\Core\Acp\Form |
6c80f0df AE |
22 | */ |
23 | class StyleEditForm extends StyleAddForm { | |
24 | /** | |
0fcfe5f6 | 25 | * @inheritDoc |
6c80f0df | 26 | */ |
f02cfd96 | 27 | public $activeMenuItem = 'wcf.acp.menu.link.style.list'; |
6c80f0df | 28 | |
6c80f0df AE |
29 | /** |
30 | * style object | |
4e25add7 | 31 | * @var Style |
6c80f0df | 32 | */ |
2e572b29 | 33 | public $style; |
6c80f0df AE |
34 | |
35 | /** | |
36 | * style id | |
37 | * @var integer | |
38 | */ | |
39 | public $styleID = 0; | |
40 | ||
41 | /** | |
0fcfe5f6 | 42 | * @inheritDoc |
6c80f0df AE |
43 | */ |
44 | public function readParameters() { | |
45 | if (isset($_REQUEST['id'])) $this->styleID = intval($_REQUEST['id']); | |
46 | $this->style = new Style($this->styleID); | |
47 | if (!$this->style->styleID) { | |
48 | throw new IllegalLinkException(); | |
49 | } | |
50 | ||
51 | parent::readParameters(); | |
52 | } | |
53 | ||
bfbc0267 AE |
54 | /** |
55 | * @inheritDoc | |
56 | */ | |
57 | public function validate() { | |
58 | parent::validate(); | |
59 | ||
60 | if (!$this->style->isTainted) { | |
61 | $this->parseOverrides('overrideScssCustom'); | |
62 | } | |
63 | } | |
64 | ||
268a850d | 65 | /** |
66 | * @inheritDoc | |
67 | */ | |
68 | public function validateIndividualScss() { | |
69 | $variables = $this->variables; | |
70 | if (!$this->style->isTainted) { | |
71 | $variables['individualScss'] = Style::joinLessVariables($variables['individualScss'], $variables['individualScssCustom']); | |
72 | $variables['overrideScss'] = Style::joinLessVariables($variables['overrideScss'], $variables['overrideScssCustom']); | |
73 | ||
74 | unset($variables['individualScssCustom']); | |
75 | unset($variables['overrideScssCustom']); | |
76 | } | |
77 | ||
78 | $variables = array_merge(StyleCompiler::getDefaultVariables(), $variables); | |
79 | ||
5c7386a0 | 80 | $this->styleTestFileDir = FileUtil::getTemporaryFilename('style_'); |
81 | FileUtil::makePath($this->styleTestFileDir); | |
268a850d | 82 | |
3eff1581 | 83 | $result = StyleCompiler::getInstance()->testStyle($this->styleTestFileDir, $this->styleName, $this->apiVersion, $this->style->imagePath, $variables); |
5c7386a0 | 84 | |
85 | if ($result !== null) { | |
1b1f7fbe | 86 | rmdir($this->styleTestFileDir); |
87 | ||
268a850d | 88 | throw new UserInputException('individualScss', [ |
5c7386a0 | 89 | 'message' => $result->getMessage(), |
268a850d | 90 | ]); |
91 | } | |
92 | } | |
93 | ||
6147a666 AE |
94 | /** |
95 | * @inheritDoc | |
96 | */ | |
97 | protected function enforcePackageNameRestriction() { | |
98 | if ($this->style->isTainted) { | |
99 | parent::enforcePackageNameRestriction(); | |
100 | } | |
101 | } | |
102 | ||
811f5a93 AE |
103 | /** |
104 | * @inheritDoc | |
105 | */ | |
106 | protected function validateApiVersion() { | |
107 | if ($this->style->isTainted) { | |
108 | parent::validateApiVersion(); | |
109 | } | |
110 | else { | |
111 | $this->apiVersion = $this->style->apiVersion; | |
112 | } | |
113 | } | |
114 | ||
6c80f0df | 115 | /** |
0fcfe5f6 | 116 | * @inheritDoc |
6c80f0df AE |
117 | */ |
118 | protected function readStyleVariables() { | |
119 | $this->variables = $this->style->getVariables(); | |
120 | ||
121 | // fix empty values ~"" | |
122 | foreach ($this->variables as &$variableValue) { | |
123 | if ($variableValue == '~""') { | |
124 | $variableValue = ''; | |
125 | } | |
126 | } | |
127 | unset($variableValue); | |
90b4b964 AE |
128 | |
129 | if (!$this->style->isTainted) { | |
97ec0367 MW |
130 | $tmp = Style::splitLessVariables($this->variables['individualScss']); |
131 | $this->variables['individualScss'] = $tmp['preset']; | |
132 | $this->variables['individualScssCustom'] = $tmp['custom']; | |
90b4b964 | 133 | |
97ec0367 MW |
134 | $tmp = Style::splitLessVariables($this->variables['overrideScss']); |
135 | $this->variables['overrideScss'] = $tmp['preset']; | |
136 | $this->variables['overrideScssCustom'] = $tmp['custom']; | |
90b4b964 | 137 | } |
5c1f7926 | 138 | |
1ecaac09 | 139 | if ($this->variables['pageLogo'] && file_exists($this->style->getAssetPath().$this->variables['pageLogo'])) { |
5c1f7926 TD |
140 | $file = new UploadFile($this->style->getAssetPath().$this->variables['pageLogo'], basename($this->variables['pageLogo']), true, true, true); |
141 | UploadHandler::getInstance()->registerFilesByField('pageLogo', [ | |
142 | $file, | |
143 | ]); | |
144 | } | |
1ecaac09 | 145 | if ($this->variables['pageLogoMobile'] && file_exists($this->style->getAssetPath().$this->variables['pageLogoMobile'])) { |
5c1f7926 TD |
146 | $file = new UploadFile($this->style->getAssetPath().$this->variables['pageLogoMobile'], basename($this->variables['pageLogoMobile']), true, true, true); |
147 | UploadHandler::getInstance()->registerFilesByField('pageLogoMobile', [ | |
148 | $file, | |
149 | ]); | |
150 | } | |
90b4b964 AE |
151 | } |
152 | ||
153 | /** | |
0fcfe5f6 | 154 | * @inheritDoc |
90b4b964 AE |
155 | */ |
156 | protected function setVariables() { | |
157 | parent::setVariables(); | |
158 | ||
159 | if (!$this->style->isTainted) { | |
97ec0367 MW |
160 | $this->specialVariables[] = 'individualScssCustom'; |
161 | $this->specialVariables[] = 'overrideScssCustom'; | |
90b4b964 | 162 | } |
6c80f0df AE |
163 | } |
164 | ||
165 | /** | |
0fcfe5f6 | 166 | * @inheritDoc |
6c80f0df AE |
167 | */ |
168 | public function readData() { | |
169 | parent::readData(); | |
170 | ||
aa5fecb3 AE |
171 | I18nHandler::getInstance()->setOptions('styleDescription', PACKAGE_ID, $this->style->styleDescription, 'wcf.style.styleDescription\d+'); |
172 | ||
6c80f0df | 173 | if (empty($_POST)) { |
811f5a93 | 174 | $this->apiVersion = $this->style->apiVersion; |
6c80f0df AE |
175 | $this->authorName = $this->style->authorName; |
176 | $this->authorURL = $this->style->authorURL; | |
177 | $this->copyright = $this->style->copyright; | |
90b4b964 | 178 | $this->isTainted = $this->style->isTainted; |
6c80f0df | 179 | $this->license = $this->style->license; |
90b4b964 | 180 | $this->packageName = $this->style->packageName; |
6c80f0df AE |
181 | $this->styleDate = $this->style->styleDate; |
182 | $this->styleDescription = $this->style->styleDescription; | |
183 | $this->styleName = $this->style->styleName; | |
184 | $this->styleVersion = $this->style->styleVersion; | |
185 | $this->templateGroupID = $this->style->templateGroupID; | |
1ecaac09 | 186 | if ($this->style->image && file_exists(WCF_DIR.'images/'.$this->style->image)) { |
0825059e | 187 | $file = new UploadFile(WCF_DIR.'images/'.$this->style->image, $this->style->image, true, true, false); |
1b6a0dfc TD |
188 | UploadHandler::getInstance()->registerFilesByField('image', [ |
189 | $file, | |
190 | ]); | |
191 | } | |
1ecaac09 | 192 | if ($this->style->image2x && file_exists(WCF_DIR.'images/'.$this->style->image2x)) { |
0825059e | 193 | $file = new UploadFile(WCF_DIR.'images/'.$this->style->image2x, $this->style->image2x, true, true, false); |
1b6a0dfc TD |
194 | UploadHandler::getInstance()->registerFilesByField('image2x', [ |
195 | $file, | |
196 | ]); | |
197 | } | |
1ecaac09 | 198 | if ($this->style->coverPhotoExtension && file_exists($this->style->getCoverPhotoLocation())) { |
0825059e TD |
199 | $file = new UploadFile($this->style->getCoverPhotoLocation(), $this->style->getCoverPhoto(), true, true, false); |
200 | UploadHandler::getInstance()->registerFilesByField('coverPhoto', [ | |
201 | $file, | |
202 | ]); | |
203 | } | |
95d803b7 TD |
204 | if ($this->style->hasFavicon) { |
205 | foreach (['png', 'jpg', 'gif'] as $extension) { | |
17271890 | 206 | $filename = "favicon-template.".$extension; |
a6e7a5ef TD |
207 | if (file_exists($this->style->getAssetPath().$filename)) { |
208 | $file = new UploadFile($this->style->getAssetPath().$filename, $filename, true, true, false); | |
95d803b7 TD |
209 | UploadHandler::getInstance()->registerFilesByField('favicon', [ |
210 | $file, | |
211 | ]); | |
212 | break; | |
213 | } | |
214 | } | |
95d803b7 | 215 | } |
908e40a3 TD |
216 | |
217 | UploadHandler::getInstance()->registerFilesByField('customAssets', array_map(function ($filename) { | |
218 | return new UploadFile($filename, basename($filename), false, true, true); | |
219 | }, glob($this->style->getAssetPath().'custom/*'))); | |
6c80f0df AE |
220 | } |
221 | } | |
222 | ||
223 | /** | |
0fcfe5f6 | 224 | * @inheritDoc |
6c80f0df AE |
225 | */ |
226 | public function save() { | |
e79f851c | 227 | AbstractForm::save(); |
6c80f0df | 228 | |
939a7c76 | 229 | if (!$this->style->isTainted) { |
97ec0367 MW |
230 | $this->variables['individualScss'] = Style::joinLessVariables($this->variables['individualScss'], $this->variables['individualScssCustom']); |
231 | $this->variables['overrideScss'] = Style::joinLessVariables($this->variables['overrideScss'], $this->variables['overrideScssCustom']); | |
90b4b964 | 232 | |
97ec0367 MW |
233 | unset($this->variables['individualScssCustom']); |
234 | unset($this->variables['overrideScssCustom']); | |
939a7c76 | 235 | } |
90b4b964 | 236 | |
c4593f20 AE |
237 | // Remove control characters that break the SCSS parser, see https://stackoverflow.com/a/23066553 |
238 | $this->variables['individualScss'] = preg_replace('/[^\PC\s]/u', '', $this->variables['individualScss']); | |
239 | ||
058cbd6a MS |
240 | $this->objectAction = new StyleAction([$this->style], 'update', [ |
241 | 'data' => array_merge($this->additionalFields, [ | |
6c80f0df AE |
242 | 'styleName' => $this->styleName, |
243 | 'templateGroupID' => $this->templateGroupID, | |
6c80f0df AE |
244 | 'styleVersion' => $this->styleVersion, |
245 | 'styleDate' => $this->styleDate, | |
6c80f0df | 246 | 'copyright' => $this->copyright, |
90b4b964 | 247 | 'packageName' => $this->packageName, |
6c80f0df AE |
248 | 'license' => $this->license, |
249 | 'authorName' => $this->authorName, | |
811f5a93 AE |
250 | 'authorURL' => $this->authorURL, |
251 | 'apiVersion' => $this->apiVersion | |
058cbd6a | 252 | ]), |
1b6a0dfc | 253 | 'uploads' => $this->uploads, |
cc17f302 | 254 | 'removedUploads' => $this->removedUploads, |
908e40a3 | 255 | 'customAssets' => $this->customAssets, |
6c80f0df | 256 | 'tmpHash' => $this->tmpHash, |
908e40a3 | 257 | 'variables' => $this->variables, |
058cbd6a | 258 | ]); |
6c80f0df AE |
259 | $this->objectAction->executeAction(); |
260 | ||
5c7386a0 | 261 | // save compiled style |
262 | if ($this->styleTestFileDir && file_exists($this->styleTestFileDir . '/style.css') && file_exists($this->styleTestFileDir . '/style-rtl.css')) { | |
263 | $styleFilename = StyleCompiler::getFilenameForStyle($this->style); | |
264 | rename($this->styleTestFileDir . '/style.css', $styleFilename . '.css'); | |
265 | rename($this->styleTestFileDir . '/style-rtl.css', $styleFilename . '-rtl.css'); | |
266 | ||
267 | rmdir($this->styleTestFileDir); | |
268 | } | |
269 | ||
aa5fecb3 AE |
270 | // save description |
271 | I18nHandler::getInstance()->save('styleDescription', $this->style->styleDescription, 'wcf.style'); | |
272 | ||
6c80f0df AE |
273 | // call saved event |
274 | $this->saved(); | |
275 | ||
276 | // reload style object to update preview image | |
277 | $this->style = new Style($this->style->styleID); | |
278 | ||
939a7c76 AE |
279 | if (!$this->style->isTainted) { |
280 | $tmp = Style::splitLessVariables($this->variables['individualScss']); | |
281 | $this->variables['individualScss'] = $tmp['preset']; | |
282 | $this->variables['individualScssCustom'] = $tmp['custom']; | |
283 | ||
284 | $tmp = Style::splitLessVariables($this->variables['overrideScss']); | |
285 | $this->variables['overrideScss'] = $tmp['preset']; | |
286 | $this->variables['overrideScssCustom'] = $tmp['custom']; | |
287 | } | |
288 | ||
6c80f0df AE |
289 | WCF::getTPL()->assign('success', true); |
290 | } | |
291 | ||
292 | /** | |
0fcfe5f6 | 293 | * @inheritDoc |
6c80f0df AE |
294 | */ |
295 | public function assignVariables() { | |
296 | parent::assignVariables(); | |
297 | ||
aa5fecb3 AE |
298 | I18nHandler::getInstance()->assignVariables(!empty($_POST)); |
299 | ||
058cbd6a | 300 | WCF::getTPL()->assign([ |
6c80f0df | 301 | 'action' => 'edit', |
939a7c76 | 302 | 'isTainted' => $this->style->isTainted, |
6c80f0df | 303 | 'style' => $this->style, |
87fc5501 | 304 | 'styleID' => $this->styleID, |
058cbd6a | 305 | ]); |
6c80f0df AE |
306 | } |
307 | } |