From c29846f281a000a9ae0c76b36f0b3c3e9f0d454b Mon Sep 17 00:00:00 2001 From: Rob Church Date: Sat, 29 Apr 2006 18:44:00 +0000 Subject: [PATCH] Rewrite reassignEdits script to be more efficient; support optional updates to recent changes table; add reporting and silent modes --- RELEASE-NOTES | 3 +- maintenance/reassignEdits.inc | 83 ----------------- maintenance/reassignEdits.inc.php | 144 ++++++++++++++++++++++++++++++ maintenance/reassignEdits.php | 39 +++++--- 4 files changed, 173 insertions(+), 96 deletions(-) delete mode 100644 maintenance/reassignEdits.inc create mode 100644 maintenance/reassignEdits.inc.php diff --git a/RELEASE-NOTES b/RELEASE-NOTES index a4e2da6673..2cf47c2fc5 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -142,7 +142,8 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN * (bug 4737) MediaWiki:Viewcount supports {{PLURAL}} now * Fix bug in wfMsgExt under PHP 5.1.2 * (bug 5761) Project talk namespace broken in Xal, Os, Udm and Cv - +* Rewrite reassignEdits script to be more efficient; support optional updates to + recent changes table == Compatibility == diff --git a/maintenance/reassignEdits.inc b/maintenance/reassignEdits.inc deleted file mode 100644 index af4c601487..0000000000 --- a/maintenance/reassignEdits.inc +++ /dev/null @@ -1,83 +0,0 @@ - - */ - -function ReassignEdits( $from, $to ) { - - # This stuff needs to come off the master, wrapped in a transaction - $dbw =& wfGetDB( DB_MASTER ); - $dbw->begin(); - - $tbl_arc = $dbw->tableName( 'archive' ); - $tbl_rev = $dbw->tableName( 'revision' ); - - $from_txt = $from['text']; - $to_id = $to['id']; - $to_txt = $to['text']; - - echo( "Searching for current revisions..." ); - $res = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_user_text = \"$from_txt\"" ); - while( $row = $dbw->fetchObject( $res ) ) { - $cur[] = $row->rev_id; - } - $ccount = count( $cur ); - echo( "found $ccount.\n" ); - - echo( "Searching for deleted revisions..." ); - $res = $dbw->query( "SELECT ar_rev_id FROM $tbl_arc WHERE ar_user_text = \"$from_txt\"" ); - while( $row = $dbw->fetchObject( $res ) ){ - $old[] = $row->ar_rev_id; - } - $ocount = count( $old ); - echo( "found $ocount.\n" ); - - if( $ccount > 0 || $ocount > 0 ) { - echo( "Reassigning edits to $to_txt..." ); - } - - if( $ccount > 0 ) { - $set = implode( ', ', $cur ); - $res = $dbw->query( "UPDATE $tbl_rev SET rev_user = $to_id, rev_user_text = \"$to_txt\" WHERE rev_id IN ( $set )" ); - } - - if( $ocount > 0 ) { - $set = implode( ', ', $old ); - $res = $dbw->query( "UPDATE $tbl_arc SET ar_user = $to_id, ar_user_text = \"$to_txt\" WHERE ar_rev_id IN ( $set )" ); - } - - if( $ccount > 0 || $ocount > 0 ) { - echo( "done.\n" ); - } - - $dbw->commit(); - return( true ); - -} - -function GetUserDetails( $spec ) { - - # IP addresses are quick to handle - if( User::isIP( $spec ) ) { - return( array( 'id' => 0, 'text' => $spec, 'valid' => true ) ); - } - - # Need to check the user exists and get ID and canonical username - $user = User::newFromName( $spec ); - if( $user->getID() ) { - # We have them - return( array( 'id' => $user->getID(), 'text' => $user->getName(), 'valid' => true ) ); - } else { - # No such user - return( array( 'id' => 0, 'text' => $spec, 'valid' => false ) ); - } - -} - - -?> diff --git a/maintenance/reassignEdits.inc.php b/maintenance/reassignEdits.inc.php new file mode 100644 index 0000000000..6e54aea14f --- /dev/null +++ b/maintenance/reassignEdits.inc.php @@ -0,0 +1,144 @@ + + * @licence GNU General Public Licence 2.0 or later + */ + +/** + * Reassign edits from one user to another + * + * @param $from User to take edits from + * @param $to User to assign edits to + * @param $rc Update the recent changes table + * @param $report Don't change things; just echo numbers + * @return integer Number of entries changed, or that would be changed + */ +function reassignEdits( &$from, &$to, $rc = false, $report = false ) { + $dbw =& wfGetDB( DB_MASTER ); + $dbw->immediateBegin(); + $fname = 'reassignEdits'; + + # Count things + out( "Checking current edits..." ); + $res = $dbw->select( 'revision', 'COUNT(*) AS count', userConditions( $from, 'rev_user', 'rev_user_text' ), $fname ); + $row = $dbw->fetchObject( $res ); + $cur = $row->count; + out( "found {$cur}.\n" ); + + out( "Checking deleted edits..." ); + $res = $dbw->select( 'archive', 'COUNT(*) AS count', userConditions( $from, 'ar_user', 'ar_user_text' ), $fname ); + $row = $dbw->fetchObject( $res ); + $del = $row->count; + out( "found {$del}.\n" ); + + # Don't count recent changes if we're not supposed to + if( $rc ) { + out( "Checking recent changes..." ); + $res = $dbw->select( 'recentchanges', 'COUNT(*) AS count', userConditions( $from, 'rc_user', 'rc_user_text' ), $fname ); + $row = $dbw->fetchObject( $res ); + $rec = $row->count; + out( "found {$rec}.\n" ); + } else { + $rec = 0; + } + + $total = $cur + $del + $rec; + out( "\nTotal entries to change: {$total}\n" ); + + if( !$report ) { + if( $total ) { + # Reassign edits + out( "\nReassigning current edits..." ); + $res = $dbw->update( 'revision', userSpecification( $to, 'rev_user', 'rev_user_text' ), userConditions( $from, 'rev_user', 'rev_user_text' ), $fname ); + out( "done.\nReassigning deleted edits..." ); + $res = $dbw->update( 'archive', userSpecification( $to, 'ar_user', 'ar_user_text' ), userConditions( $from, 'ar_user', 'ar_user_text' ), $fname ); + out( "done.\n" ); + # Update recent changes if required + if( $rc ) { + out( "Updating recent changes..." ); + $res = $dbw->update( 'recentchanges', userSpecification( $to, 'rc_user', 'rc_user_text' ), userConditions( $from, 'rc_user', 'rc_user_text' ), $fname ); + out( "done.\n" ); + } + } + } + + $dbw->immediateCommit(); + return (int)$total; +} + +/** + * Return the most efficient set of user conditions + * i.e. a user => id mapping, or a user_text => text mapping + * + * @param $user User for the condition + * @param $idfield Field name containing the identifier + * @param $utfield Field name containing the user text + * @return array + */ +function userConditions( &$user, $idfield, $utfield ) { + return $user->getId() ? array( $idfield => $user->getID() ) : array( $utfield => $user->getName() ); +} + +/** + * Return user specifications + * i.e. user => id, user_text => text + * + * @param $user User for the spec + * @param $idfield Field name containing the identifier + * @param $utfield Field name containing the user text + * @return array + */ +function userSpecification( &$user, $idfield, $utfield ) { + return array( $idfield => $user->getId(), $utfield => $user->getName() ); +} + +/** + * Echo output if $wgSilent is off + * + * @param $output Output to echo + * @return bool True if the output was echoed + */ +function out( $output ) { + global $wgSilent; + if( !$wgSilent ) { + echo( $output ); + return true; + } else { + return false; + } +} + +/** + * Mutator for $wgSilent + * + * @param $silent Switch on $wgSilent + */ +function silent( $silent = true ) { + global $wgSilent; + $wgSilent = $silent; +} + +/** + * Initialise the user object + * + * @param $username Username or IP address + * @return User + */ +function initialiseUser( $username ) { + if( User::isIP( $username ) ) { + $user = new User(); + $user->setId( 0 ); + $user->setName( $username ); + } else { + $user = User::newFromName( $username ); + } + $user->loadFromDatabase(); + return $user; +} + +?> \ No newline at end of file diff --git a/maintenance/reassignEdits.php b/maintenance/reassignEdits.php index 751d200480..4ac566af2e 100644 --- a/maintenance/reassignEdits.php +++ b/maintenance/reassignEdits.php @@ -6,26 +6,38 @@ * @package MediaWiki * @subpackage Maintenance * @author Rob Church + * @licence GNU General Public Licence 2.0 or later */ -$options = array( 'force' ); +$options = array( 'force', 'norc', 'quiet', 'report' ); require_once( 'commandLine.inc' ); -require_once( 'reassignEdits.inc' ); +require_once( 'reassignEdits.inc.php' ); -echo( "Reassign Edits\n\n" ); +# Set silent mode; --report overrides --quiet +if( !@$options['report'] && @$options['quiet'] ) + setSilent(); + +out( "Reassign Edits\n\n" ); if( @$args[0] && @$args[1] ) { - $from = GetUserDetails( $args[0] ); - $to = GetUserDetails( $args[1] ); - $tor = $args[1]; + # Set up the users involved + $from =& initialiseUser( $args[0] ); + $to =& initialiseUser( $args[1] ); - if( $to['valid'] || @$options['force'] ) { - ReassignEdits( $from, $to ); + # If the target doesn't exist, and --force is not set, stop here + if( $to->getId() || @$options['force'] ) { + # Reassign the edits + $report = @$options['report']; + $count = reassignEdits( $from, $to, !@$options['norc'], $report ); + # If reporting, and there were items, advise the user to run without --report + if( $report ) + out( "Run the script again without --report to update.\n" ); } else { - echo( "User \"$tor\" not found.\n" ); + $ton = $to->getName(); + echo( "User '{$ton}' not found.\n" ); } - + } else { ShowUsage(); } @@ -33,10 +45,13 @@ if( @$args[0] && @$args[1] ) { /** Show script usage information */ function ShowUsage() { echo( "Reassign edits from one user to another.\n\n" ); - echo( "Usage: php reassignEdits.php [--force]\n\n" ); + echo( "Usage: php reassignEdits.php [--force|--quiet|--norc|--report] \n\n" ); echo( " : Name of the user to assign edits from\n" ); echo( " : Name of the user to assign edits to\n" ); - echo( " --force : Reassign even if the target user doesn't exist\n\n" ); + echo( " --force : Reassign even if the target user doesn't exist\n" ); + echo( " --quiet : Don't print status information (except for errors)\n" ); + echo( " --norc : Don't update the recent changes table\n" ); + echo( " --report : Print out details of what would be changed, but don't update it\n\n" ); } ?> \ No newline at end of file -- 2.20.1