3 namespace wcf\system\worker
;
5 use wcf\data\reaction\type\ReactionTypeCache
;
6 use wcf\data\user\avatar\UserAvatar
;
7 use wcf\data\user\avatar\UserAvatarEditor
;
8 use wcf\data\user\avatar\UserAvatarList
;
9 use wcf\data\user\User
;
10 use wcf\data\user\UserEditor
;
11 use wcf\data\user\UserList
;
12 use wcf\data\user\UserProfileAction
;
13 use wcf\system\bbcode\BBCodeHandler
;
14 use wcf\system\database\util\PreparedStatementConditionBuilder
;
15 use wcf\system\exception\SystemException
;
16 use wcf\system\html\input\HtmlInputProcessor
;
17 use wcf\system\image\ImageHandler
;
21 * Worker implementation for updating users.
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
28 * @method UserList getObjectList()
30 class UserRebuildDataWorker
extends AbstractRebuildDataWorker
35 protected $objectListClassName = UserList
::class;
40 protected $limit = 50;
45 protected function initObjectList()
47 parent
::initObjectList();
49 $this->objectList
->sqlSelects
= 'user_option_value.userOption' . User
::getUserOptionID('aboutMe') . ' AS aboutMe';
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";
53 $this->objectList
->sqlOrderBy
= 'user_table.userID';
59 public function execute()
63 $users = $userIDs = [];
64 foreach ($this->getObjectList() as $user) {
65 $users[] = new UserEditor($user);
66 $userIDs[] = $user->userID
;
71 $action = new UserProfileAction($users, 'updateUserOnlineMarking');
72 $action->executeAction();
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
82 FROM wcf" . WCF_N
. "_article
83 WHERE userID = user_table.userID
85 " . $conditionBuilder;
86 $statement = WCF
::getDB()->prepareStatement($sql);
87 $statement->execute($conditionBuilder->getParameters());
89 // update like counter
91 $sql = "UPDATE wcf" . WCF_N
. "_user user_table
94 $reactionTypeIDs = \array_keys
(ReactionTypeCache
::getInstance()->getReactionTypes());
95 if (!empty($reactionTypeIDs)) {
99 FROM wcf" . WCF_N
. "_like
100 WHERE objectUserID = user_table.userID
101 AND reactionTypeID IN (" . \
implode(',', $reactionTypeIDs) . ")
104 $sql .= " likesReceived = 0";
107 $sql .= " " . $conditionBuilder;
108 $statement = WCF
::getDB()->prepareStatement($sql);
109 $statement->execute($conditionBuilder->getParameters());
112 // update trophy points
114 $sql = "UPDATE wcf" . WCF_N
. "_user user_table
117 FROM wcf" . WCF_N
. "_user_trophy user_trophy
118 LEFT JOIN wcf" . WCF_N
. "_trophy trophy
119 ON user_trophy.trophyID = trophy.trophyID
120 LEFT JOIN wcf" . WCF_N
. "_category trophy_category
121 ON trophy.categoryID = trophy_category.categoryID
122 WHERE user_trophy.userID = user_table.userID
123 AND trophy.isDisabled = 0
124 AND trophy_category.isDisabled = 0
126 " . $conditionBuilder;
127 $statement = WCF
::getDB()->prepareStatement($sql);
128 $statement->execute($conditionBuilder->getParameters());
131 // update signatures and about me
132 $sql = "UPDATE wcf" . WCF_N
. "_user_option_value
133 SET userOption" . User
::getUserOptionID('aboutMe') . " = ?
135 $statement = WCF
::getDB()->prepareStatement($sql);
137 // retrieve permissions
139 foreach ($users as $user) {
140 $userIDs[] = $user->userID
;
142 $userPermissions = $this->getBulkUserPermissions(
144 ['user.message.disallowedBBCodes', 'user.signature.disallowedBBCodes']
147 $htmlInputProcessor = new HtmlInputProcessor();
148 WCF
::getDB()->beginTransaction();
149 /** @var UserEditor $user */
150 foreach ($users as $user) {
151 BBCodeHandler
::getInstance()->setDisallowedBBCodes(\
explode(
153 $this->getBulkUserPermissionValue(
156 'user.signature.disallowedBBCodes'
160 if (!$user->signatureEnableHtml
) {
161 $htmlInputProcessor->process(
163 'com.woltlab.wcf.user.signature',
169 'signature' => $htmlInputProcessor->getHtml(),
170 'signatureEnableHtml' => 1,
173 $htmlInputProcessor->reprocess($user->signature
, 'com.woltlab.wcf.user.signature', $user->userID
);
174 $user->update(['signature' => $htmlInputProcessor->getHtml()]);
177 if ($user->aboutMe
) {
178 BBCodeHandler
::getInstance()->setDisallowedBBCodes(\
explode(
180 $this->getBulkUserPermissionValue(
183 'user.message.disallowedBBCodes'
187 if (!$user->signatureEnableHtml
) {
188 $htmlInputProcessor->process(
190 'com.woltlab.wcf.user.aboutMe',
195 $htmlInputProcessor->reprocess($user->aboutMe
, 'com.woltlab.wcf.user.aboutMe', $user->userID
);
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
207 $statement->execute([$html, $user->userID
]);
210 WCF
::getDB()->commitTransaction();
212 // update old/imported avatars
213 $avatarList = new UserAvatarList();
214 $avatarList->getConditionBuilder()->add('user_avatar.userID IN (?)', [$userIDs]);
215 $avatarList->getConditionBuilder()->add(
217 (user_avatar.width <> ? OR user_avatar.height <> ?)
218 OR (user_avatar.hasWebP = ? AND user_avatar.avatarExtension <> ?)
221 UserAvatar
::AVATAR_SIZE
,
222 UserAvatar
::AVATAR_SIZE
,
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
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();
244 $adapter->loadFile($avatar->getLocation());
245 } catch (SystemException
$e) {
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.
257 if ($width != UserAvatar
::AVATAR_SIZE ||
$height != UserAvatar
::AVATAR_SIZE
) {
259 $adapter = ImageHandler
::getInstance()->getAdapter();
262 $adapter->loadFile($avatar->getLocation());
263 } catch (SystemException
$e) {
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
;
274 $editor->createAvatarVariant();