Rewrite reassignEdits script to be more efficient; support optional updates to recent...
authorRob Church <robchurch@users.mediawiki.org>
Sat, 29 Apr 2006 18:44:00 +0000 (18:44 +0000)
committerRob Church <robchurch@users.mediawiki.org>
Sat, 29 Apr 2006 18:44:00 +0000 (18:44 +0000)
RELEASE-NOTES
maintenance/reassignEdits.inc [deleted file]
maintenance/reassignEdits.inc.php [new file with mode: 0644]
maintenance/reassignEdits.php

index a4e2da6..2cf47c2 100644 (file)
@@ -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 (file)
index af4c601..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-
-/**
- * Support functions for the reassignEdits script
- *
- * @package MediaWiki
- * @subpackage Maintenance
- * @author Rob Church <robchur@gmail.com>
- */
-
-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 (file)
index 0000000..6e54aea
--- /dev/null
@@ -0,0 +1,144 @@
+<?php
+
+/**
+ * Support functions for the reassignEdits script
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * @author Rob Church <robchur@gmail.com>
+ * @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
index 751d200..4ac566a 100644 (file)
@@ -6,26 +6,38 @@
  * @package MediaWiki
  * @subpackage Maintenance
  * @author Rob Church <robchur@gmail.com>
+ * @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 <from> <to> [--force]\n\n" );
+       echo( "Usage: php reassignEdits.php [--force|--quiet|--norc|--report] <from> <to>\n\n" );
        echo( "    <from> : Name of the user to assign edits from\n" );
        echo( "      <to> : 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