Commit | Line | Data |
---|---|---|
704e0423 | 1 | <?php |
a9229942 | 2 | |
704e0423 | 3 | namespace wcf\data\trophy; |
a9229942 | 4 | |
704e0423 | 5 | use wcf\data\AbstractDatabaseObjectAction; |
2126bf5e | 6 | use wcf\data\ISortableAction; |
704e0423 | 7 | use wcf\data\IToggleAction; |
8fbcc7c6 | 8 | use wcf\data\IUploadAction; |
a9229942 TD |
9 | use wcf\data\TDatabaseObjectToggle; |
10 | use wcf\data\user\trophy\UserTrophyAction; | |
11 | use wcf\data\user\trophy\UserTrophyList; | |
12 | use wcf\data\user\UserAction; | |
9e1fe407 | 13 | use wcf\system\database\util\PreparedStatementConditionBuilder; |
8fbcc7c6 | 14 | use wcf\system\exception\IllegalLinkException; |
704e0423 | 15 | use wcf\system\exception\UserInputException; |
8fbcc7c6 JR |
16 | use wcf\system\image\ImageHandler; |
17 | use wcf\system\upload\TrophyImageUploadFileValidationStrategy; | |
18 | use wcf\system\upload\UploadFile; | |
a83d788a | 19 | use wcf\system\user\storage\UserStorageHandler; |
704e0423 JR |
20 | use 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 |
34 | class 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 | } |