From 222b01f5169f1c7e69762e0e8904c24f78f71882 Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Wed, 28 Jul 2010 11:52:48 +0200 Subject: update to MediaWiki 1.16.0 --- includes/specials/SpecialUserrights.php | 390 ++++++++++++++------------------ 1 file changed, 169 insertions(+), 221 deletions(-) (limited to 'includes/specials/SpecialUserrights.php') diff --git a/includes/specials/SpecialUserrights.php b/includes/specials/SpecialUserrights.php index 90619109..36caf9a6 100644 --- a/includes/specials/SpecialUserrights.php +++ b/includes/specials/SpecialUserrights.php @@ -34,8 +34,8 @@ class UserrightsPage extends SpecialPage { return !empty( $available['add'] ) or !empty( $available['remove'] ) or ( ( $this->isself || !$checkIfSelf ) and - (!empty( $available['add-self'] ) - or !empty( $available['remove-self'] ))); + ( !empty( $available['add-self'] ) + or !empty( $available['remove-self'] ) ) ); } /** @@ -44,10 +44,10 @@ class UserrightsPage extends SpecialPage { * * @param $par Mixed: string if any subpage provided, else null */ - function execute( $par ) { + public function execute( $par ) { // If the visitor doesn't have permissions to assign or remove // any groups, it's a bit silly to give them the user search prompt. - global $wgUser, $wgRequest; + global $wgUser, $wgRequest, $wgOut; if( $par ) { $this->mTarget = $par; @@ -55,32 +55,41 @@ class UserrightsPage extends SpecialPage { $this->mTarget = $wgRequest->getVal( 'user' ); } - if (!$this->mTarget) { + /* + * If the user is blocked and they only have "partial" access + * (e.g. they don't have the userrights permission), then don't + * allow them to use Special:UserRights. + */ + if( $wgUser->isBlocked() && !$wgUser->isAllowed( 'userrights' ) ) { + $wgOut->blockedPage(); + return; + } + + $available = $this->changeableGroups(); + + if ( !$this->mTarget ) { /* * If the user specified no target, and they can only * edit their own groups, automatically set them as the * target. */ - $available = $this->changeableGroups(); - if (empty($available['add']) && empty($available['remove'])) + if ( !count( $available['add'] ) && !count( $available['remove'] ) ) $this->mTarget = $wgUser->getName(); } - if ($this->mTarget == $wgUser->getName()) + if ( $this->mTarget == $wgUser->getName() ) $this->isself = true; if( !$this->userCanChangeRights( $wgUser, true ) ) { // fixme... there may be intermediate groups we can mention. - global $wgOut; - $wgOut->showPermissionsErrorPage( array( + $wgOut->showPermissionsErrorPage( array( array( $wgUser->isAnon() ? 'userrights-nologin' - : 'userrights-notallowed' ) ); + : 'userrights-notallowed' ) ) ); return; } if ( wfReadOnly() ) { - global $wgOut; $wgOut->readOnlyPage(); return; } @@ -90,7 +99,8 @@ class UserrightsPage extends SpecialPage { $this->setHeaders(); // show the general form - $this->switchForm(); + if ( count( $available['add'] ) || count( $available['remove'] ) ) + $this->switchForm(); if( $wgRequest->wasPosted() ) { // save settings @@ -102,9 +112,7 @@ class UserrightsPage extends SpecialPage { $this->mTarget, $reason ); - - global $wgOut; - + $url = $this->getSuccessURL(); $wgOut->redirect( $url ); return; @@ -117,7 +125,7 @@ class UserrightsPage extends SpecialPage { $this->editUserGroupsForm( $this->mTarget ); } } - + function getSuccessURL() { return $this->getTitle( $this->mTarget )->getFullURL(); } @@ -130,11 +138,12 @@ class UserrightsPage extends SpecialPage { * @param $reason String: reason for group change * @return null */ - function saveUserGroups( $username, $reason = '') { + function saveUserGroups( $username, $reason = '' ) { global $wgRequest, $wgUser, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf; $user = $this->fetchUser( $username ); - if( !$user ) { + if( $user instanceof WikiErrorMsg ) { + $wgOut->addWikiMsgArray( $user->getMessageKey(), $user->getMessageArgs() ); return; } @@ -144,38 +153,58 @@ class UserrightsPage extends SpecialPage { // This could possibly create a highly unlikely race condition if permissions are changed between // when the form is loaded and when the form is saved. Ignoring it for the moment. - foreach ($allgroups as $group) { + foreach ( $allgroups as $group ) { // We'll tell it to remove all unchecked groups, and add all checked groups. // Later on, this gets filtered for what can actually be removed - if ($wgRequest->getCheck( "wpGroup-$group" )) { + if ( $wgRequest->getCheck( "wpGroup-$group" ) ) { $addgroup[] = $group; } else { $removegroup[] = $group; } } + + $this->doSaveUserGroups( $user, $addgroup, $removegroup, $reason ); + } + + /** + * Save user groups changes in the database. + * + * @param $user User object + * @param $add Array of groups to add + * @param $remove Array of groups to remove + * @param $reason String: reason for group change + * @return Array: Tuple of added, then removed groups + */ + function doSaveUserGroups( $user, $add, $remove, $reason = '' ) { + global $wgUser; // Validate input set... + $isself = ( $user->getName() == $wgUser->getName() ); + $groups = $user->getGroups(); $changeable = $this->changeableGroups(); - $addable = array_merge( $changeable['add'], $this->isself ? $changeable['add-self'] : array() ); - $removable = array_merge( $changeable['remove'], $this->isself ? $changeable['remove-self'] : array() ); - - $removegroup = array_unique( - array_intersect( (array)$removegroup, $removable ) ); - $addgroup = array_unique( - array_intersect( (array)$addgroup, $addable ) ); + $addable = array_merge( $changeable['add'], $isself ? $changeable['add-self'] : array() ); + $removable = array_merge( $changeable['remove'], $isself ? $changeable['remove-self'] : array() ); + + $remove = array_unique( + array_intersect( (array)$remove, $removable, $groups ) ); + $add = array_unique( array_diff( + array_intersect( (array)$add, $addable ), + $groups ) + ); $oldGroups = $user->getGroups(); $newGroups = $oldGroups; + // remove then add groups - if( $removegroup ) { - $newGroups = array_diff($newGroups, $removegroup); - foreach( $removegroup as $group ) { + if( $remove ) { + $newGroups = array_diff( $newGroups, $remove ); + foreach( $remove as $group ) { $user->removeGroup( $group ); } } - if( $addgroup ) { - $newGroups = array_merge($newGroups, $addgroup); - foreach( $addgroup as $group ) { + if( $add ) { + $newGroups = array_merge( $newGroups, $add ); + foreach( $add as $group ) { $user->addGroup( $group ); } } @@ -186,26 +215,24 @@ class UserrightsPage extends SpecialPage { wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) ); wfDebug( 'newGroups: ' . print_r( $newGroups, true ) ); - if( $user instanceof User ) { - // hmmm - wfRunHooks( 'UserRights', array( &$user, $addgroup, $removegroup ) ); - } + wfRunHooks( 'UserRights', array( &$user, $add, $remove ) ); if( $newGroups != $oldGroups ) { - $this->addLogEntry( $user, $oldGroups, $newGroups ); + $this->addLogEntry( $user, $oldGroups, $newGroups, $reason ); } + return array( $add, $remove ); } - + + /** * Add a rights log entry for an action. */ - function addLogEntry( $user, $oldGroups, $newGroups ) { - global $wgRequest; + function addLogEntry( $user, $oldGroups, $newGroups, $reason ) { $log = new LogPage( 'rights' ); $log->addEntry( 'rights', $user->getUserPage(), - $wgRequest->getText( 'user-reason' ), + $reason, array( $this->makeGroupNameListForLog( $oldGroups ), $this->makeGroupNameListForLog( $newGroups ) @@ -221,7 +248,8 @@ class UserrightsPage extends SpecialPage { global $wgOut; $user = $this->fetchUser( $username ); - if( !$user ) { + if( $user instanceof WikiErrorMsg ) { + $wgOut->addWikiMsgArray( $user->getMessageKey(), $user->getMessageArgs() ); return; } @@ -239,10 +267,10 @@ class UserrightsPage extends SpecialPage { * return a user (or proxy) object for manipulating it. * * Side effects: error output for invalid access - * @return mixed User, UserRightsProxy, or null + * @return mixed User, UserRightsProxy, or WikiErrorMsg */ - function fetchUser( $username ) { - global $wgOut, $wgUser, $wgUserrightsInterwikiDelimiter; + public function fetchUser( $username ) { + global $wgUser, $wgUserrightsInterwikiDelimiter; $parts = explode( $wgUserrightsInterwikiDelimiter, $username ); if( count( $parts ) < 2 ) { @@ -250,20 +278,21 @@ class UserrightsPage extends SpecialPage { $database = ''; } else { list( $name, $database ) = array_map( 'trim', $parts ); - - if( !$wgUser->isAllowed( 'userrights-interwiki' ) ) { - $wgOut->addWikiMsg( 'userrights-no-interwiki' ); - return null; - } - if( !UserRightsProxy::validDatabase( $database ) ) { - $wgOut->addWikiMsg( 'userrights-nodatabase', $database ); - return null; + + if( $database == wfWikiID() ) { + $database = ''; + } else { + if( !$wgUser->isAllowed( 'userrights-interwiki' ) ) { + return new WikiErrorMsg( 'userrights-no-interwiki' ); + } + if( !UserRightsProxy::validDatabase( $database ) ) { + return new WikiErrorMsg( 'userrights-nodatabase', $database ); + } } } if( $name == '' ) { - $wgOut->addWikiMsg( 'nouserspecified' ); - return false; + return new WikiErrorMsg( 'nouserspecified' ); } if( $name{0} == '#' ) { @@ -278,8 +307,13 @@ class UserrightsPage extends SpecialPage { } if( !$name ) { - $wgOut->addWikiMsg( 'noname' ); - return null; + return new WikiErrorMsg( 'noname' ); + } + } else { + $name = User::getCanonicalName( $name ); + if( !$name ) { + // invalid name + return new WikiErrorMsg( 'nosuchusershort', $username ); } } @@ -290,8 +324,7 @@ class UserrightsPage extends SpecialPage { } if( !$user || $user->isAnon() ) { - $wgOut->addWikiMsg( 'nosuchusershort', $username ); - return null; + return new WikiErrorMsg( 'nosuchusershort', $username ); } return $user; @@ -339,14 +372,16 @@ class UserrightsPage extends SpecialPage { * @return Array: Tuple of addable, then removable groups */ protected function splitGroups( $groups ) { - list($addable, $removable, $addself, $removeself) = array_values( $this->changeableGroups() ); + list( $addable, $removable, $addself, $removeself ) = array_values( $this->changeableGroups() ); $removable = array_intersect( - array_merge( $this->isself ? $removeself : array(), $removable ), - $groups ); // Can't remove groups the user doesn't have - $addable = array_diff( - array_merge( $this->isself ? $addself : array(), $addable ), - $groups ); // Can't add groups the user does have + array_merge( $this->isself ? $removeself : array(), $removable ), + $groups + ); // Can't remove groups the user doesn't have + $addable = array_diff( + array_merge( $this->isself ? $addself : array(), $addable ), + $groups + ); // Can't add groups the user does have return array( $addable, $removable ); } @@ -364,10 +399,21 @@ class UserrightsPage extends SpecialPage { foreach( $groups as $group ) $list[] = self::buildGroupLink( $group ); + $autolist = array(); + if ( $user instanceof User ) { + foreach( Autopromote::getAutopromoteGroups( $user ) as $group ) { + $autolist[] = self::buildGroupLink( $group ); + } + } + $grouplist = ''; if( count( $list ) > 0 ) { $grouplist = wfMsgHtml( 'userrights-groupsmember' ); - $grouplist = '

' . $grouplist . ' ' . $wgLang->listToText( $list ) . '

'; + $grouplist = '

' . $grouplist . ' ' . $wgLang->listToText( $list ) . "

\n"; + } + if( count( $autolist ) > 0 ) { + $autogrouplistintro = wfMsgHtml( 'userrights-groupsmember-auto' ); + $grouplist .= '

' . $autogrouplistintro . ' ' . $wgLang->listToText( $autolist ) . "

\n"; } $wgOut->addHTML( Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalURL(), 'name' => 'editGroup', 'id' => 'mw-userrights-form2' ) ) . @@ -409,17 +455,17 @@ class UserrightsPage extends SpecialPage { private static function buildGroupLink( $group ) { static $cache = array(); if( !isset( $cache[$group] ) ) - $cache[$group] = User::makeGroupLinkHtml( $group, User::getGroupName( $group ) ); + $cache[$group] = User::makeGroupLinkHtml( $group, htmlspecialchars( User::getGroupName( $group ) ) ); return $cache[$group]; } - + /** * Returns an array of all groups that may be edited * @return array Array of groups that may be edited. */ - protected static function getAllGroups() { - return User::getAllGroups(); - } + protected static function getAllGroups() { + return User::getAllGroups(); + } /** * Adds a table with checkboxes where you can select what groups to add/remove @@ -431,11 +477,11 @@ class UserrightsPage extends SpecialPage { $allgroups = $this->getAllGroups(); $ret = ''; - $column = 1; - $settable_col = ''; - $unsettable_col = ''; + # Put all column info into an associative array so that extensions can + # more easily manage it. + $columns = array( 'unchangeable' => array(), 'changeable' => array() ); - foreach ($allgroups as $group) { + foreach( $allgroups as $group ) { $set = in_array( $group, $usergroups ); # Should the checkbox be disabled? $disabled = !( @@ -443,53 +489,54 @@ class UserrightsPage extends SpecialPage { ( !$set && $this->canAdd( $group ) ) ); # Do we need to point out that this action is irreversible? $irreversible = !$disabled && ( - ($set && !$this->canAdd( $group )) || - (!$set && !$this->canRemove( $group ) ) ); - - $attr = $disabled ? array( 'disabled' => 'disabled' ) : array(); - $text = $irreversible - ? wfMsgHtml( 'userrights-irreversible-marker', User::getGroupMember( $group ) ) - : User::getGroupMember( $group ); - $checkbox = Xml::checkLabel( $text, "wpGroup-$group", - "wpGroup-$group", $set, $attr ); - $checkbox = $disabled ? Xml::tags( 'span', array( 'class' => 'mw-userrights-disabled' ), $checkbox ) : $checkbox; - - if ($disabled) { - $unsettable_col .= "$checkbox
\n"; + ( $set && !$this->canAdd( $group ) ) || + ( !$set && !$this->canRemove( $group ) ) ); + + $checkbox = array( + 'set' => $set, + 'disabled' => $disabled, + 'irreversible' => $irreversible + ); + + if( $disabled ) { + $columns['unchangeable'][$group] = $checkbox; } else { - $settable_col .= "$checkbox
\n"; + $columns['changeable'][$group] = $checkbox; } } - if ($column) { - $ret .= Xml::openElement( 'table', array( 'border' => '0', 'class' => 'mw-userrights-groups' ) ) . - " -"; - if( $settable_col !== '' ) { - $ret .= xml::element( 'th', null, wfMsg( 'userrights-changeable-col' ) ); - } - if( $unsettable_col !== '' ) { - $ret .= xml::element( 'th', null, wfMsg( 'userrights-unchangeable-col' ) ); - } - $ret.= " - -"; - if( $settable_col !== '' ) { - $ret .= -" - $settable_col - -"; - } - if( $unsettable_col !== '' ) { - $ret .= -" - $unsettable_col - -"; + # Build the HTML table + $ret .= Xml::openElement( 'table', array( 'border' => '0', 'class' => 'mw-userrights-groups' ) ) . + "\n"; + foreach( $columns as $name => $column ) { + if( $column === array() ) + continue; + $ret .= xml::element( 'th', null, wfMsg( 'userrights-' . $name . '-col' ) ); + } + $ret.= "\n\n"; + foreach( $columns as $column ) { + if( $column === array() ) + continue; + $ret .= "\t\n"; + foreach( $column as $group => $checkbox ) { + $attr = $checkbox['disabled'] ? array( 'disabled' => 'disabled' ) : array(); + + if ( $checkbox['irreversible'] ) { + $text = htmlspecialchars( wfMsg( 'userrights-irreversible-marker', + User::getGroupMember( $group ) ) ); + } else { + $text = htmlspecialchars( User::getGroupMember( $group ) ); + } + $checkboxHtml = Xml::checkLabel( $text, "wpGroup-" . $group, + "wpGroup-" . $group, $checkbox['set'], $attr ); + $ret .= "\t\t" . ( $checkbox['disabled'] + ? Xml::tags( 'span', array( 'class' => 'mw-userrights-disabled' ), $checkboxHtml ) + : $checkboxHtml + ) . "
\n"; } - $ret .= Xml::closeElement( 'tr' ) . Xml::closeElement( 'table' ); + $ret .= "\t\n"; } + $ret .= Xml::closeElement( 'tr' ) . Xml::closeElement( 'table' ); return $ret; } @@ -502,7 +549,7 @@ class UserrightsPage extends SpecialPage { // $this->changeableGroups()['remove'] doesn't work, of course. Thanks, // PHP. $groups = $this->changeableGroups(); - return in_array( $group, $groups['remove'] ) || ($this->isself && in_array( $group, $groups['remove-self'] )); + return in_array( $group, $groups['remove'] ) || ( $this->isself && in_array( $group, $groups['remove-self'] ) ); } /** @@ -511,116 +558,17 @@ class UserrightsPage extends SpecialPage { */ private function canAdd( $group ) { $groups = $this->changeableGroups(); - return in_array( $group, $groups['add'] ) || ($this->isself && in_array( $group, $groups['add-self'] )); + return in_array( $group, $groups['add'] ) || ( $this->isself && in_array( $group, $groups['add-self'] ) ); } /** - * Returns an array of the groups that the user can add/remove. + * Returns $wgUser->changeableGroups() * * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) ) */ function changeableGroups() { global $wgUser; - - if( $wgUser->isAllowed( 'userrights' ) ) { - // This group gives the right to modify everything (reverse- - // compatibility with old "userrights lets you change - // everything") - // Using array_merge to make the groups reindexed - $all = array_merge( User::getAllGroups() ); - return array( - 'add' => $all, - 'remove' => $all, - 'add-self' => array(), - 'remove-self' => array() - ); - } - - // Okay, it's not so simple, we will have to go through the arrays - $groups = array( - 'add' => array(), - 'remove' => array(), - 'add-self' => array(), - 'remove-self' => array() ); - $addergroups = $wgUser->getEffectiveGroups(); - - foreach ($addergroups as $addergroup) { - $groups = array_merge_recursive( - $groups, $this->changeableByGroup($addergroup) - ); - $groups['add'] = array_unique( $groups['add'] ); - $groups['remove'] = array_unique( $groups['remove'] ); - $groups['add-self'] = array_unique( $groups['add-self'] ); - $groups['remove-self'] = array_unique( $groups['remove-self'] ); - } - - // Run a hook because we can - wfRunHooks( 'UserrightsChangeableGroups', array( $this, $wgUser, $addergroups, &$groups ) ); - - return $groups; - } - - /** - * Returns an array of the groups that a particular group can add/remove. - * - * @param $group String: the group to check for whether it can add/remove - * @return Array array( 'add' => array( addablegroups ), 'remove' => array( removablegroups ) , 'add-self' => array( addablegroups to self), 'remove-self' => array( removable groups from self) ) - */ - private function changeableByGroup( $group ) { - global $wgAddGroups, $wgRemoveGroups, $wgGroupsAddToSelf, $wgGroupsRemoveFromSelf; - - $groups = array( 'add' => array(), 'remove' => array(), 'add-self' => array(), 'remove-self' => array() ); - if( empty($wgAddGroups[$group]) ) { - // Don't add anything to $groups - } elseif( $wgAddGroups[$group] === true ) { - // You get everything - $groups['add'] = User::getAllGroups(); - } elseif( is_array($wgAddGroups[$group]) ) { - $groups['add'] = $wgAddGroups[$group]; - } - - // Same thing for remove - if( empty($wgRemoveGroups[$group]) ) { - } elseif($wgRemoveGroups[$group] === true ) { - $groups['remove'] = User::getAllGroups(); - } elseif( is_array($wgRemoveGroups[$group]) ) { - $groups['remove'] = $wgRemoveGroups[$group]; - } - - // Re-map numeric keys of AddToSelf/RemoveFromSelf to the 'user' key for backwards compatibility - if( empty($wgGroupsAddToSelf['user']) || $wgGroupsAddToSelf['user'] !== true ) { - foreach($wgGroupsAddToSelf as $key => $value) { - if( is_int($key) ) { - $wgGroupsAddToSelf['user'][] = $value; - } - } - } - - if( empty($wgGroupsRemoveFromSelf['user']) || $wgGroupsRemoveFromSelf['user'] !== true ) { - foreach($wgGroupsRemoveFromSelf as $key => $value) { - if( is_int($key) ) { - $wgGroupsRemoveFromSelf['user'][] = $value; - } - } - } - - // Now figure out what groups the user can add to him/herself - if( empty($wgGroupsAddToSelf[$group]) ) { - } elseif( $wgGroupsAddToSelf[$group] === true ) { - // No idea WHY this would be used, but it's there - $groups['add-self'] = User::getAllGroups(); - } elseif( is_array($wgGroupsAddToSelf[$group]) ) { - $groups['add-self'] = $wgGroupsAddToSelf[$group]; - } - - if( empty($wgGroupsRemoveFromSelf[$group]) ) { - } elseif( $wgGroupsRemoveFromSelf[$group] === true ) { - $groups['remove-self'] = User::getAllGroups(); - } elseif( is_array($wgGroupsRemoveFromSelf[$group]) ) { - $groups['remove-self'] = $wgGroupsRemoveFromSelf[$group]; - } - - return $groups; + return $wgUser->changeableGroups(); } /** -- cgit v1.2.3-54-g00ecf