r23410 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r23409‎ | r23410 | r23411 >
Date:04:07, 26 June 2007
Author:simetrical
Status:old
Tags:
Comment:
(bug 6711) Add and to allow finer control over usergroup assignment. Completely reverse-compatible with existing userrights-based setups, but can replace Makesysop and Makebot and open the door to lots of other things as well. Could be moved to extension, I guess, but it just seems a lot simpler to have one interface for all adding/removing of groups.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/SpecialUserrights.php (modified) (history)
  • /trunk/phase3/languages/messages/MessagesEn.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/SpecialUserrights.php
@@ -27,7 +27,7 @@
2828 var $action;
2929
3030 /** Constructor*/
31 - function UserrightsForm ( &$request ) {
 31+ public function __construct( &$request ) {
3232 $this->mPosted = $request->wasPosted();
3333 $this->mRequest =& $request;
3434 $this->mName = 'userrights';
@@ -94,13 +94,17 @@
9595 if(isset($removegroup)) {
9696 $newGroups = array_diff($newGroups, $removegroup);
9797 foreach( $removegroup as $group ) {
98 - $u->removeGroup( $group );
 98+ if ( $this->canRemove( $group ) ) {
 99+ $u->removeGroup( $group );
 100+ }
99101 }
100102 }
101103 if(isset($addgroup)) {
102104 $newGroups = array_merge($newGroups, $addgroup);
103105 foreach( $addgroup as $group ) {
104 - $u->addGroup( $group );
 106+ if ( $this->canAdd( $group ) ) {
 107+ $u->addGroup( $group );
 108+ }
105109 }
106110 }
107111 $newGroups = array_unique( $newGroups );
@@ -108,7 +112,7 @@
109113 wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) );
110114 wfDebug( 'newGroups: ' . print_r( $newGroups, true ) );
111115
112 - wfRunHooks( 'UserRights', array( &$u, $addgroup, $removegroup ) );
 116+ wfRunHooks( 'UserRights', array( &$u, $addgroup, $removegroup ) );
113117 $log = new LogPage( 'rights' );
114118 $log->addEntry( 'rights', Title::makeTitle( NS_USER, $u->getName() ), $reason, array( $this->makeGroupNameList( $oldGroups ),
115119 $this->makeGroupNameList( $newGroups ) ) );
@@ -139,7 +143,7 @@
140144 */
141145 function editUserGroupsForm($username) {
142146 global $wgOut;
143 -
 147+
144148 $user = User::newFromName($username);
145149 if( is_null( $user ) ) {
146150 $wgOut->addWikiText( wfMsg( 'nouserspecified' ) );
@@ -149,12 +153,24 @@
150154 return;
151155 }
152156
153 - $groups = $user->getGroups();
154 - $this->showEditUserGroupsForm( $username, $groups );
 157+ list($addable, $removable) = array_values( $this->changeableGroups() );
 158+ $removable = array_intersect($removable, $user->getGroups()); // Can't remove groups the user doesn't have
 159+ $addable = array_diff( $addable, $user->getGroups()); // Can't add groups the user does have
 160+
 161+ $this->showEditUserGroupsForm( $username, $addable, $removable );
155162 }
156 -
157 - function showEditUserGroupsForm( $username, $groups ) {
 163+
 164+ /**
 165+ * Show the form to edit group memberships.
 166+ *
 167+ * @todo make all CSS-y and semantic
 168+ * @param $username String: Name of user you're editing
 169+ * @param $addable Array: Array of groups that can be added
 170+ * @param $removable Array: Array of groups that can be removed
 171+ */
 172+ private function showEditUserGroupsForm( $username, $addable, $removable ) {
158173 global $wgOut, $wgUser;
 174+
159175 $wgOut->addHTML(
160176 Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->action, 'name' => 'editGroup' ) ) .
161177 Xml::hidden( 'user-editname', $username ) .
@@ -162,14 +178,15 @@
163179 Xml::openElement( 'fieldset' ) .
164180 Xml::element( 'legend', array(), wfMsg( 'userrights-editusergroup' ) ) .
165181 $wgOut->parse( wfMsg( 'editinguser', $username ) ) .
 182+ $this->explainRights() .
166183 "<table border='0'>
167184 <tr>
168185 <td></td>
169186 <td>
170187 <table width='400'>
171188 <tr>
172 - <td width='50%'>" . HTMLSelectGroups( 'member', $this->mName.'-groupsmember', $groups, true, 6 ) . "</td>
173 - <td width='50%'>" . HTMLSelectGroups( 'available', $this->mName.'-groupsavailable', $groups, true, 6, true) . "</td>
 189+ <td width='50%'>" . $this->removeSelect( $removable ) . "</td>
 190+ <td width='50%'>" . $this->addSelect( $addable ) . "</td>
174191 </tr>
175192 </table>
176193 </tr>
@@ -197,5 +214,181 @@
198215 Xml::closeElement( 'form' ) . "\n"
199216 );
200217 }
 218+
 219+ /**
 220+ * Explains what groups the user can add and remove, and why.
 221+ *
 222+ * @return string Explanatory sanitized HTML message
 223+ */
 224+ private function explainRights() {
 225+ global $wgUser;
 226+ $groups = $wgUser->getEffectiveGroups();
 227+ foreach( $groups as $group ) {
 228+ if( $this->changeableByGroup( $group ) == array(
 229+ 'add' => array(),
 230+ 'remove' => array()
 231+ ) ) {
 232+ // Can't add or remove anything, ignore this group
 233+ $groups = array_diff( $groups, array( $group ) );
 234+ }
 235+ }
 236+ $grouplists = array( $groups );
 237+ list( $grouplists[1], $grouplists[2] ) = array_values( $this->changeableGroups() );
 238+
 239+ // Now format them nicely for display (yay mutable variables? I'm sick
 240+ // of thinking up new names)
 241+ foreach( $grouplists as &$list ) {
 242+ if( $list == array() ) {
 243+ $list = wfMsgExt( 'userrights-list-nogroups', 'parseinline' );
 244+ } else {
 245+ $list = wfMsgExt(
 246+ 'userrights-list-groups',
 247+ 'parseinline',
 248+ count( $list ),
 249+ implode(
 250+ $list,
 251+ wfMsgHtml( 'userrights-list-separator' )
 252+ )
 253+ );
 254+ }
 255+ }
 256+
 257+ return wfMsgExt(
 258+ 'userrights-list',
 259+ 'parse',
 260+ $grouplists[0],
 261+ $grouplists[1],
 262+ $grouplists[2]
 263+ );
 264+
 265+ }
 266+
 267+ /**
 268+ * Adds the <select> thingie where you can select what groups to remove
 269+ *
 270+ * @param array $groups The groups that can be removed
 271+ * @return string XHTML <select> element
 272+ */
 273+ private function removeSelect( $groups ) {
 274+ return $this->doSelect( $groups, 'member' );
 275+ }
 276+
 277+ /**
 278+ * Adds the <select> thingie where you can select what groups to add
 279+ *
 280+ * @param array $groups The groups that can be added
 281+ * @return string XHTML <select> element
 282+ */
 283+ private function addSelect( $groups ) {
 284+ return $this->doSelect( $groups, 'available' );
 285+ }
 286+
 287+ /**
 288+ * Adds the <select> thingie where you can select what groups to add/remove
 289+ *
 290+ * @param array $groups The groups that can be added/removed
 291+ * @param string $name 'member' or 'available'
 292+ * @return string XHTML <select> element
 293+ */
 294+ private function doSelect( $groups, $name ) {
 295+ $ret = wfMsgHtml( "{$this->mName}-groups$name" ) .
 296+ Xml::openElement( 'select', array(
 297+ 'name' => "{$name}[]",
 298+ 'multiple' => 'multiple',
 299+ 'size' => '6',
 300+ 'style' => 'width: 100%;'
 301+ )
 302+ );
 303+ foreach ($groups as $group) {
 304+ $ret .= Xml::element( 'option', array( 'value' => $group ), User::getGroupName( $group ) );
 305+ }
 306+ $ret .= Xml::closeElement( 'select' );
 307+ return $ret;
 308+ }
 309+
 310+ /**
 311+ * @param string $group The name of the group to check
 312+ * @return bool Can we remove the group?
 313+ */
 314+ private function canRemove( $group ) {
 315+ // $this->changeableGroups()['remove'] doesn't work, of course. Thanks,
 316+ // PHP.
 317+ $groups = $this->changeableGroups();
 318+ return in_array( $group, $groups['remove'] );
 319+ }
 320+
 321+ /**
 322+ * @param string $group The name of the group to check
 323+ * @return bool Can we add the group?
 324+ */
 325+ private function canAdd( $group ) {
 326+ $groups = $this->changeableGroups();
 327+ return in_array( $group, $groups['add'] );
 328+ }
 329+
 330+ /**
 331+ * Returns an array of the groups that the user can add/remove.
 332+ *
 333+ * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) )
 334+ */
 335+ private function changeableGroups() {
 336+ global $wgUser, $wgGroupPermissions;
 337+
 338+ $groups = array( 'add' => array(), 'remove' => array() );
 339+ $addergroups = $wgUser->getEffectiveGroups();
 340+
 341+ foreach ($addergroups as $addergroup) {
 342+ $groups = array_merge_recursive(
 343+ $groups, $this->changeableByGroup($addergroup)
 344+ );
 345+ $groups['add'] = array_unique( $groups['add'] );
 346+ $groups['remove'] = array_unique( $groups['remove'] );
 347+ }
 348+ return $groups;
 349+ }
 350+
 351+ /**
 352+ * Returns an array of the groups that a particular group can add/remove.
 353+ *
 354+ * @param String $group The group to check for whether it can add/remove
 355+ * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) )
 356+ */
 357+ private function changeableByGroup( $group ) {
 358+ global $wgGroupPermissions, $wgAddGroups, $wgRemoveGroups;
 359+
 360+ if( empty($wgGroupPermissions[$group]['userrights']) ) {
 361+ // This group doesn't give the right to modify anything
 362+ return array( 'add' => array(), 'remove' => array() );
 363+ }
 364+ if( empty($wgAddGroups[$group]) and empty($wgRemoveGroups[$group]) ) {
 365+ // This group gives the right to modify everything (reverse-
 366+ // compatibility with old "userrights lets you change
 367+ // everything")
 368+ return array(
 369+ 'add' => User::getAllGroups(),
 370+ 'remove' => User::getAllGroups()
 371+ );
 372+ }
 373+
 374+ // Okay, it's not so simple, we have to go through the arrays
 375+ $groups = array( 'add' => array(), 'remove' => array() );
 376+ if( empty($wgAddGroups[$group]) ) {
 377+ // Don't add anything to $groups
 378+ } elseif( $wgAddGroups[$group] === true ) {
 379+ // You get everything
 380+ $groups['add'] = User::getAllGroups();
 381+ } elseif( is_array($wgAddGroups[$group]) ) {
 382+ $groups['add'] = $wgAddGroups[$group];
 383+ }
 384+
 385+ // Same thing for remove
 386+ if( empty($wgRemoveGroups[$group]) ) {
 387+ } elseif($wgRemoveGroups[$group] === true ) {
 388+ $groups['remove'] = User::getAllGroups();
 389+ } elseif( is_array($wgRemoveGroups[$group]) ) {
 390+ $groups['remove'] = $wgRemoveGroups[$group];
 391+ }
 392+ return $groups;
 393+ }
201394 } // end class UserrightsForm
202395 ?>
Index: trunk/phase3/includes/DefaultSettings.php
@@ -1132,6 +1132,20 @@
11331133 $wgAutoConfirmCount = 0;
11341134 //$wgAutoConfirmCount = 50;
11351135
 1136+/**
 1137+ * These settings can be used to give finer control over who can assign which
 1138+ * groups at Special:Userrights. Example configuration:
 1139+ *
 1140+ * // Bureaucrat can add any group
 1141+ * $wgAddGroups['bureaucrat'] = true;
 1142+ * // Bureaucrats can only remove bots and sysops
 1143+ * $wgRemoveGroups['bureaucrat'] = array( 'bot', 'sysop' );
 1144+ * // Sysops can make bots
 1145+ * $wgAddGroups['sysop'] = array( 'bot' );
 1146+ * // Sysops can disable other sysops in an emergency, and disable bots
 1147+ * $wgRemoveGroups['sysop'] = array( 'sysop', 'bot' );
 1148+ */
 1149+$wgAddGroups = $wgRemoveGroups = array(); // Add customizations after this line
11361150
11371151
11381152 # Proxy scanner settings
Index: trunk/phase3/languages/messages/MessagesEn.php
@@ -1277,6 +1277,10 @@
12781278 'userrights-groupshelp' => 'Select groups you want the user to be removed from or added to.
12791279 Unselected groups will not be changed. You can deselect a group with CTRL + Left Click',
12801280 'userrights-reason' => 'Reason for change:',
 1281+'userrights-list' => 'Because you are a member of $1, you can add $2 and remove $3.',
 1282+'userrights-list-nogroups' => 'no groups',
 1283+'userrights-list-groups' => 'the {{PLURAL:$1|group|groups}} $2',
 1284+'userrights-list-separator' => ', ',
12811285
12821286 # Groups
12831287 'group' => 'Group:',
Index: trunk/phase3/RELEASE-NOTES
@@ -22,12 +22,14 @@
2323
2424 * $wgThumbUpright - Adjust width of upright images when parameter 'upright' is
2525 used
 26+* $wgAddGroups, $wgRemoveGroups - Finer control over who can assign which
 27+ usergroups
 28+* $wgEnotifImpersonal, $wgEnotifUseJobQ - Bulk mail options for large sites
2629
2730 == New features since 1.10 ==
2831
2932 * (bug 8868) Separate "blocked" message for autoblocks
3033 * Adding expiry of block to block messages
31 -* Bulk mail options ($wgEnotifImpersonal, $wgEnotifUseJobQ) for large sites
3234 * Links to redirect pages in categories are wrapped in
3335 <span class="redirect-in-category"></span>
3436 * Introduced 'ImageOpenShowImageInlineBefore' hook; see docs/hooks.txt for
@@ -105,6 +107,8 @@
106108 * Wrap site CSS and JavaScript in a <pre> tag, like user JS/CSS
107109 * (bug 10196) Add classes and dir="ltr" to the <pre>s on CSS and JS pages (new
108110 classes: mw-user-css, mw-user-js, mw-site-css, mw-site-js)
 111+* (bug 6711) Add $wgAddGroups and $wgRemoveGroups to allow finer control over
 112+ usergroup assignment.
109113
110114 == Bugfixes since 1.10 ==
111115

Follow-up revisions

RevisionCommit summaryAuthorDate
r23581Merged revisions 23406-23580 via svnmerge from...david04:50, 30 June 2007

Status & tagging log