Commit | Line | Data |
---|---|---|
e3667539 | 1 | <?php |
a9229942 | 2 | |
e3667539 | 3 | namespace wcf\system\worker; |
a9229942 | 4 | |
557115b5 | 5 | use wcf\data\reaction\type\ReactionTypeCache; |
2772d4eb MW |
6 | use wcf\data\user\avatar\UserAvatar; |
7 | use wcf\data\user\avatar\UserAvatarEditor; | |
8 | use wcf\data\user\avatar\UserAvatarList; | |
8a413435 | 9 | use wcf\data\user\User; |
e3667539 | 10 | use wcf\data\user\UserEditor; |
157054c9 | 11 | use wcf\data\user\UserList; |
e3667539 | 12 | use wcf\data\user\UserProfileAction; |
7e058783 | 13 | use wcf\system\bbcode\BBCodeHandler; |
e3667539 | 14 | use wcf\system\database\util\PreparedStatementConditionBuilder; |
c5c9e424 | 15 | use wcf\system\exception\SystemException; |
b8c48208 | 16 | use wcf\system\html\input\HtmlInputProcessor; |
2772d4eb | 17 | use wcf\system\image\ImageHandler; |
e3667539 MW |
18 | use 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 |
30 | class 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 | } |