MediaWiki  REL1_22
migrateUserGroup.php
Go to the documentation of this file.
00001 <?php
00024 require_once __DIR__ . '/Maintenance.php';
00025 
00031 class MigrateUserGroup extends Maintenance {
00032     public function __construct() {
00033         parent::__construct();
00034         $this->mDescription = "Re-assign users from an old group to a new one";
00035         $this->addArg( 'oldgroup', 'Old user group key', true );
00036         $this->addArg( 'newgroup', 'New user group key', true );
00037         $this->setBatchSize( 200 );
00038     }
00039 
00040     public function execute() {
00041         $count = 0;
00042         $oldGroup = $this->getArg( 0 );
00043         $newGroup = $this->getArg( 1 );
00044         $dbw = wfGetDB( DB_MASTER );
00045         $start = $dbw->selectField( 'user_groups', 'MIN(ug_user)',
00046             array( 'ug_group' => $oldGroup ), __FUNCTION__ );
00047         $end = $dbw->selectField( 'user_groups', 'MAX(ug_user)',
00048             array( 'ug_group' => $oldGroup ), __FUNCTION__ );
00049         if ( $start === null ) {
00050             $this->error( "Nothing to do - no users in the '$oldGroup' group", true );
00051         }
00052         # Do remaining chunk
00053         $end += $this->mBatchSize - 1;
00054         $blockStart = $start;
00055         $blockEnd = $start + $this->mBatchSize - 1;
00056         // Migrate users over in batches...
00057         while ( $blockEnd <= $end ) {
00058             $affected = 0;
00059             $this->output( "Doing users $blockStart to $blockEnd\n" );
00060 
00061             $dbw->begin( __METHOD__ );
00062             $dbw->update( 'user_groups',
00063                 array( 'ug_group' => $newGroup ),
00064                 array( 'ug_group' => $oldGroup,
00065                     "ug_user BETWEEN $blockStart AND $blockEnd" ),
00066                 __METHOD__,
00067                 array( 'IGNORE' )
00068             );
00069             $affected += $dbw->affectedRows();
00070             // Delete rows that the UPDATE operation above had to ignore.
00071             // This happens when a user is in both the old and new group.
00072             // Updating the row for the old group membership failed since
00073             // user/group is UNIQUE.
00074             $dbw->delete( 'user_groups',
00075                 array( 'ug_group' => $oldGroup,
00076                     "ug_user BETWEEN $blockStart AND $blockEnd" ),
00077                 __METHOD__
00078             );
00079             $affected += $dbw->affectedRows();
00080             $dbw->commit( __METHOD__ );
00081 
00082             // Clear cache for the affected users (bug 40340)
00083             if ( $affected > 0 ) {
00084                 // XXX: This also invalidates cache of unaffected users that
00085                 // were in the new group and not in the group.
00086                 $res = $dbw->select( 'user_groups', 'ug_user',
00087                     array( 'ug_group' => $newGroup,
00088                         "ug_user BETWEEN $blockStart AND $blockEnd" ),
00089                     __METHOD__
00090                 );
00091                 if ( $res !== false ) {
00092                     foreach ( $res as $row ) {
00093                         $user = User::newFromId( $row->ug_user );
00094                         $user->invalidateCache();
00095                     }
00096                 }
00097             }
00098 
00099             $count += $affected;
00100             $blockStart += $this->mBatchSize;
00101             $blockEnd += $this->mBatchSize;
00102             wfWaitForSlaves();
00103         }
00104         $this->output( "Done! $count users in group '$oldGroup' are now in '$newGroup' instead.\n" );
00105     }
00106 }
00107 
00108 $maintClass = "MigrateUserGroup";
00109 require_once RUN_MAINTENANCE_IF_MAIN;