2 namespace wcf\system\worker
;
3 use wcf\data\reaction\type\ReactionTypeCache
;
4 use wcf\data\user\avatar\UserAvatar
;
5 use wcf\data\user\avatar\UserAvatarEditor
;
6 use wcf\data\user\avatar\UserAvatarList
;
7 use wcf\data\user\User
;
8 use wcf\data\user\UserEditor
;
9 use wcf\data\user\UserList
;
10 use wcf\data\user\UserProfileAction
;
11 use wcf\system\bbcode\BBCodeHandler
;
12 use wcf\system\database\util\PreparedStatementConditionBuilder
;
13 use wcf\system\exception\SystemException
;
14 use wcf\system\html\input\HtmlInputProcessor
;
15 use wcf\system\image\ImageHandler
;
19 * Worker implementation for updating users.
22 * @copyright 2001-2019 WoltLab GmbH
23 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
24 * @package WoltLabSuite\Core\System\Worker
26 * @method UserList getObjectList()
28 class UserRebuildDataWorker
extends AbstractRebuildDataWorker
{
32 protected $objectListClassName = UserList
::class;
37 protected $limit = 50;
42 protected function initObjectList() {
43 parent
::initObjectList();
45 $this->objectList
->sqlSelects
= 'user_option_value.userOption' . User
::getUserOptionID('aboutMe') . ' AS aboutMe';
46 $this->objectList
->sqlJoins
= "LEFT JOIN wcf".WCF_N
."_user_option_value user_option_value ON (user_option_value.userID = user_table.userID)";
47 $this->objectList
->sqlOrderBy
= 'user_table.userID';
53 public function execute() {
56 $users = $userIDs = [];
57 foreach ($this->getObjectList() as $user) {
58 $users[] = new UserEditor($user);
59 $userIDs[] = $user->userID
;
64 $action = new UserProfileAction($users, 'updateUserOnlineMarking');
65 $action->executeAction();
68 if (!empty($userIDs)) {
69 // update article counter
70 $conditionBuilder = new PreparedStatementConditionBuilder();
71 $conditionBuilder->add('user_table.userID IN (?)', [$userIDs]);
72 $sql = "UPDATE wcf".WCF_N
."_user user_table
75 FROM wcf".WCF_N
."_article
76 WHERE userID = user_table.userID
79 $statement = WCF
::getDB()->prepareStatement($sql);
80 $statement->execute($conditionBuilder->getParameters());
82 // update like counter
84 $sql = "UPDATE wcf".WCF_N
."_user user_table SET";
86 $reactionTypeIDs = array_keys(ReactionTypeCache
::getInstance()->getReactionTypes());
87 if (!empty($reactionTypeIDs)) {
88 $sql .= " likesReceived = (
90 FROM wcf".WCF_N
."_like
91 WHERE objectUserID = user_table.userID
92 AND reactionTypeID IN (". implode(',', $reactionTypeIDs) .")
96 $sql .= " likesReceived = 0";
99 $sql .= " ".$conditionBuilder;
100 $statement = WCF
::getDB()->prepareStatement($sql);
101 $statement->execute($conditionBuilder->getParameters());
104 // update trophy points
106 $sql = "UPDATE wcf".WCF_N
."_user user_table
109 FROM wcf".WCF_N
."_user_trophy user_trophy
110 LEFT JOIN wcf".WCF_N
."_trophy trophy ON user_trophy.trophyID = trophy.trophyID
111 LEFT JOIN wcf".WCF_N
."_category trophy_category ON trophy.categoryID = trophy_category.categoryID
112 WHERE user_trophy.userID = user_table.userID
113 AND trophy.isDisabled = 0
114 AND trophy_category.isDisabled = 0
117 $statement = WCF
::getDB()->prepareStatement($sql);
118 $statement->execute($conditionBuilder->getParameters());
121 // update signatures and about me
122 $sql = "UPDATE wcf".WCF_N
."_user_option_value
123 SET userOption" . User
::getUserOptionID('aboutMe') . " = ?
125 $statement = WCF
::getDB()->prepareStatement($sql);
127 // retrieve permissions
129 foreach ($users as $user) {
130 $userIDs[] = $user->userID
;
132 $userPermissions = $this->getBulkUserPermissions($userIDs, ['user.message.disallowedBBCodes', 'user.signature.disallowedBBCodes']);
134 $htmlInputProcessor = new HtmlInputProcessor();
135 WCF
::getDB()->beginTransaction();
136 /** @var UserEditor $user */
137 foreach ($users as $user) {
138 BBCodeHandler
::getInstance()->setDisallowedBBCodes(explode(',', $this->getBulkUserPermissionValue($userPermissions, $user->userID
, 'user.signature.disallowedBBCodes')));
140 if (!$user->signatureEnableHtml
) {
141 $htmlInputProcessor->process($user->signature
, 'com.woltlab.wcf.user.signature', $user->userID
, true);
144 'signature' => $htmlInputProcessor->getHtml(),
145 'signatureEnableHtml' => 1
149 $htmlInputProcessor->reprocess($user->signature
, 'com.woltlab.wcf.user.signature', $user->userID
);
150 $user->update(['signature' => $htmlInputProcessor->getHtml()]);
153 if ($user->aboutMe
) {
154 BBCodeHandler
::getInstance()->setDisallowedBBCodes(explode(',', $this->getBulkUserPermissionValue($userPermissions, $user->userID
, 'user.message.disallowedBBCodes')));
156 if (!$user->signatureEnableHtml
) {
157 $htmlInputProcessor->process($user->aboutMe
, 'com.woltlab.wcf.user.aboutMe', $user->userID
, true);
160 $htmlInputProcessor->reprocess($user->aboutMe
, 'com.woltlab.wcf.user.aboutMe', $user->userID
);
163 $html = $htmlInputProcessor->getHtml();
164 // MySQL's TEXT type allows for 65,535 bytes, hence we need to count
165 // the bytes rather than the actual amount of characters
166 if (strlen($html) > 65535) {
167 // content does not fit the available space, and any
168 // attempts to truncate it will yield awkward results
172 $statement->execute([$html, $user->userID
]);
175 WCF
::getDB()->commitTransaction();
177 // update old/imported avatars
178 $avatarList = new UserAvatarList();
179 $avatarList->getConditionBuilder()->add('user_avatar.userID IN (?)', [$userIDs]);
180 $avatarList->getConditionBuilder()->add('(user_avatar.width <> ? OR user_avatar.height <> ?)', [UserAvatar
::AVATAR_SIZE
, UserAvatar
::AVATAR_SIZE
]);
181 $avatarList->readObjects();
182 foreach ($avatarList as $avatar) {
183 $editor = new UserAvatarEditor($avatar);
184 if (!file_exists($avatar->getLocation()) || @getimagesize
($avatar->getLocation()) === false) {
185 // delete avatars that are missing or broken
190 $width = $avatar->width
;
191 $height = $avatar->height
;
192 if ($width != $height) {
193 // make avatar quadratic
194 $width = $height = min($width, $height, UserAvatar
::AVATAR_SIZE
);
195 $adapter = ImageHandler
::getInstance()->getAdapter();
198 $adapter->loadFile($avatar->getLocation());
200 catch (SystemException
$e) {
206 $thumbnail = $adapter->createThumbnail($width, $height, false);
207 $adapter->writeImage($thumbnail, $avatar->getLocation());
208 // Clear thumbnail as soon as possible to free up the memory.
212 if ($width != UserAvatar
::AVATAR_SIZE ||
$height != UserAvatar
::AVATAR_SIZE
) {
214 $adapter = ImageHandler
::getInstance()->getAdapter();
217 $adapter->loadFile($avatar->getLocation());
219 catch (SystemException
$e) {
225 $adapter->resize(0, 0, $width, $height, UserAvatar
::AVATAR_SIZE
, UserAvatar
::AVATAR_SIZE
);
226 $adapter->writeImage($adapter->getImage(), $avatar->getLocation());
227 $width = $height = UserAvatar
::AVATAR_SIZE
;