* @package WoltLabSuite\Core\System\Worker * * @method UserList getObjectList() */ class UserRebuildDataWorker extends AbstractRebuildDataWorker { /** * @inheritDoc */ protected $objectListClassName = UserList::class; /** * @inheritDoc */ protected $limit = 50; /** * @inheritDoc */ protected function initObjectList() { parent::initObjectList(); $this->objectList->sqlSelects = 'user_option_value.userOption' . User::getUserOptionID('aboutMe') . ' AS aboutMe'; $this->objectList->sqlJoins = " LEFT JOIN wcf" . WCF_N . "_user_option_value user_option_value ON user_option_value.userID = user_table.userID"; $this->objectList->sqlOrderBy = 'user_table.userID'; } /** * @inheritDoc */ public function execute() { parent::execute(); $users = $userIDs = []; foreach ($this->getObjectList() as $user) { $users[] = new UserEditor($user); $userIDs[] = $user->userID; } // update user ranks if (!empty($users)) { $action = new UserProfileAction($users, 'updateUserOnlineMarking'); $action->executeAction(); } if (!empty($userIDs)) { // update article counter $conditionBuilder = new PreparedStatementConditionBuilder(); $conditionBuilder->add('user_table.userID IN (?)', [$userIDs]); $sql = "UPDATE wcf" . WCF_N . "_user user_table SET articles = ( SELECT COUNT(*) FROM wcf" . WCF_N . "_article WHERE userID = user_table.userID ) " . $conditionBuilder; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditionBuilder->getParameters()); // update like counter if (MODULE_LIKE) { $sql = "UPDATE wcf" . WCF_N . "_user user_table SET"; $reactionTypeIDs = \array_keys(ReactionTypeCache::getInstance()->getReactionTypes()); if (!empty($reactionTypeIDs)) { $sql .= " likesReceived = ( SELECT COUNT(*) FROM wcf" . WCF_N . "_like WHERE objectUserID = user_table.userID AND reactionTypeID IN (" . \implode(',', $reactionTypeIDs) . ") )"; } else { $sql .= " likesReceived = 0"; } $sql .= " " . $conditionBuilder; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditionBuilder->getParameters()); } // update trophy points if (MODULE_TROPHY) { $sql = "UPDATE wcf" . WCF_N . "_user user_table SET trophyPoints = ( SELECT COUNT(*) FROM wcf" . WCF_N . "_user_trophy user_trophy LEFT JOIN wcf" . WCF_N . "_trophy trophy ON user_trophy.trophyID = trophy.trophyID LEFT JOIN wcf" . WCF_N . "_category trophy_category ON trophy.categoryID = trophy_category.categoryID WHERE user_trophy.userID = user_table.userID AND trophy.isDisabled = 0 AND trophy_category.isDisabled = 0 ) " . $conditionBuilder; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditionBuilder->getParameters()); } // update signatures and about me $sql = "UPDATE wcf" . WCF_N . "_user_option_value SET userOption" . User::getUserOptionID('aboutMe') . " = ? WHERE userID = ?"; $statement = WCF::getDB()->prepareStatement($sql); // retrieve permissions $userIDs = []; foreach ($users as $user) { $userIDs[] = $user->userID; } $userPermissions = $this->getBulkUserPermissions( $userIDs, ['user.message.disallowedBBCodes', 'user.signature.disallowedBBCodes'] ); $htmlInputProcessor = new HtmlInputProcessor(); WCF::getDB()->beginTransaction(); /** @var UserEditor $user */ foreach ($users as $user) { BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode( ',', $this->getBulkUserPermissionValue( $userPermissions, $user->userID, 'user.signature.disallowedBBCodes' ) )); if (!$user->signatureEnableHtml) { $htmlInputProcessor->process( $user->signature, 'com.woltlab.wcf.user.signature', $user->userID, true ); $user->update([ 'signature' => $htmlInputProcessor->getHtml(), 'signatureEnableHtml' => 1, ]); } else { $htmlInputProcessor->reprocess($user->signature, 'com.woltlab.wcf.user.signature', $user->userID); $user->update(['signature' => $htmlInputProcessor->getHtml()]); } if ($user->aboutMe) { BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode( ',', $this->getBulkUserPermissionValue( $userPermissions, $user->userID, 'user.message.disallowedBBCodes' ) )); if (!$user->signatureEnableHtml) { $htmlInputProcessor->process( $user->aboutMe, 'com.woltlab.wcf.user.aboutMe', $user->userID, true ); } else { $htmlInputProcessor->reprocess($user->aboutMe, 'com.woltlab.wcf.user.aboutMe', $user->userID); } $html = $htmlInputProcessor->getHtml(); // MySQL's TEXT type allows for 65,535 bytes, hence we need to count // the bytes rather than the actual amount of characters if (\strlen($html) > 65535) { // content does not fit the available space, and any // attempts to truncate it will yield awkward results $html = ''; } $statement->execute([$html, $user->userID]); } } WCF::getDB()->commitTransaction(); // update old/imported avatars $avatarList = new UserAvatarList(); $avatarList->getConditionBuilder()->add('user_avatar.userID IN (?)', [$userIDs]); $avatarList->getConditionBuilder()->add( '( (user_avatar.width <> ? OR user_avatar.height <> ?) OR (user_avatar.hasWebP = ? AND user_avatar.avatarExtension <> ?) )', [ UserAvatar::AVATAR_SIZE, UserAvatar::AVATAR_SIZE, 1, "gif", ] ); $avatarList->readObjects(); foreach ($avatarList as $avatar) { $editor = new UserAvatarEditor($avatar); if (!\file_exists($avatar->getLocation()) || @\getimagesize($avatar->getLocation()) === false) { // delete avatars that are missing or broken $editor->delete(); continue; } $width = $avatar->width; $height = $avatar->height; if ($width != $height) { // make avatar quadratic $width = $height = \min($width, $height, UserAvatar::AVATAR_SIZE); $adapter = ImageHandler::getInstance()->getAdapter(); try { $adapter->loadFile($avatar->getLocation()); } catch (SystemException $e) { // broken image $editor->delete(); continue; } $thumbnail = $adapter->createThumbnail($width, $height, false); $adapter->writeImage($thumbnail, $avatar->getLocation()); // Clear thumbnail as soon as possible to free up the memory. $thumbnail = null; } if ($width != UserAvatar::AVATAR_SIZE || $height != UserAvatar::AVATAR_SIZE) { // resize avatar $adapter = ImageHandler::getInstance()->getAdapter(); try { $adapter->loadFile($avatar->getLocation()); } catch (SystemException $e) { // broken image $editor->delete(); continue; } $adapter->resize(0, 0, $width, $height, UserAvatar::AVATAR_SIZE, UserAvatar::AVATAR_SIZE); $adapter->writeImage($adapter->getImage(), $avatar->getLocation()); $width = $height = UserAvatar::AVATAR_SIZE; } $editor->deleteLegacyThumbnails(); $editor->createAvatarVariant(); $editor->update([ 'width' => $width, 'height' => $height, ]); } } } }