Apply PSR-12 code style (#3886)
[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';
50 $this->objectList->sqlJoins = "LEFT JOIN wcf" . WCF_N . "_user_option_value user_option_value ON (user_option_value.userID = user_table.userID)";
51 $this->objectList->sqlOrderBy = 'user_table.userID';
52 }
53
54 /**
55 * @inheritDoc
56 */
57 public function execute()
58 {
59 parent::execute();
60
61 $users = $userIDs = [];
62 foreach ($this->getObjectList() as $user) {
63 $users[] = new UserEditor($user);
64 $userIDs[] = $user->userID;
65 }
66
67 // update user ranks
68 if (!empty($users)) {
69 $action = new UserProfileAction($users, 'updateUserOnlineMarking');
70 $action->executeAction();
71 }
72
73 if (!empty($userIDs)) {
74 // update article counter
75 $conditionBuilder = new PreparedStatementConditionBuilder();
76 $conditionBuilder->add('user_table.userID IN (?)', [$userIDs]);
77 $sql = "UPDATE wcf" . WCF_N . "_user user_table
78 SET articles = (
79 SELECT COUNT(*)
80 FROM wcf" . WCF_N . "_article
81 WHERE userID = user_table.userID
82 )
83 " . $conditionBuilder;
84 $statement = WCF::getDB()->prepareStatement($sql);
85 $statement->execute($conditionBuilder->getParameters());
86
87 // update like counter
88 if (MODULE_LIKE) {
89 $sql = "UPDATE wcf" . WCF_N . "_user user_table
90 SET";
91
92 $reactionTypeIDs = \array_keys(ReactionTypeCache::getInstance()->getReactionTypes());
93 if (!empty($reactionTypeIDs)) {
94 $sql .= "
95 likesReceived = (
96 SELECT COUNT(*)
97 FROM wcf" . WCF_N . "_like
98 WHERE objectUserID = user_table.userID
99 AND reactionTypeID IN (" . \implode(',', $reactionTypeIDs) . ")
100 )";
101 } else {
102 $sql .= " likesReceived = 0";
103 }
104
105 $sql .= " " . $conditionBuilder;
106 $statement = WCF::getDB()->prepareStatement($sql);
107 $statement->execute($conditionBuilder->getParameters());
108 }
109
110 // update trophy points
111 if (MODULE_TROPHY) {
112 $sql = "UPDATE wcf" . WCF_N . "_user user_table
113 SET trophyPoints = (
114 SELECT COUNT(*)
115 FROM wcf" . WCF_N . "_user_trophy user_trophy
116 LEFT JOIN wcf" . WCF_N . "_trophy trophy
117 ON (user_trophy.trophyID = trophy.trophyID)
118 LEFT JOIN wcf" . WCF_N . "_category trophy_category
119 ON (trophy.categoryID = trophy_category.categoryID)
120 WHERE user_trophy.userID = user_table.userID
121 AND trophy.isDisabled = 0
122 AND trophy_category.isDisabled = 0
123 )
124 " . $conditionBuilder;
125 $statement = WCF::getDB()->prepareStatement($sql);
126 $statement->execute($conditionBuilder->getParameters());
127 }
128
129 // update signatures and about me
130 $sql = "UPDATE wcf" . WCF_N . "_user_option_value
131 SET userOption" . User::getUserOptionID('aboutMe') . " = ?
132 WHERE userID = ?";
133 $statement = WCF::getDB()->prepareStatement($sql);
134
135 // retrieve permissions
136 $userIDs = [];
137 foreach ($users as $user) {
138 $userIDs[] = $user->userID;
139 }
140 $userPermissions = $this->getBulkUserPermissions(
141 $userIDs,
142 ['user.message.disallowedBBCodes', 'user.signature.disallowedBBCodes']
143 );
144
145 $htmlInputProcessor = new HtmlInputProcessor();
146 WCF::getDB()->beginTransaction();
147 /** @var UserEditor $user */
148 foreach ($users as $user) {
149 BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode(
150 ',',
151 $this->getBulkUserPermissionValue(
152 $userPermissions,
153 $user->userID,
154 'user.signature.disallowedBBCodes'
155 )
156 ));
157
158 if (!$user->signatureEnableHtml) {
159 $htmlInputProcessor->process(
160 $user->signature,
161 'com.woltlab.wcf.user.signature',
162 $user->userID,
163 true
164 );
165
166 $user->update([
167 'signature' => $htmlInputProcessor->getHtml(),
168 'signatureEnableHtml' => 1,
169 ]);
170 } else {
171 $htmlInputProcessor->reprocess($user->signature, 'com.woltlab.wcf.user.signature', $user->userID);
172 $user->update(['signature' => $htmlInputProcessor->getHtml()]);
173 }
174
175 if ($user->aboutMe) {
176 BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode(
177 ',',
178 $this->getBulkUserPermissionValue(
179 $userPermissions,
180 $user->userID,
181 'user.message.disallowedBBCodes'
182 )
183 ));
184
185 if (!$user->signatureEnableHtml) {
186 $htmlInputProcessor->process(
187 $user->aboutMe,
188 'com.woltlab.wcf.user.aboutMe',
189 $user->userID,
190 true
191 );
192 } else {
193 $htmlInputProcessor->reprocess($user->aboutMe, 'com.woltlab.wcf.user.aboutMe', $user->userID);
194 }
195
196 $html = $htmlInputProcessor->getHtml();
197 // MySQL's TEXT type allows for 65,535 bytes, hence we need to count
198 // the bytes rather than the actual amount of characters
199 if (\strlen($html) > 65535) {
200 // content does not fit the available space, and any
201 // attempts to truncate it will yield awkward results
202 $html = '';
203 }
204
205 $statement->execute([$html, $user->userID]);
206 }
207 }
208 WCF::getDB()->commitTransaction();
209
210 // update old/imported avatars
211 $avatarList = new UserAvatarList();
212 $avatarList->getConditionBuilder()->add('user_avatar.userID IN (?)', [$userIDs]);
213 $avatarList->getConditionBuilder()->add(
214 '(user_avatar.width <> ? OR user_avatar.height <> ?)',
215 [UserAvatar::AVATAR_SIZE, UserAvatar::AVATAR_SIZE]
216 );
217 $avatarList->readObjects();
218 foreach ($avatarList as $avatar) {
219 $editor = new UserAvatarEditor($avatar);
220 if (!\file_exists($avatar->getLocation()) || @\getimagesize($avatar->getLocation()) === false) {
221 // delete avatars that are missing or broken
222 $editor->delete();
223 continue;
224 }
225
226 $width = $avatar->width;
227 $height = $avatar->height;
228 if ($width != $height) {
229 // make avatar quadratic
230 $width = $height = \min($width, $height, UserAvatar::AVATAR_SIZE);
231 $adapter = ImageHandler::getInstance()->getAdapter();
232
233 try {
234 $adapter->loadFile($avatar->getLocation());
235 } catch (SystemException $e) {
236 // broken image
237 $editor->delete();
238 continue;
239 }
240
241 $thumbnail = $adapter->createThumbnail($width, $height, false);
242 $adapter->writeImage($thumbnail, $avatar->getLocation());
243 // Clear thumbnail as soon as possible to free up the memory.
244 $thumbnail = null;
245 }
246
247 if ($width != UserAvatar::AVATAR_SIZE || $height != UserAvatar::AVATAR_SIZE) {
248 // resize avatar
249 $adapter = ImageHandler::getInstance()->getAdapter();
250
251 try {
252 $adapter->loadFile($avatar->getLocation());
253 } catch (SystemException $e) {
254 // broken image
255 $editor->delete();
256 continue;
257 }
258
259 $adapter->resize(0, 0, $width, $height, UserAvatar::AVATAR_SIZE, UserAvatar::AVATAR_SIZE);
260 $adapter->writeImage($adapter->getImage(), $avatar->getLocation());
261 $width = $height = UserAvatar::AVATAR_SIZE;
262 }
263
264 $editor->update([
265 'width' => $width,
266 'height' => $height,
267 ]);
268 }
269 }
270 }
e3667539 271}