Split additional joins into multiple lines
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / data / trophy / TrophyAction.class.php
CommitLineData
704e0423 1<?php
a9229942 2
704e0423 3namespace wcf\data\trophy;
a9229942 4
704e0423 5use wcf\data\AbstractDatabaseObjectAction;
2126bf5e 6use wcf\data\ISortableAction;
704e0423 7use wcf\data\IToggleAction;
8fbcc7c6 8use wcf\data\IUploadAction;
a9229942
TD
9use wcf\data\TDatabaseObjectToggle;
10use wcf\data\user\trophy\UserTrophyAction;
11use wcf\data\user\trophy\UserTrophyList;
12use wcf\data\user\UserAction;
9e1fe407 13use wcf\system\database\util\PreparedStatementConditionBuilder;
8fbcc7c6 14use wcf\system\exception\IllegalLinkException;
704e0423 15use wcf\system\exception\UserInputException;
8fbcc7c6
JR
16use wcf\system\image\ImageHandler;
17use wcf\system\upload\TrophyImageUploadFileValidationStrategy;
18use wcf\system\upload\UploadFile;
a83d788a 19use wcf\system\user\storage\UserStorageHandler;
704e0423
JR
20use wcf\system\WCF;
21
22/**
a9229942 23 * Trophy related actions.
704e0423 24 *
a9229942
TD
25 * @author Joshua Ruesweg
26 * @copyright 2001-2019 WoltLab GmbH
27 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
28 * @package WoltLabSuite\Core\Data\Trophy
29 * @since 3.1
a83d788a 30 *
a9229942
TD
31 * @method TrophyEditor[] getObjects()
32 * @method TrophyEditor getSingleObject()
704e0423 33 */
a9229942
TD
34class TrophyAction extends AbstractDatabaseObjectAction implements IToggleAction, IUploadAction, ISortableAction
35{
36 use TDatabaseObjectToggle;
37
38 /**
39 * @inheritDoc
40 */
41 protected $permissionsDelete = ['admin.trophy.canManageTrophy'];
42
43 /**
44 * @inheritDoc
45 */
46 protected $permissionsUpdate = ['admin.trophy.canManageTrophy'];
47
48 /**
49 * @inheritDoc
50 */
51 protected $requireACP = ['toggle', 'delete'];
52
53 /**
54 * @inheritDoc
55 * @return Trophy
56 */
57 public function create()
58 {
59 $showOrder = 0;
60 if (isset($this->parameters['data']['showOrder'])) {
61 $showOrder = $this->parameters['data']['showOrder'];
62 unset($this->parameters['data']['showOrder']);
63 }
64
65 /** @var Trophy $trophy */
66 $trophy = parent::create();
67
68 if (isset($this->parameters['tmpHash']) && $this->parameters['data']['type'] === Trophy::TYPE_IMAGE) {
69 $this->updateTrophyImage($trophy);
70 }
71
72 $trophyEditor = new TrophyEditor($trophy);
73 $trophyEditor->setShowOrder($showOrder);
74
75 return new Trophy($trophy->trophyID);
76 }
77
78 /**
79 * @inheritDoc
80 */
81 public function delete()
82 {
83 // update trophy points
84 $userTrophyList = new UserTrophyList();
85 if (!empty($userTrophyList->sqlJoins)) {
86 $userTrophyList->sqlJoins .= ' ';
87 }
d3bd0a85
MS
88 $userTrophyList->sqlJoins .= '
89 LEFT JOIN wcf' . WCF_N . '_trophy trophy
90 ON user_trophy.trophyID = trophy.trophyID
91 LEFT JOIN wcf' . WCF_N . '_category category
92 ON trophy.categoryID = category.categoryID';
a9229942
TD
93
94 $userTrophyList->getConditionBuilder()->add('trophy.isDisabled = ?', [0]);
95 $userTrophyList->getConditionBuilder()->add('category.isDisabled = ?', [0]);
96 $userTrophyList->getConditionBuilder()->add('user_trophy.trophyID IN (?)', [$this->getObjectIDs()]);
97 $userTrophyList->readObjects();
98
99 $userTrophyAction = new UserTrophyAction($userTrophyList->getObjects(), 'delete');
100 $userTrophyAction->executeAction();
101
102 $returnValues = parent::delete();
103
104 UserStorageHandler::getInstance()->resetAll('specialTrophies');
105
106 return $returnValues;
107 }
108
109 /**
110 * @inheritDoc
111 */
112 public function update()
113 {
114 parent::update();
115
116 if (isset($this->parameters['data']['type']) && $this->parameters['data']['type'] === Trophy::TYPE_IMAGE) {
117 foreach ($this->getObjects() as $trophy) {
118 if (isset($this->parameters['tmpHash'])) {
119 $this->updateTrophyImage($trophy);
120 }
121 }
122 }
123
124 if (\count($this->objects) == 1 && isset($this->parameters['data']['showOrder']) && $this->parameters['data']['showOrder'] != \reset($this->objects)->showOrder) {
125 \reset($this->objects)->setShowOrder($this->parameters['data']['showOrder']);
126 }
127 }
128
129 /**
130 * @inheritDoc
131 */
132 public function toggle()
133 {
134 $enabledTrophyIDs = [];
135 $disabledTrophyIDs = [];
136
137 foreach ($this->getObjects() as $trophy) {
138 $trophy->update(['isDisabled' => $trophy->isDisabled ? 0 : 1]);
139
140 if (!$trophy->isDisabled) {
141 $disabledTrophyIDs[] = $trophy->trophyID;
142 } else {
143 $enabledTrophyIDs[] = $trophy->trophyID;
144 }
145 }
146
147 if (!empty($disabledTrophyIDs)) {
148 $conditionBuilder = new PreparedStatementConditionBuilder();
149 $conditionBuilder->add('trophyID IN (?)', [$disabledTrophyIDs]);
150 $sql = "DELETE FROM wcf" . WCF_N . "_user_special_trophy
151 " . $conditionBuilder;
152 $statement = WCF::getDB()->prepareStatement($sql);
153 $statement->execute($conditionBuilder->getParameters());
154
155 // update trophy points
156 $conditionBuilder = new PreparedStatementConditionBuilder();
157 $conditionBuilder->add('trophyID IN (?)', [$disabledTrophyIDs]);
158 $sql = "SELECT COUNT(*) as count, userID
159 FROM wcf" . WCF_N . "_user_trophy
160 " . $conditionBuilder . "
161 GROUP BY userID";
162 $statement = WCF::getDB()->prepareStatement($sql);
163 $statement->execute($conditionBuilder->getParameters());
164
165 while ($row = $statement->fetchArray()) {
166 $userAction = new UserAction([$row['userID']], 'update', [
167 'counters' => [
168 'trophyPoints' => $row['count'] * -1,
169 ],
170 ]);
171 $userAction->executeAction();
172 }
173 }
174
175 if (!empty($enabledTrophyIDs)) {
176 // update trophy points
177 $conditionBuilder = new PreparedStatementConditionBuilder();
178 $conditionBuilder->add('trophyID IN (?)', [$enabledTrophyIDs]);
179 $sql = "SELECT COUNT(*) as count, userID
180 FROM wcf" . WCF_N . "_user_trophy
181 " . $conditionBuilder . "
182 GROUP BY userID";
183 $statement = WCF::getDB()->prepareStatement($sql);
184 $statement->execute($conditionBuilder->getParameters());
185
186 while ($row = $statement->fetchArray()) {
187 $userAction = new UserAction([$row['userID']], 'update', [
188 'counters' => [
189 'trophyPoints' => $row['count'],
190 ],
191 ]);
192 $userAction->executeAction();
193 }
194 }
195
196 UserStorageHandler::getInstance()->resetAll('specialTrophies');
197 }
198
199 /**
200 * @inheritDoc
201 */
202 public function validateUpload()
203 {
204 WCF::getSession()->checkPermissions(['admin.trophy.canManageTrophy']);
205
206 $this->readString('tmpHash');
207 $this->readInteger('trophyID', true);
208
209 if ($this->parameters['trophyID']) {
210 $this->parameters['trophy'] = new Trophy($this->parameters['trophyID']);
211
212 if (!$this->parameters['trophy']->trophyID) {
213 throw new IllegalLinkException();
214 }
215 }
216
217 $this->parameters['__files']->validateFiles(new TrophyImageUploadFileValidationStrategy());
218
219 /** @var UploadFile[] $files */
220 $files = $this->parameters['__files']->getFiles();
221
222 // only one file is allowed
223 if (\count($files) !== 1) {
224 throw new UserInputException('file');
225 }
226
227 $this->parameters['file'] = \reset($files);
228
229 if ($this->parameters['file']->getValidationErrorType()) {
230 throw new UserInputException('file', $this->parameters['file']->getValidationErrorType());
231 }
232 }
233
234 /**
235 * @inheritDoc
236 */
237 public function upload()
238 {
239 $fileName = WCF_DIR . 'images/trophy/tmp_' . $this->parameters['tmpHash'] . '.' . $this->parameters['file']->getFileExtension();
240 if ($this->parameters['file']->getImageData()['height'] > 128) {
241 $adapter = ImageHandler::getInstance()->getAdapter();
242 $adapter->loadFile($this->parameters['file']->getLocation());
243 $adapter->resize(
244 0,
245 0,
246 $this->parameters['file']->getImageData()['height'],
247 $this->parameters['file']->getImageData()['height'],
248 128,
249 128
250 );
251 $adapter->writeImage($adapter->getImage(), $fileName);
252 } else {
253 \copy($this->parameters['file']->getLocation(), $fileName);
254 }
255
256 // remove old image
257 @\unlink($this->parameters['file']->getLocation());
258
259 // store extension within session variables
260 WCF::getSession()->register(
261 'trophyImage-' . $this->parameters['tmpHash'],
262 $this->parameters['file']->getFileExtension()
263 );
264
265 if ($this->parameters['trophyID']) {
266 $this->updateTrophyImage($this->parameters['trophy']);
267
268 return [
269 'url' => WCF::getPath() . 'images/trophy/trophyImage-' . $this->parameters['trophyID'] . '.' . $this->parameters['file']->getFileExtension(),
270 ];
271 }
272
273 return [
274 'url' => WCF::getPath() . 'images/trophy/' . \basename($fileName),
275 ];
276 }
277
278 /**
279 * Updates style preview image.
280 *
281 * @param Trophy $trophy
282 */
283 protected function updateTrophyImage(Trophy $trophy)
284 {
285 if (!isset($this->parameters['tmpHash'])) {
286 return;
287 }
288
289 $fileExtension = WCF::getSession()->getVar('trophyImage-' . $this->parameters['tmpHash']);
290 if ($fileExtension !== null) {
291 $oldFilename = WCF_DIR . 'images/trophy/tmp_' . $this->parameters['tmpHash'] . '.' . $fileExtension;
292 if (\file_exists($oldFilename)) {
293 $filename = 'trophyImage-' . $trophy->trophyID . '.' . $fileExtension;
294 if (@\rename($oldFilename, WCF_DIR . 'images/trophy/' . $filename)) {
295 // delete old file if it has a different file extension
296 if ($trophy->iconFile != $filename) {
297 @\unlink(WCF_DIR . 'images/trophy/' . $trophy->iconFile);
298
299 $trophyEditor = new TrophyEditor($trophy);
300 $trophyEditor->update([
301 'iconFile' => $filename,
302 ]);
303 }
304 } else {
305 // remove temp file
306 @\unlink($oldFilename);
307 }
308 }
309 }
310 }
311
312 /**
313 * @inheritDoc
314 */
315 public function validateUpdatePosition()
316 {
317 WCF::getSession()->checkPermissions($this->permissionsUpdate);
318
319 if (!isset($this->parameters['data']['structure']) || !\is_array($this->parameters['data']['structure'])) {
320 throw new UserInputException('structure');
321 }
322
323 $trophyList = new TrophyList();
324 $trophyList->setObjectIDs($this->parameters['data']['structure'][0]);
325 $trophyList->readObjects();
326 if (\count($trophyList) !== \count($this->parameters['data']['structure'][0])) {
327 throw new UserInputException('structure');
328 }
329
330 $this->readInteger('offset', true, 'data');
331 }
332
333 /**
334 * @inheritDoc
335 */
336 public function updatePosition()
337 {
338 $sql = "UPDATE wcf" . WCF_N . "_trophy
339 SET showOrder = ?
340 WHERE trophyID = ?";
341 $statement = WCF::getDB()->prepareStatement($sql);
342
343 $showOrder = $this->parameters['data']['offset'];
344 WCF::getDB()->beginTransaction();
345 foreach ($this->parameters['data']['structure'][0] as $trophyID) {
346 $statement->execute([
347 $showOrder++,
348 $trophyID,
349 ]);
350 }
351 WCF::getDB()->commitTransaction();
352 }
704e0423 353}