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\cache\builder\UserNotificationEventCacheBuilder
;
10 use wcf\system\clipboard\ClipboardHandler
;
11 use wcf\system\database\util\PreparedStatementConditionBuilder
;
12 use wcf\system\exception\PermissionDeniedException
;
13 use wcf\system\exception\UserInputException
;
15 use wcf\util\StringUtil
;
16 use wcf\util\UserRegistrationUtil
;
19 * Executes user-related actions.
21 * @author Alexander Ebert
22 * @copyright 2001-2013 WoltLab GmbH
23 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
24 * @package com.woltlab.wcf
25 * @subpackage data.user
26 * @category Community Framework
28 class UserAction
extends AbstractDatabaseObjectAction
implements IClipboardAction
, ISearchAction
{
30 * @see wcf\data\AbstractDatabaseObjectAction::$className
32 public $className = 'wcf\data\user\UserEditor';
35 * @see wcf\data\AbstractDatabaseObjectAction::$allowGuestAccess
37 protected $allowGuestAccess = array('getSearchResultList');
40 * @see wcf\data\AbstractDatabaseObjectAction::$permissionsCreate
42 protected $permissionsCreate = array('admin.user.canAddUser');
45 * @see wcf\data\AbstractDatabaseObjectAction::$permissionsDelete
47 protected $permissionsDelete = array('admin.user.canDeleteUser');
50 * @see wcf\data\AbstractDatabaseObjectAction::$permissionsUpdate
52 protected $permissionsUpdate = array('admin.user.canEditUser');
55 * Validates permissions and parameters.
57 public function validateCreate() {
58 $this->readString('password', false, 'data');
62 * Validates accessible groups.
64 * @param boolean $ignoreOwnUser
66 protected function __validateAccessibleGroups($ignoreOwnUser = true) {
68 if (in_array(WCF
::getUser()->userID
, $this->objectIDs
)) {
69 unset($this->objectIDs
[array_search(WCF
::getUser()->userID
, $this->objectIDs
)]);
70 if (isset($this->objects
[WCF
::getUser()->userID
])) {
71 unset($this->objects
[WCF
::getUser()->userID
]);
76 // list might be empty because only our own user id was given
77 if (empty($this->objectIDs
)) {
78 throw new UserInputException('objectIDs');
82 $conditions = new PreparedStatementConditionBuilder();
83 $conditions->add("userID IN (?)", array($this->objectIDs
));
85 $sql = "SELECT DISTINCT groupID
86 FROM wcf".WCF_N
."_user_to_group
88 $statement = WCF
::getDB()->prepareStatement($sql);
89 $statement->execute($conditions->getParameters());
92 while ($row = $statement->fetchArray()) {
93 $groupIDs[] = $row['groupID'];
96 if (!UserGroup
::isAccessibleGroup($groupIDs)) {
97 throw new PermissionDeniedException();
102 * Validates permissions and parameters.
104 public function validateDelete() {
105 // read and validate user objects
106 parent
::validateDelete();
108 $this->__validateAccessibleGroups();
112 * @see wcf\data\IDeleteAction::delete()
114 public function delete() {
115 if (empty($this->objects
)) {
116 $this->readObjects();
120 $avatarIDs = array();
121 foreach ($this->objects
as $user) {
122 if ($user->avatarID
) $avatarIDs[] = $user->avatarID
;
124 if (!empty($avatarIDs)) {
125 $action = new UserAvatarAction($avatarIDs, 'delete');
126 $action->executeAction();
129 // delete profile comments
130 if (!empty($this->objectIDs
)) {
131 $objectType = ObjectTypeCache
::getInstance()->getObjectTypeByName('com.woltlab.wcf.comment.commentableContent', 'com.woltlab.wcf.user.profileComment');
132 $conditionBuilder = new PreparedStatementConditionBuilder();
133 $conditionBuilder->add('objectTypeID = ?', array($objectType->objectTypeID
));
134 $conditionBuilder->add('objectID IN (?)', array($this->objectIDs
));
136 $sql = "DELETE FROM wcf".WCF_N
."_comment
138 $statement = WCF
::getDB()->prepareStatement($sql);
139 $statement->execute($conditionBuilder->getParameters());
142 $returnValue = parent
::delete();
148 * Validates permissions and parameters.
150 public function validateUpdate() {
152 if (empty($this->objects
)) {
153 $this->readObjects();
155 if (empty($this->objects
)) {
156 throw new UserInputException('objectIDs');
161 WCF
::getSession()->checkPermissions($this->permissionsUpdate
);
163 catch (PermissionDeniedException
$e) {
164 // check if we're editing ourselves
165 if (count($this->objects
) == 1 && ($this->objects
[0]->userID
== WCF
::getUser()->userID
)) {
166 $count = count($this->parameters
);
167 if ($count > 1 ||
($count == 1 && !isset($this->parameters
['options']))) {
168 throw new PermissionDeniedException();
172 throw new PermissionDeniedException();
177 * Validates the ban action.
179 public function validateBan() {
180 WCF
::getSession()->checkPermissions(array('admin.user.canBanUser'));
182 $this->__validateAccessibleGroups();
186 * Validates the unban action.
188 public function validateUnban() {
189 $this->validateBan();
195 public function ban() {
196 $conditionBuilder = new PreparedStatementConditionBuilder();
197 $conditionBuilder->add('userID IN (?)', array($this->objectIDs
));
198 $sql = "UPDATE wcf".WCF_N
."_user
202 $statement = WCF
::getDB()->prepareStatement($sql);
204 array_merge(array(1, $this->parameters
['banReason']), $conditionBuilder->getParameters())
207 $this->unmarkItems();
213 public function unban() {
214 $conditionBuilder = new PreparedStatementConditionBuilder();
215 $conditionBuilder->add('userID IN (?)', array($this->objectIDs
));
216 $sql = "UPDATE wcf".WCF_N
."_user
219 $statement = WCF
::getDB()->prepareStatement($sql);
220 $statement->execute($conditionBuilder->getParameters());
224 * Creates a new user.
228 public function create() {
229 $user = parent
::create();
230 $userEditor = new UserEditor($user);
232 // updates user options
233 if (isset($this->parameters
['options'])) {
234 $userEditor->updateUserOptions($this->parameters
['options']);
237 // insert user groups
238 $addDefaultGroups = (isset($this->parameters
['addDefaultGroups'])) ?
$this->parameters
['addDefaultGroups'] : true;
239 $groupIDs = (isset($this->parameters
['groups'])) ?
$this->parameters
['groups'] : array();
240 $userEditor->addToGroups($groupIDs, false, $addDefaultGroups);
242 // insert visible languages
243 $languageIDs = (isset($this->parameters
['languages'])) ?
$this->parameters
['languages'] : array();
244 $userEditor->addToLanguages($languageIDs);
247 // set default notifications
248 $sql = "INSERT INTO wcf".WCF_N
."_user_notification_event_to_user
251 $statement = WCF
::getDB()->prepareStatement($sql);
252 foreach (UserNotificationEventCacheBuilder
::getInstance()->getData() as $events) {
253 foreach ($events as $event) {
254 if ($event->preset
) {
255 $statement->execute(array($user->userID
, $event->eventID
));
265 * @see wcf\data\AbstractDatabaseObjectAction::update()
267 public function update() {
268 if (isset($this->parameters
['data'])) {
271 if (isset($this->parameters
['data']['languageID'])) {
272 foreach ($this->objects
as $object) {
273 if ($object->userID
== WCF
::getUser()->userID
) {
274 if ($this->parameters
['data']['languageID'] != WCF
::getUser()->languageID
) {
275 WCF
::setLanguage($this->parameters
['data']['languageID']);
284 if (empty($this->objects
)) {
285 $this->readObjects();
289 $groupIDs = (isset($this->parameters
['groups'])) ?
$this->parameters
['groups'] : array();
290 $languageIDs = (isset($this->parameters
['languageIDs'])) ?
$this->parameters
['languageIDs'] : array();
291 $removeGroups = (isset($this->parameters
['removeGroups'])) ?
$this->parameters
['removeGroups'] : array();
292 $userOptions = (isset($this->parameters
['options'])) ?
$this->parameters
['options'] : array();
294 if (!empty($groupIDs)) {
295 $action = new UserAction($this->objects
, 'addToGroups', array('groups' => $groupIDs));
296 $action->executeAction();
299 foreach ($this->objects
as $userEditor) {
300 if (!empty($removeGroups)) {
301 $userEditor->removeFromGroups($removeGroups);
304 if (!empty($userOptions)) {
305 $userEditor->updateUserOptions($userOptions);
308 if (!empty($languageIDs)) {
309 $userEditor->addToLanguages($languageIDs);
315 * Add users to given groups.
317 public function addToGroups() {
318 if (empty($this->objects
)) {
319 $this->readObjects();
322 $groupIDs = $this->parameters
['groups'];
323 $deleteOldGroups = $addDefaultGroups = true;
324 if (isset($this->parameters
['deleteOldGroups'])) $deleteOldGroups = $this->parameters
['deleteOldGroups'];
325 if (isset($this->parameters
['addDefaultGroups'])) $addDefaultGroups = $this->parameters
['addDefaultGroups'];
327 foreach ($this->objects
as $userEditor) {
328 $userEditor->addToGroups($groupIDs, $deleteOldGroups, $addDefaultGroups);
331 if (MODULE_USER_RANK
) {
332 $action = new UserProfileAction($this->objects
, 'updateUserRank');
333 $action->executeAction();
335 if (MODULE_USERS_ONLINE
) {
336 $action = new UserProfileAction($this->objects
, 'updateUserOnlineMarking');
337 $action->executeAction();
342 * @see wcf\data\ISearchAction::validateGetSearchResultList()
344 public function validateGetSearchResultList() {
345 $this->readBoolean('includeUserGroups', false, 'data');
346 $this->readString('searchString', false, 'data');
348 if (isset($this->parameters
['data']['excludedSearchValues']) && !is_array($this->parameters
['data']['excludedSearchValues'])) {
349 throw new UserInputException('excludedSearchValues');
354 * @see wcf\data\ISearchAction::getSearchResultList()
356 public function getSearchResultList() {
357 $searchString = $this->parameters
['data']['searchString'];
358 $excludedSearchValues = array();
359 if (isset($this->parameters
['data']['excludedSearchValues'])) {
360 $excludedSearchValues = $this->parameters
['data']['excludedSearchValues'];
364 if ($this->parameters
['data']['includeUserGroups']) {
365 $accessibleGroups = UserGroup
::getAccessibleGroups();
366 foreach ($accessibleGroups as $group) {
367 $groupName = $group->getName();
368 if (!in_array($groupName, $excludedSearchValues)) {
369 $pos = StringUtil
::indexOfIgnoreCase($groupName, $searchString);
370 if ($pos !== false && $pos == 0) {
372 'label' => $groupName,
373 'objectID' => $group->groupID
,
381 $conditionBuilder = new PreparedStatementConditionBuilder();
382 $conditionBuilder->add("username LIKE ?", array($searchString.'%'));
383 if (!empty($excludedSearchValues)) {
384 $conditionBuilder->add("username NOT IN (?)", array($excludedSearchValues));
388 $sql = "SELECT userID, username
389 FROM wcf".WCF_N
."_user
391 $statement = WCF
::getDB()->prepareStatement($sql, 10);
392 $statement->execute($conditionBuilder->getParameters());
393 while ($row = $statement->fetchArray()) {
395 'label' => $row['username'],
396 'objectID' => $row['userID'],
405 * @see wcf\data\IClipboardAction::validateUnmarkAll()
407 public function validateUnmarkAll() {
412 * @see wcf\data\IClipboardAction::unmarkAll()
414 public function unmarkAll() {
415 ClipboardHandler
::getInstance()->removeItems(ClipboardHandler
::getInstance()->getObjectTypeID('com.woltlab.wcf.user'));
421 * @param array<integer> $userIDs
423 protected function unmarkItems(array $userIDs = array()) {
424 if (empty($userIDs)) {
425 $userIDs = $this->objectIDs
;
428 if (!empty($userIDs)) {
429 ClipboardHandler
::getInstance()->unmark($userIDs, ClipboardHandler
::getInstance()->getObjectTypeID('com.woltlab.wcf.user'));
434 * Validates the enable action.
436 public function validateEnable() {
437 WCF
::getSession()->checkPermissions(array('admin.user.canEnableUser'));
441 * Validates the disable action.
443 public function validateDisable() {
444 $this->validateEnable();
450 public function enable() {
451 if (empty($this->objects
)) $this->readObjects();
453 $action = new UserAction($this->objects
, 'update', array(
455 'activationCode' => 0
457 'removeGroups' => UserGroup
::getGroupIDsByType(array(UserGroup
::GUESTS
))
459 $action->executeAction();
460 $action = new UserAction($this->objects
, 'addToGroups', array(
461 'groups' => UserGroup
::getGroupIDsByType(array(UserGroup
::USERS
)),
462 'deleteOldGroups' => false,
463 'addDefaultGroups' => false
465 $action->executeAction();
471 public function disable() {
472 if (empty($this->objects
)) $this->readObjects();
474 $action = new UserAction($this->objects
, 'update', array(
476 'activationCode' => UserRegistrationUtil
::getActivationCode()
478 'removeGroups' => UserGroup
::getGroupIDsByType(array(UserGroup
::USERS
)),
480 $action->executeAction();
481 $action = new UserAction($this->objects
, 'addToGroups', array(
482 'groups' => UserGroup
::getGroupIDsByType(array(UserGroup
::GUESTS
)),
483 'deleteOldGroups' => false,
484 'addDefaultGroups' => false
486 $action->executeAction();