Merge pull request #5951 from WoltLab/upload-form-field-v2
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / acp / form / SmileyAddForm.class.php
1 <?php
2
3 namespace wcf\acp\form;
4
5 use wcf\data\category\Category;
6 use wcf\data\category\CategoryNodeTree;
7 use wcf\data\smiley\SmileyAction;
8 use wcf\data\smiley\SmileyEditor;
9 use wcf\form\AbstractForm;
10 use wcf\system\database\util\PreparedStatementConditionBuilder;
11 use wcf\system\exception\UserInputException;
12 use wcf\system\language\I18nHandler;
13 use wcf\system\request\LinkHandler;
14 use wcf\system\WCF;
15 use wcf\util\FileUtil;
16 use wcf\util\ImageUtil;
17 use wcf\util\StringUtil;
18
19 /**
20 * Shows the smiley add form.
21 *
22 * @author Tim Duesterhus
23 * @copyright 2001-2019 WoltLab GmbH
24 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
25 */
26 class SmileyAddForm extends AbstractForm
27 {
28 /**
29 * @inheritDoc
30 */
31 public $activeMenuItem = 'wcf.acp.menu.link.smiley.add';
32
33 /**
34 * @inheritDoc
35 */
36 public $templateName = 'smileyAdd';
37
38 /**
39 * @inheritDoc
40 */
41 public $neededPermissions = ['admin.content.smiley.canManageSmiley'];
42
43 /**
44 * @inheritDoc
45 */
46 public $neededModules = ['MODULE_SMILEY'];
47
48 /**
49 * primary smiley code
50 * @var string
51 */
52 public $smileyCode = '';
53
54 /**
55 * show order value
56 * @var int
57 */
58 public $showOrder = 0;
59
60 /**
61 * categoryID value
62 * @var int
63 */
64 public $categoryID = 0;
65
66 /**
67 * smileyTitle
68 * @var string
69 */
70 public $smileyTitle = '';
71
72 /**
73 * aliases value
74 * @var string
75 */
76 public $aliases = '';
77
78 /**
79 * path to the smiley file
80 * @var string
81 */
82 public $smileyPath = '';
83
84 /**
85 * path to the smiley file (2x)
86 * @var string
87 */
88 public $smileyPath2x = '';
89
90 /**
91 * node tree with available smiley categories
92 * @var CategoryNodeTree
93 */
94 public $categoryNodeTree;
95
96 /**
97 * data of the uploaded smiley file
98 * @var array
99 */
100 public $fileUpload = [];
101
102 /**
103 * data of the uploaded smiley file (2x)
104 * @var array
105 */
106 public $fileUpload2x = [];
107
108 /**
109 * temporary name of the uploaded smiley file
110 * @var string
111 */
112 public $uploadedFilename = '';
113
114 /**
115 * temporary name of the uploaded smiley file (2x)
116 * @var string
117 */
118 public $uploadedFilename2x = '';
119
120 /**
121 * @inheritDoc
122 */
123 public function assignVariables()
124 {
125 parent::assignVariables();
126
127 I18nHandler::getInstance()->assignVariables();
128
129 WCF::getTPL()->assign([
130 'action' => 'add',
131 'smileyTitle' => $this->smileyTitle,
132 'showOrder' => $this->showOrder,
133 'categoryID' => $this->categoryID,
134 'smileyCode' => $this->smileyCode,
135 'aliases' => $this->aliases,
136 'smileyPath' => $this->smileyPath,
137 'smileyPath2x' => $this->smileyPath2x,
138 'categoryNodeList' => $this->categoryNodeTree->getIterator(),
139 'uploadedFilename' => $this->uploadedFilename,
140 'uploadedFilename2x' => $this->uploadedFilename2x,
141 ]);
142 }
143
144 /**
145 * @inheritDoc
146 */
147 public function readData()
148 {
149 parent::readData();
150
151 $this->categoryNodeTree = new CategoryNodeTree('com.woltlab.wcf.bbcode.smiley', 0, true);
152 }
153
154 /**
155 * @inheritDoc
156 */
157 public function readParameters()
158 {
159 parent::readParameters();
160
161 I18nHandler::getInstance()->register('smileyTitle');
162 }
163
164 /**
165 * @inheritDoc
166 */
167 public function readFormParameters()
168 {
169 parent::readFormParameters();
170
171 I18nHandler::getInstance()->readValues();
172
173 if (I18nHandler::getInstance()->isPlainValue('smileyTitle')) {
174 $this->smileyTitle = I18nHandler::getInstance()->getValue('smileyTitle');
175 }
176
177 if (isset($_POST['showOrder'])) {
178 $this->showOrder = \intval($_POST['showOrder']);
179 }
180 if (isset($_POST['categoryID'])) {
181 $this->categoryID = \intval($_POST['categoryID']);
182 }
183 if (isset($_POST['smileyCode'])) {
184 $this->smileyCode = StringUtil::trim($_POST['smileyCode']);
185 }
186 if (isset($_POST['aliases'])) {
187 $this->aliases = StringUtil::unifyNewlines(StringUtil::trim($_POST['aliases']));
188 }
189 if (isset($_POST['smileyPath'])) {
190 $this->smileyPath = FileUtil::removeLeadingSlash(StringUtil::trim($_POST['smileyPath']));
191 }
192 if (isset($_POST['uploadedFilename'])) {
193 $this->uploadedFilename = StringUtil::trim($_POST['uploadedFilename']);
194 }
195 if (isset($_FILES['fileUpload'])) {
196 $this->fileUpload = $_FILES['fileUpload'];
197 }
198 if (isset($_POST['smileyPath2x'])) {
199 $this->smileyPath2x = FileUtil::removeLeadingSlash(StringUtil::trim($_POST['smileyPath2x']));
200 }
201 if (isset($_POST['uploadedFilename2x'])) {
202 $this->uploadedFilename2x = StringUtil::trim($_POST['uploadedFilename2x']);
203 }
204 if (isset($_FILES['fileUpload2x'])) {
205 $this->fileUpload2x = $_FILES['fileUpload2x'];
206 }
207 }
208
209 /**
210 * @inheritDoc
211 */
212 public function save()
213 {
214 parent::save();
215
216 $this->objectAction = new SmileyAction([], 'create', [
217 'data' => \array_merge($this->additionalFields, [
218 'smileyTitle' => $this->smileyTitle,
219 'smileyCode' => $this->smileyCode,
220 'aliases' => $this->aliases,
221 'smileyPath' => $this->smileyPath,
222 'smileyPath2x' => $this->smileyPath2x,
223 'showOrder' => $this->showOrder,
224 'categoryID' => $this->categoryID ?: null,
225 'packageID' => 1,
226 ]),
227 'fileLocation' => $this->uploadedFilename ? WCF_DIR . 'images/smilies/' . $this->uploadedFilename : '',
228 'fileLocation2x' => $this->uploadedFilename2x ? WCF_DIR . 'images/smilies/' . $this->uploadedFilename2x : '',
229 ]);
230 $this->objectAction->executeAction();
231 $returnValues = $this->objectAction->getReturnValues();
232 $smileyEditor = new SmileyEditor($returnValues['returnValues']);
233 $smileyID = $returnValues['returnValues']->smileyID;
234
235 if (!I18nHandler::getInstance()->isPlainValue('smileyTitle')) {
236 I18nHandler::getInstance()->save('smileyTitle', 'wcf.smiley.title' . $smileyID, 'wcf.smiley', 1);
237
238 // update title
239 $smileyEditor->update([
240 'smileyTitle' => 'wcf.smiley.title' . $smileyID,
241 ]);
242 }
243
244 // reset values
245 $this->smileyCode = '';
246 $this->categoryID = 0;
247 $this->showOrder = 0;
248 $this->smileyPath = $this->smileyPath2x = '';
249 $this->aliases = '';
250 $this->uploadedFilename = $this->uploadedFilename2x = '';
251
252 I18nHandler::getInstance()->reset();
253
254 $this->saved();
255
256 // show success message
257 WCF::getTPL()->assign([
258 'success' => true,
259 'objectEditLink' => LinkHandler::getInstance()->getControllerLink(
260 SmileyEditForm::class,
261 ['id' => $smileyID]
262 ),
263 ]);
264 }
265
266 /**
267 * @inheritDoc
268 */
269 public function validate()
270 {
271 parent::validate();
272
273 if ($this->uploadedFilename) {
274 if (!\file_exists(WCF_DIR . 'images/smilies/' . $this->uploadedFilename)) {
275 $this->uploadedFilename = '';
276 throw new UserInputException('fileUpload', 'uploadFailed');
277 }
278 } elseif (!empty($this->fileUpload['name'])) {
279 if (!ImageUtil::isImage($this->fileUpload['tmp_name'], $this->fileUpload['name'])) {
280 $this->uploadedFilename = '';
281 throw new UserInputException('fileUpload', 'noImage');
282 }
283
284 do {
285 $this->uploadedFilename = StringUtil::getRandomID() . '.' . \mb_strtolower(\mb_substr(
286 $this->fileUpload['name'],
287 \mb_strrpos($this->fileUpload['name'], '.') + 1
288 ));
289 } while (\file_exists(WCF_DIR . 'images/smilies/' . $this->uploadedFilename));
290
291 if (
292 !@\move_uploaded_file(
293 $this->fileUpload['tmp_name'],
294 WCF_DIR . 'images/smilies/' . $this->uploadedFilename
295 )
296 ) {
297 $this->uploadedFilename = '';
298 throw new UserInputException('fileUpload', 'uploadFailed');
299 }
300 } else {
301 if (empty($this->smileyPath)) {
302 throw new UserInputException('smileyPath');
303 }
304
305 if (!\is_file(WCF_DIR . $this->smileyPath)) {
306 throw new UserInputException('smileyPath', 'notFound');
307 }
308 }
309
310 if ($this->uploadedFilename2x) {
311 if (!\file_exists(WCF_DIR . 'images/smilies/' . $this->uploadedFilename2x)) {
312 $this->uploadedFilename2x = '';
313 throw new UserInputException('fileUpload2x', 'uploadFailed');
314 }
315 } elseif (!empty($this->fileUpload2x['name'])) {
316 if (!ImageUtil::isImage($this->fileUpload2x['tmp_name'], $this->fileUpload2x['name'])) {
317 $this->uploadedFilename2x = '';
318 throw new UserInputException('fileUpload2x', 'noImage');
319 }
320
321 do {
322 $this->uploadedFilename2x = StringUtil::getRandomID() . '.' . \mb_strtolower(\mb_substr(
323 $this->fileUpload2x['name'],
324 \mb_strrpos($this->fileUpload2x['name'], '.') + 1
325 ));
326 } while (\file_exists(WCF_DIR . 'images/smilies/' . $this->uploadedFilename2x));
327
328 if (
329 !@\move_uploaded_file(
330 $this->fileUpload2x['tmp_name'],
331 WCF_DIR . 'images/smilies/' . $this->uploadedFilename2x
332 )
333 ) {
334 $this->uploadedFilename2x = '';
335 throw new UserInputException('fileUpload2x', 'uploadFailed');
336 }
337 } elseif ($this->smileyPath2x && !\is_file(WCF_DIR . $this->smileyPath2x)) {
338 throw new UserInputException('smileyPath2x', 'notFound');
339 }
340
341 // validate title
342 if (!I18nHandler::getInstance()->validateValue('smileyTitle')) {
343 if (I18nHandler::getInstance()->isPlainValue('smileyTitle')) {
344 throw new UserInputException('smileyTitle');
345 } else {
346 throw new UserInputException('smileyTitle', 'multilingual');
347 }
348 }
349
350 if ($this->categoryID) {
351 $category = new Category($this->categoryID);
352 if (!$category->categoryID) {
353 throw new UserInputException('categoryID', 'invalid');
354 }
355 }
356
357 if (empty($this->smileyCode)) {
358 throw new UserInputException('smileyCode');
359 }
360
361 // validate smiley code and aliases against existing smilies
362 $conditionBuilder = new PreparedStatementConditionBuilder();
363 if (isset($this->smiley)) {
364 $conditionBuilder->add('smileyID <> ?', [$this->smiley->smileyID]);
365 }
366 $sql = "SELECT smileyCode, aliases
367 FROM wcf" . WCF_N . "_smiley
368 " . $conditionBuilder;
369 $statement = WCF::getDB()->prepareStatement($sql);
370 $statement->execute($conditionBuilder->getParameters());
371
372 $aliases = \explode("\n", $this->aliases);
373 $aliases = \array_map('\mb_strtolower', $aliases);
374 while ($row = $statement->fetchArray()) {
375 $known = [];
376 if (!empty($row['aliases'])) {
377 $known = \explode("\n", $row['aliases']);
378 }
379 $known[] = $row['smileyCode'];
380 $known = \array_map('\mb_strtolower', $known);
381
382 if (\in_array(\mb_strtolower($this->smileyCode), $known)) {
383 throw new UserInputException('smileyCode', 'notUnique');
384 } else {
385 $conflicts = \array_intersect($aliases, $known);
386 if (!empty($conflicts)) {
387 throw new UserInputException('aliases', 'notUnique');
388 }
389 }
390 }
391 }
392 }