Index: trunk/phase3/docs/hooks.txt |
— | — | @@ -1439,6 +1439,13 @@ |
1440 | 1440 | 'add-self' => array( addablegroups to self ), |
1441 | 1441 | 'remove-self' => array( removable groups from self ) |
1442 | 1442 | ) |
| 1443 | + |
| 1444 | +'UserRightsLogEntry': before a log entry is added by UserrightsPage::addLogEntry(). If you use this hook to add your own log entries, you can return false to prevent the usual log entry from being added |
| 1445 | +$user: User or UserrightsProxy object |
| 1446 | +$oldGroups: Array of groups the user was a member of before the change |
| 1447 | +$newGroups: Array of groups the user is a member of after the change |
| 1448 | +$reason: User-provided summary |
| 1449 | + |
1443 | 1450 | 'UserRetrieveNewTalks': called when retrieving "You have new messages!" message(s) |
1444 | 1451 | $user: user retrieving new talks messages |
1445 | 1452 | $talks: array of new talks page(s) |
Index: trunk/phase3/includes/User.php |
— | — | @@ -3231,8 +3231,116 @@ |
3232 | 3232 | return $text; |
3233 | 3233 | } |
3234 | 3234 | } |
| 3235 | + |
| 3236 | + /** |
| 3237 | + * Returns an array of the groups that a particular group can add/remove. |
| 3238 | + * |
| 3239 | + * @param $group String: the group to check for whether it can add/remove |
| 3240 | + * @return Array array( 'add' => array( addablegroups ), |
| 3241 | + * 'remove' => array( removablegroups ), |
| 3242 | + * 'add-self' => array( addablegroups to self), |
| 3243 | + * 'remove-self' => array( removable groups from self) ) |
| 3244 | + */ |
| 3245 | + static function changeableByGroup( $group ) { |
| 3246 | + global $wgAddGroups, $wgRemoveGroups, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf; |
3235 | 3247 | |
| 3248 | + $groups = array( 'add' => array(), 'remove' => array(), 'add-self' => array(), 'remove-self' => array() ); |
| 3249 | + if( empty($wgAddGroups[$group]) ) { |
| 3250 | + // Don't add anything to $groups |
| 3251 | + } elseif( $wgAddGroups[$group] === true ) { |
| 3252 | + // You get everything |
| 3253 | + $groups['add'] = self::getAllGroups(); |
| 3254 | + } elseif( is_array($wgAddGroups[$group]) ) { |
| 3255 | + $groups['add'] = $wgAddGroups[$group]; |
| 3256 | + } |
| 3257 | + |
| 3258 | + // Same thing for remove |
| 3259 | + if( empty($wgRemoveGroups[$group]) ) { |
| 3260 | + } elseif($wgRemoveGroups[$group] === true ) { |
| 3261 | + $groups['remove'] = self::getAllGroups(); |
| 3262 | + } elseif( is_array($wgRemoveGroups[$group]) ) { |
| 3263 | + $groups['remove'] = $wgRemoveGroups[$group]; |
| 3264 | + } |
| 3265 | + |
| 3266 | + // Re-map numeric keys of AddToSelf/RemoveFromSelf to the 'user' key for backwards compatibility |
| 3267 | + if( empty($wgGroupsAddToSelf['user']) || $wgGroupsAddToSelf['user'] !== true ) { |
| 3268 | + foreach($wgGroupsAddToSelf as $key => $value) { |
| 3269 | + if( is_int($key) ) { |
| 3270 | + $wgGroupsAddToSelf['user'][] = $value; |
| 3271 | + } |
| 3272 | + } |
| 3273 | + } |
| 3274 | + |
| 3275 | + if( empty($wgGroupsRemoveFromSelf['user']) || $wgGroupsRemoveFromSelf['user'] !== true ) { |
| 3276 | + foreach($wgGroupsRemoveFromSelf as $key => $value) { |
| 3277 | + if( is_int($key) ) { |
| 3278 | + $wgGroupsRemoveFromSelf['user'][] = $value; |
| 3279 | + } |
| 3280 | + } |
| 3281 | + } |
| 3282 | + |
| 3283 | + // Now figure out what groups the user can add to him/herself |
| 3284 | + if( empty($wgGroupsAddToSelf[$group]) ) { |
| 3285 | + } elseif( $wgGroupsAddToSelf[$group] === true ) { |
| 3286 | + // No idea WHY this would be used, but it's there |
| 3287 | + $groups['add-self'] = User::getAllGroups(); |
| 3288 | + } elseif( is_array($wgGroupsAddToSelf[$group]) ) { |
| 3289 | + $groups['add-self'] = $wgGroupsAddToSelf[$group]; |
| 3290 | + } |
| 3291 | + |
| 3292 | + if( empty($wgGroupsRemoveFromSelf[$group]) ) { |
| 3293 | + } elseif( $wgGroupsRemoveFromSelf[$group] === true ) { |
| 3294 | + $groups['remove-self'] = User::getAllGroups(); |
| 3295 | + } elseif( is_array($wgGroupsRemoveFromSelf[$group]) ) { |
| 3296 | + $groups['remove-self'] = $wgGroupsRemoveFromSelf[$group]; |
| 3297 | + } |
| 3298 | + |
| 3299 | + return $groups; |
| 3300 | + } |
| 3301 | + |
3236 | 3302 | /** |
| 3303 | + * Returns an array of groups that this user can add and remove |
| 3304 | + * @return Array array( 'add' => array( addablegroups ), |
| 3305 | + * 'remove' => array( removablegroups ), |
| 3306 | + * 'add-self' => array( addablegroups to self), |
| 3307 | + * 'remove-self' => array( removable groups from self) ) |
| 3308 | + */ |
| 3309 | + function changeableGroups() { |
| 3310 | + if( $this->isAllowed( 'userrights' ) ) { |
| 3311 | + // This group gives the right to modify everything (reverse- |
| 3312 | + // compatibility with old "userrights lets you change |
| 3313 | + // everything") |
| 3314 | + // Using array_merge to make the groups reindexed |
| 3315 | + $all = array_merge( User::getAllGroups() ); |
| 3316 | + return array( |
| 3317 | + 'add' => $all, |
| 3318 | + 'remove' => $all, |
| 3319 | + 'add-self' => array(), |
| 3320 | + 'remove-self' => array() |
| 3321 | + ); |
| 3322 | + } |
| 3323 | + |
| 3324 | + // Okay, it's not so simple, we will have to go through the arrays |
| 3325 | + $groups = array( |
| 3326 | + 'add' => array(), |
| 3327 | + 'remove' => array(), |
| 3328 | + 'add-self' => array(), |
| 3329 | + 'remove-self' => array() ); |
| 3330 | + $addergroups = $this->getEffectiveGroups(); |
| 3331 | + |
| 3332 | + foreach ($addergroups as $addergroup) { |
| 3333 | + $groups = array_merge_recursive( |
| 3334 | + $groups, $this->changeableByGroup($addergroup) |
| 3335 | + ); |
| 3336 | + $groups['add'] = array_unique( $groups['add'] ); |
| 3337 | + $groups['remove'] = array_unique( $groups['remove'] ); |
| 3338 | + $groups['add-self'] = array_unique( $groups['add-self'] ); |
| 3339 | + $groups['remove-self'] = array_unique( $groups['remove-self'] ); |
| 3340 | + } |
| 3341 | + return $groups; |
| 3342 | + } |
| 3343 | + |
| 3344 | + /** |
3237 | 3345 | * Increment the user's edit-count field. |
3238 | 3346 | * Will have no effect for anonymous users. |
3239 | 3347 | */ |
Index: trunk/phase3/includes/api/ApiQueryRecentChanges.php |
— | — | @@ -43,12 +43,13 @@ |
44 | 44 | private $fld_comment = false, $fld_user = false, $fld_flags = false, |
45 | 45 | $fld_timestamp = false, $fld_title = false, $fld_ids = false, |
46 | 46 | $fld_sizes = false; |
47 | | - |
| 47 | + /** |
| 48 | + * Get an array mapping token names to their handler functions. |
| 49 | + * The prototype for a token function is func($pageid, $title, $rc) |
| 50 | + * it should return a token or false (permission denied) |
| 51 | + * @return array(tokenname => function) |
| 52 | + */ |
48 | 53 | protected function getTokenFunctions() { |
49 | | - // tokenname => function |
50 | | - // function prototype is func($pageid, $title, $rev) |
51 | | - // should return token or false |
52 | | - |
53 | 54 | // Don't call the hooks twice |
54 | 55 | if(isset($this->tokenFunctions)) |
55 | 56 | return $this->tokenFunctions; |
Index: trunk/phase3/includes/api/ApiUserrights.php |
— | — | @@ -0,0 +1,117 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/* |
| 5 | + * Created on Mar 24, 2009 |
| 6 | + * API for MediaWiki 1.8+ |
| 7 | + * |
| 8 | + * Copyright (C) 2009 Roan Kattouw <Firstname>.<Lastname>@home.nl |
| 9 | + * |
| 10 | + * This program is free software; you can redistribute it and/or modify |
| 11 | + * it under the terms of the GNU General Public License as published by |
| 12 | + * the Free Software Foundation; either version 2 of the License, or |
| 13 | + * (at your option) any later version. |
| 14 | + * |
| 15 | + * This program is distributed in the hope that it will be useful, |
| 16 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | + * GNU General Public License for more details. |
| 19 | + * |
| 20 | + * You should have received a copy of the GNU General Public License along |
| 21 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 22 | + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 23 | + * http://www.gnu.org/copyleft/gpl.html |
| 24 | + */ |
| 25 | + |
| 26 | +if (!defined('MEDIAWIKI')) { |
| 27 | + // Eclipse helper - will be ignored in production |
| 28 | + require_once ("ApiBase.php"); |
| 29 | +} |
| 30 | + |
| 31 | + |
| 32 | +/** |
| 33 | + * @ingroup API |
| 34 | + */ |
| 35 | +class ApiUserrights extends ApiBase { |
| 36 | + |
| 37 | + public function __construct($main, $action) { |
| 38 | + parent :: __construct($main, $action); |
| 39 | + } |
| 40 | + |
| 41 | + public function execute() { |
| 42 | + global $wgUser; |
| 43 | + $params = $this->extractRequestParams(); |
| 44 | + if(is_null($params['user'])) |
| 45 | + $this->dieUsageMsg(array('missingparam', 'user')); |
| 46 | + $user = User::newFromName($params['user']); |
| 47 | + if($user->isAnon()) |
| 48 | + $this->dieUsageMsg(array('nosuchuser', $params['user'])); |
| 49 | + if(is_null($params['token'])) |
| 50 | + $this->dieUsageMsg(array('missingparam', 'token')); |
| 51 | + if(!$wgUser->matchEditToken($params['token'], $user->getName())) |
| 52 | + $this->dieUsageMsg(array('sessionfailure')); |
| 53 | + |
| 54 | + $r['user'] = $user->getName(); |
| 55 | + list($r['added'], $r['removed']) = |
| 56 | + UserrightsPage::doSaveUserGroups( |
| 57 | + $user, (array)$params['add'], |
| 58 | + (array)$params['remove'], $params['reason']); |
| 59 | + |
| 60 | + $this->getResult()->setIndexedTagName($r['added'], 'group'); |
| 61 | + $this->getResult()->setIndexedTagName($r['removed'], 'group'); |
| 62 | + $this->getResult()->addValue(null, $this->getModuleName(), $r); |
| 63 | + } |
| 64 | + |
| 65 | + public function mustBePosted() { |
| 66 | + return true; |
| 67 | + } |
| 68 | + |
| 69 | + public function isWriteMode() { |
| 70 | + return true; |
| 71 | + } |
| 72 | + |
| 73 | + public function getAllowedParams() { |
| 74 | + return array ( |
| 75 | + 'user' => array( |
| 76 | + ApiBase :: PARAM_TYPE => 'user' |
| 77 | + ), |
| 78 | + 'add' => array( |
| 79 | + ApiBase :: PARAM_TYPE => User::getAllGroups(), |
| 80 | + ApiBase :: PARAM_ISMULTI => true |
| 81 | + ), |
| 82 | + 'remove' => array( |
| 83 | + ApiBase :: PARAM_TYPE => User::getAllGroups(), |
| 84 | + ApiBase :: PARAM_ISMULTI => true |
| 85 | + ), |
| 86 | + 'token' => null, |
| 87 | + 'reason' => array( |
| 88 | + ApiBase :: PARAM_DFLT => '' |
| 89 | + ) |
| 90 | + ); |
| 91 | + } |
| 92 | + |
| 93 | + public function getParamDescription() { |
| 94 | + return array ( |
| 95 | + 'user' => 'User name', |
| 96 | + 'add' => 'Add the user to these groups', |
| 97 | + 'remove' => 'Remove the user from these groups', |
| 98 | + 'token' => 'A userrights token previously retrieved through list=users', |
| 99 | + 'reason' => 'Reason for the change', |
| 100 | + ); |
| 101 | + } |
| 102 | + |
| 103 | + public function getDescription() { |
| 104 | + return array( |
| 105 | + 'Add/remove a user to/from groups', |
| 106 | + ); |
| 107 | + } |
| 108 | + |
| 109 | + protected function getExamples() { |
| 110 | + return array ( |
| 111 | + 'api.php?action=userrights&user=FooBot&add=bot&remove=sysop|bureaucrat&token=123ABC' |
| 112 | + ); |
| 113 | + } |
| 114 | + |
| 115 | + public function getVersion() { |
| 116 | + return __CLASS__ . ': $Id$'; |
| 117 | + } |
| 118 | +} |
Property changes on: trunk/phase3/includes/api/ApiUserrights.php |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 119 | + native |
Name: svn:keywords |
2 | 120 | + Id |
Index: trunk/phase3/includes/api/ApiMain.php |
— | — | @@ -80,6 +80,7 @@ |
81 | 81 | 'watch' => 'ApiWatch', |
82 | 82 | 'patrol' => 'ApiPatrol', |
83 | 83 | 'import' => 'ApiImport', |
| 84 | + 'userrights' => 'ApiUserrights', |
84 | 85 | ); |
85 | 86 | |
86 | 87 | /** |
Index: trunk/phase3/includes/api/ApiQueryUsers.php |
— | — | @@ -39,7 +39,37 @@ |
40 | 40 | public function __construct($query, $moduleName) { |
41 | 41 | parent :: __construct($query, $moduleName, 'us'); |
42 | 42 | } |
| 43 | + |
| 44 | + /** |
| 45 | + * Get an array mapping token names to their handler functions. |
| 46 | + * The prototype for a token function is func($user) |
| 47 | + * it should return a token or false (permission denied) |
| 48 | + * @return array(tokenname => function) |
| 49 | + */ |
| 50 | + protected function getTokenFunctions() { |
| 51 | + // Don't call the hooks twice |
| 52 | + if(isset($this->tokenFunctions)) |
| 53 | + return $this->tokenFunctions; |
43 | 54 | |
| 55 | + // If we're in JSON callback mode, no tokens can be obtained |
| 56 | + if(!is_null($this->getMain()->getRequest()->getVal('callback'))) |
| 57 | + return array(); |
| 58 | + |
| 59 | + $this->tokenFunctions = array( |
| 60 | + 'userrights' => array( 'ApiQueryUsers', 'getUserrightsToken' ), |
| 61 | + ); |
| 62 | + wfRunHooks('APIQueryUsersTokens', array(&$this->tokenFunctions)); |
| 63 | + return $this->tokenFunctions; |
| 64 | + } |
| 65 | + |
| 66 | + public static function getUserrightsToken($user) |
| 67 | + { |
| 68 | + global $wgUser; |
| 69 | + // Since the permissions check for userrights is non-trivial, |
| 70 | + // don't bother with it here |
| 71 | + return $wgUser->editToken($user->getName()); |
| 72 | + } |
| 73 | + |
44 | 74 | public function execute() { |
45 | 75 | $params = $this->extractRequestParams(); |
46 | 76 | $result = $this->getResult(); |
— | — | @@ -115,6 +145,18 @@ |
116 | 146 | } |
117 | 147 | if(isset($this->prop['emailable']) && $user->canReceiveEmail()) |
118 | 148 | $data[$name]['emailable'] = ''; |
| 149 | + if(!is_null($params['token'])) |
| 150 | + { |
| 151 | + $tokenFunctions = $this->getTokenFunctions(); |
| 152 | + foreach($params['token'] as $t) |
| 153 | + { |
| 154 | + $val = call_user_func($tokenFunctions[$t], $user); |
| 155 | + if($val === false) |
| 156 | + $this->setWarning("Action '$t' is not allowed for the current user"); |
| 157 | + else |
| 158 | + $data[$name][$t . 'token'] = $val; |
| 159 | + } |
| 160 | + } |
119 | 161 | } |
120 | 162 | } |
121 | 163 | // Second pass: add result data to $retval |
— | — | @@ -153,7 +195,11 @@ |
154 | 196 | ), |
155 | 197 | 'users' => array( |
156 | 198 | ApiBase :: PARAM_ISMULTI => true |
157 | | - ) |
| 199 | + ), |
| 200 | + 'token' => array( |
| 201 | + ApiBase :: PARAM_TYPE => array_keys($this->getTokenFunctions()), |
| 202 | + ApiBase :: PARAM_ISMULTI => true |
| 203 | + ), |
158 | 204 | ); |
159 | 205 | } |
160 | 206 | |
— | — | @@ -167,7 +213,8 @@ |
168 | 214 | ' registration - adds the user\'s registration timestamp', |
169 | 215 | ' emailable - tags if the user can and wants to receive e-mail through [[Special:Emailuser]]', |
170 | 216 | ), |
171 | | - 'users' => 'A list of users to obtain the same information for' |
| 217 | + 'users' => 'A list of users to obtain the same information for', |
| 218 | + 'token' => 'Which tokens to obtain for each user', |
172 | 219 | ); |
173 | 220 | } |
174 | 221 | |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -292,6 +292,7 @@ |
293 | 293 | 'ApiRollback' => 'includes/api/ApiRollback.php', |
294 | 294 | 'ApiUnblock' => 'includes/api/ApiUnblock.php', |
295 | 295 | 'ApiUndelete' => 'includes/api/ApiUndelete.php', |
| 296 | + 'ApiUserrights' => 'includes/api/ApiUserrights.php', |
296 | 297 | 'ApiWatch' => 'includes/api/ApiWatch.php', |
297 | 298 | 'Services_JSON' => 'includes/api/ApiFormatJson_json.php', |
298 | 299 | 'Services_JSON_Error' => 'includes/api/ApiFormatJson_json.php', |
Index: trunk/phase3/includes/specials/SpecialUserrights.php |
— | — | @@ -149,29 +149,46 @@ |
150 | 150 | $removegroup[] = $group; |
151 | 151 | } |
152 | 152 | } |
| 153 | + self::doSaveUserGroups( $user, $addgroup, $removegroup, $reason ); |
| 154 | + } |
| 155 | + |
| 156 | + /** |
| 157 | + * Save user groups changes in the database. |
| 158 | + * |
| 159 | + * @param $user User object |
| 160 | + * @param $add Array of groups to add |
| 161 | + * @param $remove Array of groups to remove |
| 162 | + * @param $reason String: reason for group change |
| 163 | + * @return Array: Tuple of added, then removed groups |
| 164 | + */ |
| 165 | + static function doSaveUserGroups( $user, $add, $remove, $reason = '' ) { |
| 166 | + global $wgUser; |
153 | 167 | |
154 | 168 | // Validate input set... |
155 | | - $changeable = $this->changeableGroups(); |
156 | | - $addable = array_merge( $changeable['add'], $this->isself ? $changeable['add-self'] : array() ); |
157 | | - $removable = array_merge( $changeable['remove'], $this->isself ? $changeable['remove-self'] : array() ); |
| 169 | + $isself = ($user->getName() == $wgUser->getName()); |
| 170 | + $groups = $user->getGroups(); |
| 171 | + $changeable = $wgUser->changeableGroups(); |
| 172 | + $addable = array_merge( $changeable['add'], $isself ? $changeable['add-self'] : array() ); |
| 173 | + $removable = array_merge( $changeable['remove'], $isself ? $changeable['remove-self'] : array() ); |
158 | 174 | |
159 | | - $removegroup = array_unique( |
160 | | - array_intersect( (array)$removegroup, $removable ) ); |
161 | | - $addgroup = array_unique( |
162 | | - array_intersect( (array)$addgroup, $addable ) ); |
| 175 | + $remove = array_unique( |
| 176 | + array_intersect( (array)$remove, $removable, $groups ) ); |
| 177 | + $add = array_unique( array_diff( |
| 178 | + array_intersect( (array)$add, $addable ), |
| 179 | + $groups ) ); |
163 | 180 | |
164 | 181 | $oldGroups = $user->getGroups(); |
165 | 182 | $newGroups = $oldGroups; |
166 | 183 | // remove then add groups |
167 | | - if( $removegroup ) { |
168 | | - $newGroups = array_diff($newGroups, $removegroup); |
169 | | - foreach( $removegroup as $group ) { |
| 184 | + if( $remove ) { |
| 185 | + $newGroups = array_diff($newGroups, $remove); |
| 186 | + foreach( $remove as $group ) { |
170 | 187 | $user->removeGroup( $group ); |
171 | 188 | } |
172 | 189 | } |
173 | | - if( $addgroup ) { |
174 | | - $newGroups = array_merge($newGroups, $addgroup); |
175 | | - foreach( $addgroup as $group ) { |
| 190 | + if( $add ) { |
| 191 | + $newGroups = array_merge($newGroups, $add); |
| 192 | + foreach( $add as $group ) { |
176 | 193 | $user->addGroup( $group ); |
177 | 194 | } |
178 | 195 | } |
— | — | @@ -182,29 +199,34 @@ |
183 | 200 | |
184 | 201 | wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) ); |
185 | 202 | wfDebug( 'newGroups: ' . print_r( $newGroups, true ) ); |
186 | | - if( $user instanceof User ) { |
187 | | - // hmmm |
188 | | - wfRunHooks( 'UserRights', array( &$user, $addgroup, $removegroup ) ); |
189 | | - } |
| 203 | + wfRunHooks( 'UserRights', array( &$user, $add, $remove ) ); |
190 | 204 | |
191 | 205 | if( $newGroups != $oldGroups ) { |
192 | | - $this->addLogEntry( $user, $oldGroups, $newGroups ); |
| 206 | + self::addLogEntry( $user, $oldGroups, $newGroups, $reason ); |
193 | 207 | } |
| 208 | + return array( $add, $remove ); |
194 | 209 | } |
| 210 | + |
195 | 211 | |
196 | 212 | /** |
197 | 213 | * Add a rights log entry for an action. |
198 | 214 | */ |
199 | | - function addLogEntry( $user, $oldGroups, $newGroups ) { |
200 | | - global $wgRequest; |
| 215 | + static function addLogEntry( $user, $oldGroups, $newGroups, $reason ) { |
| 216 | + // Just overriding addLogEntry in a subclass would be cleaner, |
| 217 | + // but that requires PHP 5.3 (late static bindings) |
| 218 | + if( !wfRunHooks( 'UserRightsLogEntry', array( $user, $oldGroups, |
| 219 | + $newGroups, $reason ) ) ) { |
| 220 | + return; |
| 221 | + } |
| 222 | + |
201 | 223 | $log = new LogPage( 'rights' ); |
202 | 224 | |
203 | 225 | $log->addEntry( 'rights', |
204 | 226 | $user->getUserPage(), |
205 | | - $wgRequest->getText( 'user-reason' ), |
| 227 | + $reason, |
206 | 228 | array( |
207 | | - $this->makeGroupNameListForLog( $oldGroups ), |
208 | | - $this->makeGroupNameListForLog( $newGroups ) |
| 229 | + self::makeGroupNameListForLog( $oldGroups ), |
| 230 | + self::makeGroupNameListForLog( $newGroups ) |
209 | 231 | ) |
210 | 232 | ); |
211 | 233 | } |
— | — | @@ -293,7 +315,7 @@ |
294 | 316 | return $user; |
295 | 317 | } |
296 | 318 | |
297 | | - function makeGroupNameList( $ids ) { |
| 319 | + static function makeGroupNameList( $ids ) { |
298 | 320 | if( empty( $ids ) ) { |
299 | 321 | return wfMsgForContent( 'rightsnone' ); |
300 | 322 | } else { |
— | — | @@ -301,11 +323,11 @@ |
302 | 324 | } |
303 | 325 | } |
304 | 326 | |
305 | | - function makeGroupNameListForLog( $ids ) { |
| 327 | + static function makeGroupNameListForLog( $ids ) { |
306 | 328 | if( empty( $ids ) ) { |
307 | 329 | return ''; |
308 | 330 | } else { |
309 | | - return $this->makeGroupNameList( $ids ); |
| 331 | + return self::makeGroupNameList( $ids ); |
310 | 332 | } |
311 | 333 | } |
312 | 334 | |
— | — | @@ -511,115 +533,20 @@ |
512 | 534 | } |
513 | 535 | |
514 | 536 | /** |
515 | | - * Returns an array of the groups that the user can add/remove. |
| 537 | + * Returns $wgUser->changeableGroups() |
516 | 538 | * |
517 | 539 | * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) ) |
518 | 540 | */ |
519 | 541 | function changeableGroups() { |
520 | 542 | global $wgUser; |
521 | | - |
522 | | - if( $wgUser->isAllowed( 'userrights' ) ) { |
523 | | - // This group gives the right to modify everything (reverse- |
524 | | - // compatibility with old "userrights lets you change |
525 | | - // everything") |
526 | | - // Using array_merge to make the groups reindexed |
527 | | - $all = array_merge( User::getAllGroups() ); |
528 | | - return array( |
529 | | - 'add' => $all, |
530 | | - 'remove' => $all, |
531 | | - 'add-self' => array(), |
532 | | - 'remove-self' => array() |
533 | | - ); |
534 | | - } |
535 | | - |
536 | | - // Okay, it's not so simple, we will have to go through the arrays |
537 | | - $groups = array( |
538 | | - 'add' => array(), |
539 | | - 'remove' => array(), |
540 | | - 'add-self' => array(), |
541 | | - 'remove-self' => array() ); |
542 | | - $addergroups = $wgUser->getEffectiveGroups(); |
543 | | - |
544 | | - foreach ($addergroups as $addergroup) { |
545 | | - $groups = array_merge_recursive( |
546 | | - $groups, $this->changeableByGroup($addergroup) |
547 | | - ); |
548 | | - $groups['add'] = array_unique( $groups['add'] ); |
549 | | - $groups['remove'] = array_unique( $groups['remove'] ); |
550 | | - $groups['add-self'] = array_unique( $groups['add-self'] ); |
551 | | - $groups['remove-self'] = array_unique( $groups['remove-self'] ); |
552 | | - } |
553 | | - |
| 543 | + $groups = $wgUser->changeableGroups(); |
554 | 544 | // Run a hook because we can |
555 | | - wfRunHooks( 'UserrightsChangeableGroups', array( $this, $wgUser, $addergroups, &$groups ) ); |
556 | | - |
| 545 | + wfRunHooks( 'UserrightsChangeableGroups', array( $this, |
| 546 | + $wgUser, $wgUser->getEffectiveGroups(), &$groups ) ); |
557 | 547 | return $groups; |
558 | 548 | } |
559 | 549 | |
560 | 550 | /** |
561 | | - * Returns an array of the groups that a particular group can add/remove. |
562 | | - * |
563 | | - * @param $group String: the group to check for whether it can add/remove |
564 | | - * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) ) |
565 | | - */ |
566 | | - private function changeableByGroup( $group ) { |
567 | | - global $wgAddGroups, $wgRemoveGroups, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf; |
568 | | - |
569 | | - $groups = array( 'add' => array(), 'remove' => array(), 'add-self' => array(), 'remove-self' => array() ); |
570 | | - if( empty($wgAddGroups[$group]) ) { |
571 | | - // Don't add anything to $groups |
572 | | - } elseif( $wgAddGroups[$group] === true ) { |
573 | | - // You get everything |
574 | | - $groups['add'] = User::getAllGroups(); |
575 | | - } elseif( is_array($wgAddGroups[$group]) ) { |
576 | | - $groups['add'] = $wgAddGroups[$group]; |
577 | | - } |
578 | | - |
579 | | - // Same thing for remove |
580 | | - if( empty($wgRemoveGroups[$group]) ) { |
581 | | - } elseif($wgRemoveGroups[$group] === true ) { |
582 | | - $groups['remove'] = User::getAllGroups(); |
583 | | - } elseif( is_array($wgRemoveGroups[$group]) ) { |
584 | | - $groups['remove'] = $wgRemoveGroups[$group]; |
585 | | - } |
586 | | - |
587 | | - // Re-map numeric keys of AddToSelf/RemoveFromSelf to the 'user' key for backwards compatibility |
588 | | - if( empty($wgGroupsAddToSelf['user']) || $wgGroupsAddToSelf['user'] !== true ) { |
589 | | - foreach($wgGroupsAddToSelf as $key => $value) { |
590 | | - if( is_int($key) ) { |
591 | | - $wgGroupsAddToSelf['user'][] = $value; |
592 | | - } |
593 | | - } |
594 | | - } |
595 | | - |
596 | | - if( empty($wgGroupsRemoveFromSelf['user']) || $wgGroupsRemoveFromSelf['user'] !== true ) { |
597 | | - foreach($wgGroupsRemoveFromSelf as $key => $value) { |
598 | | - if( is_int($key) ) { |
599 | | - $wgGroupsRemoveFromSelf['user'][] = $value; |
600 | | - } |
601 | | - } |
602 | | - } |
603 | | - |
604 | | - // Now figure out what groups the user can add to him/herself |
605 | | - if( empty($wgGroupsAddToSelf[$group]) ) { |
606 | | - } elseif( $wgGroupsAddToSelf[$group] === true ) { |
607 | | - // No idea WHY this would be used, but it's there |
608 | | - $groups['add-self'] = User::getAllGroups(); |
609 | | - } elseif( is_array($wgGroupsAddToSelf[$group]) ) { |
610 | | - $groups['add-self'] = $wgGroupsAddToSelf[$group]; |
611 | | - } |
612 | | - |
613 | | - if( empty($wgGroupsRemoveFromSelf[$group]) ) { |
614 | | - } elseif( $wgGroupsRemoveFromSelf[$group] === true ) { |
615 | | - $groups['remove-self'] = User::getAllGroups(); |
616 | | - } elseif( is_array($wgGroupsRemoveFromSelf[$group]) ) { |
617 | | - $groups['remove-self'] = $wgGroupsRemoveFromSelf[$group]; |
618 | | - } |
619 | | - |
620 | | - return $groups; |
621 | | - } |
622 | | - |
623 | | - /** |
624 | 551 | * Show a rights log fragment for the specified user |
625 | 552 | * |
626 | 553 | * @param $user User to show log for |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -345,6 +345,7 @@ |
346 | 346 | when someone tries to use them |
347 | 347 | * BREAKING CHANGE: action=purge requires write rights and, for anonymous users, |
348 | 348 | a POST request |
| 349 | +* (bug 15935) Added action=userrights to add/remove users to/from groups |
349 | 350 | * (bug 18099) Using appendtext to edit a non-existent page causes an interface |
350 | 351 | message to be included in the page text |
351 | 352 | * Added uiprop=changeablegroups to meta=userinfo |