Merge "Slight improvements to FormSpecialPage behavior."
[lhc/web/wiklou.git] / includes / specials / SpecialUserrights.php
index d4baae2..f23bc2d 100644 (file)
@@ -45,6 +45,11 @@ class UserrightsPage extends SpecialPage {
                return $this->userCanChangeRights( $user, false );
        }
 
+       /**
+        * @param User $user
+        * @param bool $checkIfSelf
+        * @return bool
+        */
        public function userCanChangeRights( $user, $checkIfSelf = true ) {
                $available = $this->changeableGroups();
                if ( $user->getId() == 0 ) {
@@ -75,13 +80,13 @@ class UserrightsPage extends SpecialPage {
                 * (e.g. they don't have the userrights permission), then don't
                 * allow them to use Special:UserRights.
                 */
-               if( $user->isBlocked() && !$user->isAllowed( 'userrights' ) ) {
+               if ( $user->isBlocked() && !$user->isAllowed( 'userrights' ) ) {
                        throw new UserBlockedError( $user->getBlock() );
                }
 
                $request = $this->getRequest();
 
-               if( $par !== null ) {
+               if ( $par !== null ) {
                        $this->mTarget = $par;
                } else {
                        $this->mTarget = $request->getVal( 'user' );
@@ -95,15 +100,16 @@ class UserrightsPage extends SpecialPage {
                         * edit their own groups, automatically set them as the
                         * target.
                         */
-                       if ( !count( $available['add'] ) && !count( $available['remove'] ) )
+                       if ( !count( $available['add'] ) && !count( $available['remove'] ) ) {
                                $this->mTarget = $user->getName();
+                       }
                }
 
                if ( User::getCanonicalName( $this->mTarget ) == $user->getName() ) {
                        $this->isself = true;
                }
 
-               if( !$this->userCanChangeRights( $user, true ) ) {
+               if ( !$this->userCanChangeRights( $user, true ) ) {
                        // @todo FIXME: There may be intermediate groups we can mention.
                        $msg = $user->isAnon() ? 'userrights-nologin' : 'userrights-notallowed';
                        throw new PermissionsError( null, array( array( $msg ) ) );
@@ -122,25 +128,36 @@ class UserrightsPage extends SpecialPage {
                        $this->switchForm();
                }
 
-               if( $request->wasPosted() ) {
+               if (
+                       $request->wasPosted() &&
+                       $request->getCheck( 'saveusergroups' ) &&
+                       $user->matchEditToken( $request->getVal( 'wpEditToken' ), $this->mTarget )
+               ) {
                        // save settings
-                       if( $request->getCheck( 'saveusergroups' ) ) {
-                               $reason = $request->getVal( 'user-reason' );
-                               $tok = $request->getVal( 'wpEditToken' );
-                               if( $user->matchEditToken( $tok, $this->mTarget ) ) {
-                                       $this->saveUserGroups(
-                                               $this->mTarget,
-                                               $reason
-                                       );
-
-                                       $out->redirect( $this->getSuccessURL() );
-                                       return;
-                               }
+                       $status = $this->fetchUser( $this->mTarget );
+                       if ( !$status->isOK() ) {
+                               $this->getOutput()->addWikiText( $status->getWikiText() );
+                               return;
+                       }
+
+                       $targetUser = $status->value;
+
+                       if ( $request->getVal( 'conflictcheck-originalgroups' ) !== implode( ',', $targetUser->getGroups() ) ) {
+                               $out->addWikiMsg( 'userrights-conflict' );
+                       } else {
+                               $this->saveUserGroups(
+                                       $this->mTarget,
+                                       $request->getVal( 'user-reason' ),
+                                       $targetUser
+                               );
+
+                               $out->redirect( $this->getSuccessURL() );
+                               return;
                        }
                }
 
                // show some more forms
-               if( $this->mTarget !== null ) {
+               if ( $this->mTarget !== null ) {
                        $this->editUserGroupsForm( $this->mTarget );
                }
        }
@@ -155,17 +172,10 @@ class UserrightsPage extends SpecialPage {
         *
         * @param string $username username to apply changes to.
         * @param string $reason reason for group change
+        * @param User|UserRightsProxy $user Target user object.
         * @return null
         */
-       function saveUserGroups( $username, $reason = '' ) {
-               $status = $this->fetchUser( $username );
-               if( !$status->isOK() ) {
-                       $this->getOutput()->addWikiText( $status->getWikiText() );
-                       return;
-               } else {
-                       $user = $status->value;
-               }
-
+       function saveUserGroups( $username, $reason, $user ) {
                $allgroups = $this->getAllGroups();
                $addgroup = array();
                $removegroup = array();
@@ -213,15 +223,15 @@ class UserrightsPage extends SpecialPage {
                $newGroups = $oldGroups;
 
                // remove then add groups
-               if( $remove ) {
+               if ( $remove ) {
                        $newGroups = array_diff( $newGroups, $remove );
-                       foreach( $remove as $group ) {
+                       foreach ( $remove as $group ) {
                                $user->removeGroup( $group );
                        }
                }
-               if( $add ) {
+               if ( $add ) {
                        $newGroups = array_merge( $newGroups, $add );
-                       foreach( $add as $group ) {
+                       foreach ( $add as $group ) {
                                $user->addGroup( $group );
                        }
                }
@@ -234,7 +244,7 @@ class UserrightsPage extends SpecialPage {
                wfDebug( 'newGroups: ' . print_r( $newGroups, true ) );
                wfRunHooks( 'UserRights', array( &$user, $add, $remove ) );
 
-               if( $newGroups != $oldGroups ) {
+               if ( $newGroups != $oldGroups ) {
                        $this->addLogEntry( $user, $oldGroups, $newGroups, $reason );
                }
                return array( $add, $remove );
@@ -262,7 +272,7 @@ class UserrightsPage extends SpecialPage {
         */
        function editUserGroupsForm( $username ) {
                $status = $this->fetchUser( $username );
-               if( !$status->isOK() ) {
+               if ( !$status->isOK() ) {
                        $this->getOutput()->addWikiText( $status->getWikiText() );
                        return;
                } else {
@@ -283,63 +293,64 @@ class UserrightsPage extends SpecialPage {
         * return a user (or proxy) object for manipulating it.
         *
         * Side effects: error output for invalid access
+        * @param string $username
         * @return Status object
         */
        public function fetchUser( $username ) {
                global $wgUserrightsInterwikiDelimiter;
 
                $parts = explode( $wgUserrightsInterwikiDelimiter, $username );
-               if( count( $parts ) < 2 ) {
+               if ( count( $parts ) < 2 ) {
                        $name = trim( $username );
                        $database = '';
                } else {
                        list( $name, $database ) = array_map( 'trim', $parts );
 
-                       if( $database == wfWikiID() ) {
+                       if ( $database == wfWikiID() ) {
                                $database = '';
                        } else {
-                               if( !$this->getUser()->isAllowed( 'userrights-interwiki' ) ) {
+                               if ( !$this->getUser()->isAllowed( 'userrights-interwiki' ) ) {
                                        return Status::newFatal( 'userrights-no-interwiki' );
                                }
-                               if( !UserRightsProxy::validDatabase( $database ) ) {
+                               if ( !UserRightsProxy::validDatabase( $database ) ) {
                                        return Status::newFatal( 'userrights-nodatabase', $database );
                                }
                        }
                }
 
-               if( $name === '' ) {
+               if ( $name === '' ) {
                        return Status::newFatal( 'nouserspecified' );
                }
 
-               if( $name[0] == '#' ) {
+               if ( $name[0] == '#' ) {
                        // Numeric ID can be specified...
                        // We'll do a lookup for the name internally.
                        $id = intval( substr( $name, 1 ) );
 
-                       if( $database == '' ) {
+                       if ( $database == '' ) {
                                $name = User::whoIs( $id );
                        } else {
                                $name = UserRightsProxy::whoIs( $database, $id );
                        }
 
-                       if( !$name ) {
+                       if ( !$name ) {
                                return Status::newFatal( 'noname' );
                        }
                } else {
                        $name = User::getCanonicalName( $name );
-                       if( $name === false ) {
+                       if ( $name === false ) {
                                // invalid name
                                return Status::newFatal( 'nosuchusershort', $username );
                        }
                }
 
-               if( $database == '' ) {
+               if ( $database == '' ) {
                        $user = User::newFromName( $name );
                } else {
                        $user = UserRightsProxy::newFromName( $database, $name );
                }
 
-               if( !$user || $user->isAnon() ) {
+               if ( !$user || $user->isAnon() ) {
                        return Status::newFatal( 'nosuchusershort', $username );
                }
 
@@ -347,7 +358,7 @@ class UserrightsPage extends SpecialPage {
        }
 
        function makeGroupNameList( $ids ) {
-               if( empty( $ids ) ) {
+               if ( empty( $ids ) ) {
                        return $this->msg( 'rightsnone' )->inContentLanguage()->text();
                } else {
                        return implode( ', ', $ids );
@@ -364,7 +375,7 @@ class UserrightsPage extends SpecialPage {
        function makeGroupNameListForLog( $ids ) {
                wfDeprecated( __METHOD__, '1.21' );
 
-               if( empty( $ids ) ) {
+               if ( empty( $ids ) ) {
                        return '';
                } else {
                        return $this->makeGroupNameList( $ids );
@@ -419,7 +430,7 @@ class UserrightsPage extends SpecialPage {
        protected function showEditUserGroupsForm( $user, $groups ) {
                $list = array();
                $membersList = array();
-               foreach( $groups as $group ) {
+               foreach ( $groups as $group ) {
                        $list[] = self::buildGroupLink( $group );
                        $membersList[] = self::buildGroupMemberLink( $group );
                }
@@ -427,7 +438,7 @@ class UserrightsPage extends SpecialPage {
                $autoList = array();
                $autoMembersList = array();
                if ( $user instanceof User ) {
-                       foreach( Autopromote::getAutopromoteGroups( $user ) as $group ) {
+                       foreach ( Autopromote::getAutopromoteGroups( $user ) as $group ) {
                                $autoList[] = self::buildGroupLink( $group );
                                $autoMembersList[] = self::buildGroupMemberLink( $group );
                        }
@@ -447,12 +458,12 @@ class UserrightsPage extends SpecialPage {
                $count = count( $list );
                if ( $count > 0 ) {
                        $grouplist = $this->msg( 'userrights-groupsmember', $count, $user->getName() )->parse();
-                       $grouplist = '<p>' . $grouplist  . ' ' . $displayedList . "</p>\n";
+                       $grouplist = '<p>' . $grouplist . ' ' . $displayedList . "</p>\n";
                }
                $count = count( $autoList );
                if ( $count > 0 ) {
                        $autogrouplistintro = $this->msg( 'userrights-groupsmember-auto', $count, $user->getName() )->parse();
-                       $grouplist .= '<p>' . $autogrouplistintro  . ' ' . $displayedAutolist . "</p>\n";
+                       $grouplist .= '<p>' . $autogrouplistintro . ' ' . $displayedAutolist . "</p>\n";
                }
 
                $userToolLinks = Linker::userToolLinks(
@@ -466,6 +477,7 @@ class UserrightsPage extends SpecialPage {
                        Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getTitle()->getLocalURL(), 'name' => 'editGroup', 'id' => 'mw-userrights-form2' ) ) .
                        Html::hidden( 'user', $this->mTarget ) .
                        Html::hidden( 'wpEditToken', $this->getUser()->getEditToken( $this->mTarget ) ) .
+                       Html::hidden( 'conflictcheck-originalgroups', implode( ',', $user->getGroups() ) ) . // Conflict detection
                        Xml::openElement( 'fieldset' ) .
                        Xml::element( 'legend', array(), $this->msg( 'userrights-editusergroup', $user->getName() )->text() ) .
                        $this->msg( 'editinguser' )->params( wfEscapeWikiText( $user->getName() ) )->rawParams( $userToolLinks )->parse() .
@@ -539,7 +551,7 @@ class UserrightsPage extends SpecialPage {
                # 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 = !(
@@ -556,7 +568,7 @@ class UserrightsPage extends SpecialPage {
                                'irreversible' => $irreversible
                        );
 
-                       if( $disabled ) {
+                       if ( $disabled ) {
                                $columns['unchangeable'][$group] = $checkbox;
                        } else {
                                $columns['changeable'][$group] = $checkbox;
@@ -566,17 +578,19 @@ class UserrightsPage extends SpecialPage {
                # Build the HTML table
                $ret .= Xml::openElement( 'table', array( 'class' => 'mw-userrights-groups' ) ) .
                        "<tr>\n";
-               foreach( $columns as $name => $column ) {
-                       if( $column === array() )
+               foreach ( $columns as $name => $column ) {
+                       if ( $column === array() ) {
                                continue;
+                       }
                        $ret .= Xml::element( 'th', null, $this->msg( 'userrights-' . $name . '-col', count( $column ) )->text() );
                }
                $ret .= "</tr>\n<tr>\n";
-               foreach( $columns as $column ) {
-                       if( $column === array() )
+               foreach ( $columns as $column ) {
+                       if ( $column === array() ) {
                                continue;
+                       }
                        $ret .= "\t<td style='vertical-align:top;'>\n";
-                       foreach( $column as $group => $checkbox ) {
+                       foreach ( $column as $group => $checkbox ) {
                                $attr = $checkbox['disabled'] ? array( 'disabled' => 'disabled' ) : array();
 
                                $member = User::getGroupMember( $group, $user->getName() );