Fix typo in avatar condition in UserRebuildDataWorker
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / system / worker / UserRebuildDataWorker.class.php
CommitLineData
e3667539 1<?php
a9229942 2
e3667539 3namespace wcf\system\worker;
a9229942 4
557115b5 5use wcf\data\reaction\type\ReactionTypeCache;
2772d4eb
MW
6use wcf\data\user\avatar\UserAvatar;
7use wcf\data\user\avatar\UserAvatarEditor;
8use wcf\data\user\avatar\UserAvatarList;
8a413435 9use wcf\data\user\User;
e3667539 10use wcf\data\user\UserEditor;
157054c9 11use wcf\data\user\UserList;
e3667539 12use wcf\data\user\UserProfileAction;
7e058783 13use wcf\system\bbcode\BBCodeHandler;
e3667539 14use wcf\system\database\util\PreparedStatementConditionBuilder;
c5c9e424 15use wcf\system\exception\SystemException;
b8c48208 16use wcf\system\html\input\HtmlInputProcessor;
2772d4eb 17use wcf\system\image\ImageHandler;
e3667539
MW
18use wcf\system\WCF;
19
20/**
21 * Worker implementation for updating users.
a9229942
TD
22 *
23 * @author Marcel Werk
24 * @copyright 2001-2019 WoltLab GmbH
25 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
26 * @package WoltLabSuite\Core\System\Worker
27 *
28 * @method UserList getObjectList()
e3667539 29 */
a9229942
TD
30class UserRebuildDataWorker extends AbstractRebuildDataWorker
31{
32 /**
33 * @inheritDoc
34 */
35 protected $objectListClassName = UserList::class;
36
37 /**
38 * @inheritDoc
39 */
40 protected $limit = 50;
41
42 /**
43 * @inheritDoc
44 */
45 protected function initObjectList()
46 {
47 parent::initObjectList();
48
49 $this->objectList->sqlSelects = 'user_option_value.userOption' . User::getUserOptionID('aboutMe') . ' AS aboutMe';
d3bd0a85
MS
50 $this->objectList->sqlJoins = "
51 LEFT JOIN wcf" . WCF_N . "_user_option_value user_option_value
52 ON user_option_value.userID = user_table.userID";
a9229942
TD
53 $this->objectList->sqlOrderBy = 'user_table.userID';
54 }
55
56 /**
57 * @inheritDoc
58 */
59 public function execute()
60 {
61 parent::execute();
62
63 $users = $userIDs = [];
64 foreach ($this->getObjectList() as $user) {
65 $users[] = new UserEditor($user);
66 $userIDs[] = $user->userID;
67 }
68
69 // update user ranks
70 if (!empty($users)) {
71 $action = new UserProfileAction($users, 'updateUserOnlineMarking');
72 $action->executeAction();
73 }
74
75 if (!empty($userIDs)) {
76 // update article counter
77 $conditionBuilder = new PreparedStatementConditionBuilder();
78 $conditionBuilder->add('user_table.userID IN (?)', [$userIDs]);
79 $sql = "UPDATE wcf" . WCF_N . "_user user_table
80 SET articles = (
81 SELECT COUNT(*)
82 FROM wcf" . WCF_N . "_article
83 WHERE userID = user_table.userID
84 )
85 " . $conditionBuilder;
86 $statement = WCF::getDB()->prepareStatement($sql);
87 $statement->execute($conditionBuilder->getParameters());
88
89 // update like counter
90 if (MODULE_LIKE) {
91 $sql = "UPDATE wcf" . WCF_N . "_user user_table
92 SET";
93
94 $reactionTypeIDs = \array_keys(ReactionTypeCache::getInstance()->getReactionTypes());
95 if (!empty($reactionTypeIDs)) {
96 $sql .= "
97 likesReceived = (
98 SELECT COUNT(*)
99 FROM wcf" . WCF_N . "_like
100 WHERE objectUserID = user_table.userID
101 AND reactionTypeID IN (" . \implode(',', $reactionTypeIDs) . ")
102 )";
103 } else {
104 $sql .= " likesReceived = 0";
105 }
106
107 $sql .= " " . $conditionBuilder;
108 $statement = WCF::getDB()->prepareStatement($sql);
109 $statement->execute($conditionBuilder->getParameters());
110 }
111
112 // update trophy points
113 if (MODULE_TROPHY) {
114 $sql = "UPDATE wcf" . WCF_N . "_user user_table
115 SET trophyPoints = (
116 SELECT COUNT(*)
117 FROM wcf" . WCF_N . "_user_trophy user_trophy
118 LEFT JOIN wcf" . WCF_N . "_trophy trophy
c240c98a 119 ON user_trophy.trophyID = trophy.trophyID
a9229942 120 LEFT JOIN wcf" . WCF_N . "_category trophy_category
c240c98a 121 ON trophy.categoryID = trophy_category.categoryID
a9229942
TD
122 WHERE user_trophy.userID = user_table.userID
123 AND trophy.isDisabled = 0
124 AND trophy_category.isDisabled = 0
125 )
126 " . $conditionBuilder;
127 $statement = WCF::getDB()->prepareStatement($sql);
128 $statement->execute($conditionBuilder->getParameters());
129 }
130
131 // update signatures and about me
132 $sql = "UPDATE wcf" . WCF_N . "_user_option_value
133 SET userOption" . User::getUserOptionID('aboutMe') . " = ?
134 WHERE userID = ?";
135 $statement = WCF::getDB()->prepareStatement($sql);
136
137 // retrieve permissions
138 $userIDs = [];
139 foreach ($users as $user) {
140 $userIDs[] = $user->userID;
141 }
142 $userPermissions = $this->getBulkUserPermissions(
143 $userIDs,
144 ['user.message.disallowedBBCodes', 'user.signature.disallowedBBCodes']
145 );
146
147 $htmlInputProcessor = new HtmlInputProcessor();
148 WCF::getDB()->beginTransaction();
149 /** @var UserEditor $user */
150 foreach ($users as $user) {
151 BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode(
152 ',',
153 $this->getBulkUserPermissionValue(
154 $userPermissions,
155 $user->userID,
156 'user.signature.disallowedBBCodes'
157 )
158 ));
159
160 if (!$user->signatureEnableHtml) {
161 $htmlInputProcessor->process(
162 $user->signature,
163 'com.woltlab.wcf.user.signature',
164 $user->userID,
165 true
166 );
167
168 $user->update([
169 'signature' => $htmlInputProcessor->getHtml(),
170 'signatureEnableHtml' => 1,
171 ]);
172 } else {
173 $htmlInputProcessor->reprocess($user->signature, 'com.woltlab.wcf.user.signature', $user->userID);
174 $user->update(['signature' => $htmlInputProcessor->getHtml()]);
175 }
176
177 if ($user->aboutMe) {
178 BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode(
179 ',',
180 $this->getBulkUserPermissionValue(
181 $userPermissions,
182 $user->userID,
183 'user.message.disallowedBBCodes'
184 )
185 ));
186
187 if (!$user->signatureEnableHtml) {
188 $htmlInputProcessor->process(
189 $user->aboutMe,
190 'com.woltlab.wcf.user.aboutMe',
191 $user->userID,
192 true
193 );
194 } else {
195 $htmlInputProcessor->reprocess($user->aboutMe, 'com.woltlab.wcf.user.aboutMe', $user->userID);
196 }
197
198 $html = $htmlInputProcessor->getHtml();
199 // MySQL's TEXT type allows for 65,535 bytes, hence we need to count
200 // the bytes rather than the actual amount of characters
201 if (\strlen($html) > 65535) {
202 // content does not fit the available space, and any
203 // attempts to truncate it will yield awkward results
204 $html = '';
205 }
206
207 $statement->execute([$html, $user->userID]);
208 }
209 }
210 WCF::getDB()->commitTransaction();
211
212 // update old/imported avatars
213 $avatarList = new UserAvatarList();
214 $avatarList->getConditionBuilder()->add('user_avatar.userID IN (?)', [$userIDs]);
215 $avatarList->getConditionBuilder()->add(
71a3289c
AE
216 '(
217 (user_avatar.width <> ? OR user_avatar.height <> ?)
218 OR (user_avatar.hasWebP = ? AND user_avatar.avatarExtension <> ?)
219 )',
220 [
221 UserAvatar::AVATAR_SIZE,
222 UserAvatar::AVATAR_SIZE,
4084160a 223 0,
71a3289c
AE
224 "gif",
225 ]
a9229942
TD
226 );
227 $avatarList->readObjects();
228 foreach ($avatarList as $avatar) {
229 $editor = new UserAvatarEditor($avatar);
230 if (!\file_exists($avatar->getLocation()) || @\getimagesize($avatar->getLocation()) === false) {
231 // delete avatars that are missing or broken
232 $editor->delete();
233 continue;
234 }
235
236 $width = $avatar->width;
237 $height = $avatar->height;
238 if ($width != $height) {
239 // make avatar quadratic
240 $width = $height = \min($width, $height, UserAvatar::AVATAR_SIZE);
241 $adapter = ImageHandler::getInstance()->getAdapter();
242
243 try {
244 $adapter->loadFile($avatar->getLocation());
245 } catch (SystemException $e) {
246 // broken image
247 $editor->delete();
248 continue;
249 }
250
251 $thumbnail = $adapter->createThumbnail($width, $height, false);
252 $adapter->writeImage($thumbnail, $avatar->getLocation());
253 // Clear thumbnail as soon as possible to free up the memory.
254 $thumbnail = null;
255 }
256
257 if ($width != UserAvatar::AVATAR_SIZE || $height != UserAvatar::AVATAR_SIZE) {
258 // resize avatar
259 $adapter = ImageHandler::getInstance()->getAdapter();
260
261 try {
262 $adapter->loadFile($avatar->getLocation());
263 } catch (SystemException $e) {
264 // broken image
265 $editor->delete();
266 continue;
267 }
268
269 $adapter->resize(0, 0, $width, $height, UserAvatar::AVATAR_SIZE, UserAvatar::AVATAR_SIZE);
270 $adapter->writeImage($adapter->getImage(), $avatar->getLocation());
271 $width = $height = UserAvatar::AVATAR_SIZE;
272 }
273
f68296a6 274 $editor->deleteLegacyThumbnails();
71a3289c
AE
275 $editor->createAvatarVariant();
276
a9229942
TD
277 $editor->update([
278 'width' => $width,
279 'height' => $height,
280 ]);
281 }
282 }
283 }
e3667539 284}