2 namespace wcf\data\user
;
3 use wcf\data\
object\type\ObjectTypeCache
;
4 use wcf\data\user\avatar\UserAvatarAction
;
5 use wcf\data\user\group\UserGroup
;
6 use wcf\data\AbstractDatabaseObjectAction
;
7 use wcf\data\IClipboardAction
;
8 use wcf\data\ISearchAction
;
9 use wcf\system\attachment\AttachmentHandler
;
10 use wcf\system\clipboard\ClipboardHandler
;
11 use wcf\system\comment\CommentHandler
;
12 use wcf\system\database\util\PreparedStatementConditionBuilder
;
13 use wcf\system\email\mime\MimePartFacade
;
14 use wcf\system\email\mime\RecipientAwareTextMimePart
;
15 use wcf\system\email\Email
;
16 use wcf\system\email\UserMailbox
;
17 use wcf\system\event\EventHandler
;
18 use wcf\system\exception\IllegalLinkException
;
19 use wcf\system\exception\PermissionDeniedException
;
20 use wcf\system\exception\UserInputException
;
21 use wcf\system\request\RequestHandler
;
23 use wcf\util\UserRegistrationUtil
;
26 * Executes user-related actions.
28 * @author Alexander Ebert
29 * @copyright 2001-2018 WoltLab GmbH
30 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
31 * @package WoltLabSuite\Core\Data\User
33 * @method UserEditor[] getObjects()
34 * @method UserEditor getSingleObject()
36 class UserAction
extends AbstractDatabaseObjectAction
implements IClipboardAction
, ISearchAction
{
40 public $className = UserEditor
::class;
45 protected $allowGuestAccess = ['getSearchResultList'];
50 protected $permissionsCreate = ['admin.user.canAddUser'];
55 protected $permissionsDelete = ['admin.user.canDeleteUser'];
60 protected $permissionsUpdate = ['admin.user.canEditUser'];
65 protected $requireACP = ['create', 'delete', 'resendActivationMail'];
68 * Validates permissions and parameters.
70 public function validateCreate() {
71 $this->readString('password', false, 'data');
75 * Validates accessible groups.
77 * @param boolean $ignoreOwnUser
78 * @throws PermissionDeniedException
79 * @throws UserInputException
81 protected function __validateAccessibleGroups($ignoreOwnUser = true) {
83 if (in_array(WCF
::getUser()->userID
, $this->objectIDs
)) {
84 unset($this->objectIDs
[array_search(WCF
::getUser()->userID
, $this->objectIDs
)]);
85 if (isset($this->objects
[WCF
::getUser()->userID
])) {
86 unset($this->objects
[WCF
::getUser()->userID
]);
91 // list might be empty because only our own user id was given
92 if (empty($this->objectIDs
)) {
93 throw new UserInputException('objectIDs');
97 $conditions = new PreparedStatementConditionBuilder();
98 $conditions->add("userID IN (?)", [$this->objectIDs
]);
100 $sql = "SELECT DISTINCT groupID
101 FROM wcf".WCF_N
."_user_to_group
103 $statement = WCF
::getDB()->prepareStatement($sql);
104 $statement->execute($conditions->getParameters());
105 $groupIDs = $statement->fetchAll(\PDO
::FETCH_COLUMN
);
107 if (!UserGroup
::isAccessibleGroup($groupIDs)) {
108 throw new PermissionDeniedException();
113 * Validates permissions and parameters.
115 public function validateDelete() {
116 // read and validate user objects
117 parent
::validateDelete();
119 $this->__validateAccessibleGroups();
125 public function delete() {
126 if (empty($this->objects
)) {
127 $this->readObjects();
132 foreach ($this->getObjects() as $user) {
133 if ($user->avatarID
) $avatarIDs[] = $user->avatarID
;
135 if (!empty($avatarIDs)) {
136 $action = new UserAvatarAction($avatarIDs, 'delete');
137 $action->executeAction();
140 // delete profile comments and signature attachments
141 if (!empty($this->objectIDs
)) {
142 CommentHandler
::getInstance()->deleteObjects('com.woltlab.wcf.user.profileComment', $this->objectIDs
);
143 AttachmentHandler
::removeAttachments('com.woltlab.wcf.user.signature', $this->objectIDs
);
146 return parent
::delete();
150 * Validates permissions and parameters.
152 public function validateUpdate() {
154 if (empty($this->objects
)) {
155 $this->readObjects();
157 if (empty($this->objects
)) {
158 throw new UserInputException('objectIDs');
162 // disallow updating of anything except for options outside of ACP
163 if (RequestHandler
::getInstance()->isACPRequest() && (count($this->parameters
) != 1 ||
!isset($this->parameters
['options']))) {
164 throw new PermissionDeniedException();
168 WCF
::getSession()->checkPermissions($this->permissionsUpdate
);
170 catch (PermissionDeniedException
$e) {
171 // check if we're editing ourselves
172 if (count($this->objects
) == 1 && ($this->objects
[0]->userID
== WCF
::getUser()->userID
)) {
173 $count = count($this->parameters
);
174 if ($count > 1 ||
($count == 1 && !isset($this->parameters
['options']))) {
175 throw new PermissionDeniedException();
179 throw new PermissionDeniedException();
185 * Validates the ban action.
187 public function validateBan() {
188 $this->validateUnban();
190 $this->readString('banReason', true);
191 $this->readString('banExpires', true);
195 * Validates the unban action.
197 public function validateUnban() {
198 WCF
::getSession()->checkPermissions(['admin.user.canBanUser']);
200 $this->__validateAccessibleGroups();
206 public function ban() {
207 $banExpires = $this->parameters
['banExpires'];
209 $banExpires = strtotime($banExpires);
210 if ($banExpires > 2147483647) $banExpires = 2147483647;
216 $conditionBuilder = new PreparedStatementConditionBuilder();
217 $conditionBuilder->add('userID IN (?)', [$this->objectIDs
]);
219 $sql = "UPDATE wcf".WCF_N
."_user
224 $statement = WCF
::getDB()->prepareStatement($sql);
228 $this->parameters
['banReason'],
230 ], $conditionBuilder->getParameters())
233 $this->unmarkItems();
235 $firstUser = new User(reset($this->objectIDs
));
236 return WCF
::getLanguage()->getDynamicVariable('wcf.user.banned', ['user' => $firstUser]);
242 public function unban() {
243 $conditionBuilder = new PreparedStatementConditionBuilder();
244 $conditionBuilder->add('userID IN (?)', [$this->objectIDs
]);
246 $sql = "UPDATE wcf".WCF_N
."_user
250 $statement = WCF
::getDB()->prepareStatement($sql);
255 ], $conditionBuilder->getParameters())
263 public function create() {
264 /** @var User $user */
265 $user = parent
::create();
266 $userEditor = new UserEditor($user);
268 // updates user options
269 if (isset($this->parameters
['options'])) {
270 $userEditor->updateUserOptions($this->parameters
['options']);
273 // insert user groups
274 $addDefaultGroups = isset($this->parameters
['addDefaultGroups']) ?
$this->parameters
['addDefaultGroups'] : true;
275 $groupIDs = isset($this->parameters
['groups']) ?
$this->parameters
['groups'] : [];
276 $userEditor->addToGroups($groupIDs, false, $addDefaultGroups);
278 // insert visible languages
279 if (!isset($this->parameters
['languageIDs'])) {
280 // using the 'languages' key is deprecated since WCF 2.1, please use 'languageIDs' instead
281 $this->parameters
['languageIDs'] = (!empty($this->parameters
['languages'])) ?
$this->parameters
['languages'] : [];
283 $userEditor->addToLanguages($this->parameters
['languageIDs'], false);
286 // set default notifications
287 $sql = "INSERT INTO wcf".WCF_N
."_user_notification_event_to_user
288 (userID, eventID, mailNotificationType)
289 SELECT ?, eventID, presetMailNotificationType
290 FROM wcf".WCF_N
."_user_notification_event
292 $statement = WCF
::getDB()->prepareStatement($sql);
293 $statement->execute([$user->userID
, 1]);
296 if (MODULE_USER_RANK
) {
297 $action = new UserProfileAction([$userEditor], 'updateUserRank');
298 $action->executeAction();
300 // update user online marking
301 $action = new UserProfileAction([$userEditor], 'updateUserOnlineMarking');
302 $action->executeAction();
311 public function update() {
312 if (isset($this->parameters
['data']) ||
isset($this->parameters
['counters'])) {
315 if (isset($this->parameters
['data']['languageID'])) {
316 foreach ($this->getObjects() as $object) {
317 if ($object->userID
== WCF
::getUser()->userID
) {
318 if ($this->parameters
['data']['languageID'] != WCF
::getUser()->languageID
) {
319 WCF
::setLanguage($this->parameters
['data']['languageID']);
328 if (empty($this->objects
)) {
329 $this->readObjects();
333 $groupIDs = isset($this->parameters
['groups']) ?
$this->parameters
['groups'] : [];
334 $languageIDs = isset($this->parameters
['languageIDs']) ?
$this->parameters
['languageIDs'] : [];
335 $removeGroups = isset($this->parameters
['removeGroups']) ?
$this->parameters
['removeGroups'] : [];
336 $userOptions = isset($this->parameters
['options']) ?
$this->parameters
['options'] : [];
338 if (!empty($groupIDs)) {
339 $action = new UserAction($this->objects
, 'addToGroups', [
340 'groups' => $groupIDs,
341 'addDefaultGroups' => false
343 $action->executeAction();
346 if (!empty($removeGroups)) {
347 $action = new UserAction($this->objects
, 'removeFromGroups', [
348 'groups' => $removeGroups
350 $action->executeAction();
353 foreach ($this->getObjects() as $userEditor) {
354 if (!empty($userOptions)) {
355 $userEditor->updateUserOptions($userOptions);
358 if (!empty($languageIDs)) {
359 $userEditor->addToLanguages($languageIDs);
363 // handle user rename
364 if (count($this->objects
) == 1 && !empty($this->parameters
['data']['username'])) {
365 if ($this->objects
[0]->username
!= $this->parameters
['data']['username']) {
366 $userID = $this->objects
[0]->userID
;
367 $username = $this->parameters
['data']['username'];
369 WCF
::getDB()->beginTransaction();
372 $sql = "UPDATE wcf".WCF_N
."_article
375 $statement = WCF
::getDB()->prepareStatement($sql);
376 $statement->execute([$username, $userID]);
379 $sql = "UPDATE wcf".WCF_N
."_comment
382 $statement = WCF
::getDB()->prepareStatement($sql);
383 $statement->execute([$username, $userID]);
385 // update comment responses
386 $sql = "UPDATE wcf".WCF_N
."_comment_response
389 $statement = WCF
::getDB()->prepareStatement($sql);
390 $statement->execute([$username, $userID]);
393 $sql = "UPDATE wcf".WCF_N
."_media
396 $statement = WCF
::getDB()->prepareStatement($sql);
397 $statement->execute([$username, $userID]);
399 // update modification log
400 $sql = "UPDATE wcf".WCF_N
."_modification_log
403 $statement = WCF
::getDB()->prepareStatement($sql);
404 $statement->execute([$username, $userID]);
406 WCF
::getDB()->commitTransaction();
408 // fire event to handle other database tables
409 EventHandler
::getInstance()->fireAction($this, 'rename');
415 * Remove users from given groups.
417 public function removeFromGroups() {
418 if (empty($this->objects
)) {
419 $this->readObjects();
422 $groupIDs = $this->parameters
['groups'];
424 foreach ($this->getObjects() as $userEditor) {
425 $userEditor->removeFromGroups($groupIDs);
430 UserEditor
::resetCache();
431 $this->readObjects();
433 if (MODULE_USER_RANK
) {
434 $action = new UserProfileAction($this->objects
, 'updateUserRank');
435 $action->executeAction();
437 if (MODULE_USERS_ONLINE
) {
438 $action = new UserProfileAction($this->objects
, 'updateUserOnlineMarking');
439 $action->executeAction();
444 * Add users to given groups.
446 public function addToGroups() {
447 if (empty($this->objects
)) {
448 $this->readObjects();
451 $groupIDs = $this->parameters
['groups'];
452 $deleteOldGroups = $addDefaultGroups = true;
453 if (isset($this->parameters
['deleteOldGroups'])) $deleteOldGroups = $this->parameters
['deleteOldGroups'];
454 if (isset($this->parameters
['addDefaultGroups'])) $addDefaultGroups = $this->parameters
['addDefaultGroups'];
456 foreach ($this->getObjects() as $userEditor) {
457 $userEditor->addToGroups($groupIDs, $deleteOldGroups, $addDefaultGroups);
462 UserEditor
::resetCache();
463 $this->readObjects();
465 if (MODULE_USER_RANK
) {
466 $action = new UserProfileAction($this->objects
, 'updateUserRank');
467 $action->executeAction();
469 if (MODULE_USERS_ONLINE
) {
470 $action = new UserProfileAction($this->objects
, 'updateUserOnlineMarking');
471 $action->executeAction();
478 public function validateGetSearchResultList() {
479 $this->readBoolean('includeUserGroups', false, 'data');
480 $this->readString('searchString', false, 'data');
482 if (isset($this->parameters
['data']['excludedSearchValues']) && !is_array($this->parameters
['data']['excludedSearchValues'])) {
483 throw new UserInputException('excludedSearchValues');
490 public function getSearchResultList() {
491 $searchString = $this->parameters
['data']['searchString'];
492 $excludedSearchValues = [];
493 if (isset($this->parameters
['data']['excludedSearchValues'])) {
494 $excludedSearchValues = $this->parameters
['data']['excludedSearchValues'];
498 if ($this->parameters
['data']['includeUserGroups']) {
499 $accessibleGroups = UserGroup
::getAccessibleGroups();
500 foreach ($accessibleGroups as $group) {
501 $groupName = $group->getName();
502 if (!in_array($groupName, $excludedSearchValues)) {
503 $pos = mb_strripos($groupName, $searchString);
504 if ($pos !== false && $pos == 0) {
506 'label' => $groupName,
507 'objectID' => $group->groupID
,
516 $searchString = addcslashes($searchString, '_%');
518 'searchString' => $searchString
520 EventHandler
::getInstance()->fireAction($this, 'beforeFindUsers', $parameters);
521 $userProfileList = new UserProfileList();
522 $userProfileList->getConditionBuilder()->add("username LIKE ?", [$parameters['searchString'].'%']);
523 if (!empty($excludedSearchValues)) {
524 $userProfileList->getConditionBuilder()->add("username NOT IN (?)", [$excludedSearchValues]);
526 $userProfileList->sqlLimit
= 10;
527 $userProfileList->readObjects();
529 foreach ($userProfileList as $userProfile) {
531 'icon' => $userProfile->getAvatar()->getImageTag(16),
532 'label' => $userProfile->username
,
533 'objectID' => $userProfile->userID
,
544 public function validateUnmarkAll() {
551 public function unmarkAll() {
552 ClipboardHandler
::getInstance()->removeItems(ClipboardHandler
::getInstance()->getObjectTypeID('com.woltlab.wcf.user'));
558 * @param integer[] $userIDs
560 protected function unmarkItems(array $userIDs = []) {
561 if (empty($userIDs)) {
562 $userIDs = $this->objectIDs
;
565 if (!empty($userIDs)) {
566 ClipboardHandler
::getInstance()->unmark($userIDs, ClipboardHandler
::getInstance()->getObjectTypeID('com.woltlab.wcf.user'));
571 * Validates the enable action.
573 public function validateEnable() {
574 WCF
::getSession()->checkPermissions(['admin.user.canEnableUser']);
576 $this->__validateAccessibleGroups();
580 * Validates the disable action.
582 public function validateDisable() {
583 $this->validateEnable();
589 public function enable() {
590 if (empty($this->objects
)) $this->readObjects();
592 $action = new UserAction($this->objects
, 'update', [
594 'activationCode' => 0
596 'removeGroups' => UserGroup
::getGroupIDsByType([UserGroup
::GUESTS
])
598 $action->executeAction();
599 $action = new UserAction($this->objects
, 'addToGroups', [
600 'groups' => UserGroup
::getGroupIDsByType([UserGroup
::USERS
]),
601 'deleteOldGroups' => false,
602 'addDefaultGroups' => false
604 $action->executeAction();
606 // send e-mail notification
607 if (empty($this->parameters
['skipNotification'])) {
608 foreach ($this->getObjects() as $user) {
609 $email = new Email();
610 $email->addRecipient(new UserMailbox($user->getDecoratedObject()));
611 $email->setSubject($user->getLanguage()->getDynamicVariable('wcf.acp.user.activation.mail.subject'));
612 $email->setBody(new MimePartFacade([
613 new RecipientAwareTextMimePart('text/html', 'email_adminActivation'),
614 new RecipientAwareTextMimePart('text/plain', 'email_adminActivation')
620 $this->unmarkItems();
626 public function disable() {
627 if (empty($this->objects
)) $this->readObjects();
629 $action = new UserAction($this->objects
, 'update', [
631 'activationCode' => UserRegistrationUtil
::getActivationCode()
633 'removeGroups' => UserGroup
::getGroupIDsByType([UserGroup
::USERS
])
635 $action->executeAction();
636 $action = new UserAction($this->objects
, 'addToGroups', [
637 'groups' => UserGroup
::getGroupIDsByType([UserGroup
::GUESTS
]),
638 'deleteOldGroups' => false,
639 'addDefaultGroups' => false
641 $action->executeAction();
643 $this->unmarkItems();
649 protected function readObjects() {
650 if (empty($this->objectIDs
)) {
655 $baseClass = call_user_func([$this->className
, 'getBaseClass']);
658 $sql = "SELECT user_option_value.*, user_table.*
659 FROM wcf".WCF_N
."_user user_table
660 LEFT JOIN wcf".WCF_N
."_user_option_value user_option_value
661 ON (user_option_value.userID = user_table.userID)
662 WHERE user_table.userID IN (".str_repeat('?,', count($this->objectIDs
) - 1)."?)";
663 $statement = WCF
::getDB()->prepareStatement($sql);
664 $statement->execute($this->objectIDs
);
665 while ($object = $statement->fetchObject($baseClass)) {
666 $this->objects
[] = new $this->className($object);
671 * Validates the 'disableSignature' action.
673 public function validateDisableSignature() {
674 $this->validateEnableSignature();
676 $this->readString('disableSignatureReason', true);
677 $this->readString('disableSignatureExpires', true);
681 * Disables the signature of the handled users.
683 public function disableSignature() {
684 if (empty($this->objects
)) {
685 $this->readObjects();
688 $disableSignatureExpires = $this->parameters
['disableSignatureExpires'];
689 if ($disableSignatureExpires) {
690 $disableSignatureExpires = strtotime($disableSignatureExpires);
693 $disableSignatureExpires = 0;
696 foreach ($this->getObjects() as $userEditor) {
697 $userEditor->update([
698 'disableSignature' => 1,
699 'disableSignatureReason' => $this->parameters
['disableSignatureReason'],
700 'disableSignatureExpires' => $disableSignatureExpires
706 * Validates the 'enableSignature' action.
708 public function validateEnableSignature() {
709 WCF
::getSession()->checkPermissions(['admin.user.canDisableSignature']);
711 $this->__validateAccessibleGroups();
713 if (empty($this->objects
)) {
714 $this->readObjects();
716 if (empty($this->objects
)) {
717 throw new UserInputException('objectIDs');
723 * Enables the signature of the handled users.
725 public function enableSignature() {
726 if (empty($this->objects
)) {
727 $this->readObjects();
730 foreach ($this->getObjects() as $userEditor) {
731 $userEditor->update([
732 'disableSignature' => 0
738 * Validates the 'disableAvatar' action.
740 public function validateDisableAvatar() {
741 $this->validateEnableAvatar();
743 $this->readString('disableAvatarReason', true);
744 $this->readString('disableAvatarExpires', true);
748 * Disables the avatar of the handled users.
750 public function disableAvatar() {
751 if (empty($this->objects
)) {
752 $this->readObjects();
755 $disableAvatarExpires = $this->parameters
['disableAvatarExpires'];
756 if ($disableAvatarExpires) {
757 $disableAvatarExpires = strtotime($disableAvatarExpires);
760 $disableAvatarExpires = 0;
763 foreach ($this->getObjects() as $userEditor) {
764 $userEditor->update([
765 'disableAvatar' => 1,
766 'disableAvatarReason' => $this->parameters
['disableAvatarReason'],
767 'disableAvatarExpires' => $disableAvatarExpires
773 * Validates the 'disableCoverPhoto' action.
777 public function validateDisableCoverPhoto() {
778 $this->validateEnableCoverPhoto();
780 $this->readString('disableCoverPhotoReason', true);
781 $this->readString('disableCoverPhotoExpires', true);
785 * Disables the cover photo of the handled users.
789 public function disableCoverPhoto() {
790 if (empty($this->objects
)) {
791 $this->readObjects();
794 $disableCoverPhotoExpires = $this->parameters
['disableCoverPhotoExpires'];
795 if ($disableCoverPhotoExpires) {
796 $disableCoverPhotoExpires = strtotime($disableCoverPhotoExpires);
799 $disableCoverPhotoExpires = 0;
802 foreach ($this->getObjects() as $userEditor) {
803 $userEditor->update([
804 'disableCoverPhoto' => 1,
805 'disableCoverPhotoReason' => $this->parameters
['disableCoverPhotoReason'],
806 'disableCoverPhotoExpires' => $disableCoverPhotoExpires
812 * Validates the 'enableAvatar' action.
814 public function validateEnableAvatar() {
815 WCF
::getSession()->checkPermissions(['admin.user.canDisableAvatar']);
817 $this->__validateAccessibleGroups();
819 if (empty($this->objects
)) {
820 $this->readObjects();
822 if (empty($this->objects
)) {
823 throw new UserInputException('objectIDs');
829 * Enables the avatar of the handled users.
831 public function enableAvatar() {
832 if (empty($this->objects
)) {
833 $this->readObjects();
836 foreach ($this->getObjects() as $userEditor) {
837 $userEditor->update([
844 * Validates the 'enableCoverPhoto' action.
848 public function validateEnableCoverPhoto() {
849 WCF
::getSession()->checkPermissions(['admin.user.canDisableCoverPhoto']);
851 $this->__validateAccessibleGroups();
853 if (empty($this->objects
)) {
854 $this->readObjects();
856 if (empty($this->objects
)) {
857 throw new UserInputException('objectIDs');
863 * Enables the cover photo of the handled users.
867 public function enableCoverPhoto() {
868 if (empty($this->objects
)) {
869 $this->readObjects();
872 foreach ($this->getObjects() as $userEditor) {
873 $userEditor->update([
874 'disableCoverPhoto' => 0
880 * Returns the remove content dialog.
885 public function prepareRemoveContent() {
886 $knownContentProvider = array_map(function ($contentProvider) {
887 return $contentProvider->objectType
;
888 }, array_filter(ObjectTypeCache
::getInstance()->getObjectTypes('com.woltlab.wcf.content.userContentProvider'), function ($contentProvider) {
889 return !$contentProvider->hidden
;
893 'template' => WCF
::getTPL()->fetch('removeUserContentDialog', 'wcf', [
894 'knownContentProvider' => $knownContentProvider,
895 'userID' => $this->parameters
['userID'],
896 'user' => $this->parameters
['user']
902 * Validates the prepareRemoveContent method.
906 public function validatePrepareRemoveContent() {
907 if (!isset($this->parameters
['userID'])) {
908 throw new \
InvalidArgumentException("userID missing");
911 $this->parameters
['user'] = new User($this->parameters
['userID']);
913 if ($this->parameters
['user']->userID
&& !$this->parameters
['user']->canEdit()) {
914 throw new PermissionDeniedException();
919 * Validates parameters to retrieve the social network privacy settings.
922 public function validateGetSocialNetworkPrivacySettings() {
927 * Returns the social network privacy settings.
930 public function getSocialNetworkPrivacySettings() {
935 * Validates the 'saveSocialNetworkPrivacySettings' action.
938 public function validateSaveSocialNetworkPrivacySettings() {
943 * Saves the social network privacy settings.
946 public function saveSocialNetworkPrivacySettings() {
951 * Validates the 'resendActivationMail' action.
952 * @throws UserInputException
955 public function validateResendActivationMail() {
956 $this->readObjects();
958 if (!WCF
::getSession()->getPermission('admin.user.canEnableUser')) {
959 throw new PermissionDeniedException();
962 if (REGISTER_ACTIVATION_METHOD
!= 1) {
963 throw new IllegalLinkException();
966 foreach ($this->objects
as $object) {
967 if (!$object->activationCode
) {
968 throw new UserInputException('objectIDs');
974 * Triggers a new activation email.
977 public function resendActivationMail() {
978 // update every selected user's activation code
979 foreach ($this->objects
as $object) {
980 $action = new UserAction([$object], 'update', [
982 'activationCode' => UserRegistrationUtil
::getActivationCode()
985 $action->executeAction();
989 // get fresh user list with updated user objects
990 $newUserList = new UserList();
991 $newUserList->getConditionBuilder()->add('user_table.userID IN (?)', [$this->objectIDs
]);
992 $newUserList->readObjects();
993 foreach ($newUserList->getObjects() as $object) {
994 $email = new Email();
995 $email->addRecipient(new UserMailbox($object));
996 $email->setSubject($object->getLanguage()->getDynamicVariable('wcf.user.register.needActivation.mail.subject'));
997 $email->setBody(new MimePartFacade([
998 new RecipientAwareTextMimePart('text/html', 'email_registerNeedActivation'),
999 new RecipientAwareTextMimePart('text/plain', 'email_registerNeedActivation')
1004 $this->unmarkItems($this->objectIDs
);