Index: trunk/phase3/maintenance/reassignEdits.inc |
— | — | @@ -1,83 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -/** |
5 | | - * Support functions for the reassignEdits script |
6 | | - * |
7 | | - * @package MediaWiki |
8 | | - * @subpackage Maintenance |
9 | | - * @author Rob Church <robchur@gmail.com> |
10 | | - */ |
11 | | - |
12 | | -function ReassignEdits( $from, $to ) { |
13 | | - |
14 | | - # This stuff needs to come off the master, wrapped in a transaction |
15 | | - $dbw =& wfGetDB( DB_MASTER ); |
16 | | - $dbw->begin(); |
17 | | - |
18 | | - $tbl_arc = $dbw->tableName( 'archive' ); |
19 | | - $tbl_rev = $dbw->tableName( 'revision' ); |
20 | | - |
21 | | - $from_txt = $from['text']; |
22 | | - $to_id = $to['id']; |
23 | | - $to_txt = $to['text']; |
24 | | - |
25 | | - echo( "Searching for current revisions..." ); |
26 | | - $res = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_user_text = \"$from_txt\"" ); |
27 | | - while( $row = $dbw->fetchObject( $res ) ) { |
28 | | - $cur[] = $row->rev_id; |
29 | | - } |
30 | | - $ccount = count( $cur ); |
31 | | - echo( "found $ccount.\n" ); |
32 | | - |
33 | | - echo( "Searching for deleted revisions..." ); |
34 | | - $res = $dbw->query( "SELECT ar_rev_id FROM $tbl_arc WHERE ar_user_text = \"$from_txt\"" ); |
35 | | - while( $row = $dbw->fetchObject( $res ) ){ |
36 | | - $old[] = $row->ar_rev_id; |
37 | | - } |
38 | | - $ocount = count( $old ); |
39 | | - echo( "found $ocount.\n" ); |
40 | | - |
41 | | - if( $ccount > 0 || $ocount > 0 ) { |
42 | | - echo( "Reassigning edits to $to_txt..." ); |
43 | | - } |
44 | | - |
45 | | - if( $ccount > 0 ) { |
46 | | - $set = implode( ', ', $cur ); |
47 | | - $res = $dbw->query( "UPDATE $tbl_rev SET rev_user = $to_id, rev_user_text = \"$to_txt\" WHERE rev_id IN ( $set )" ); |
48 | | - } |
49 | | - |
50 | | - if( $ocount > 0 ) { |
51 | | - $set = implode( ', ', $old ); |
52 | | - $res = $dbw->query( "UPDATE $tbl_arc SET ar_user = $to_id, ar_user_text = \"$to_txt\" WHERE ar_rev_id IN ( $set )" ); |
53 | | - } |
54 | | - |
55 | | - if( $ccount > 0 || $ocount > 0 ) { |
56 | | - echo( "done.\n" ); |
57 | | - } |
58 | | - |
59 | | - $dbw->commit(); |
60 | | - return( true ); |
61 | | - |
62 | | -} |
63 | | - |
64 | | -function GetUserDetails( $spec ) { |
65 | | - |
66 | | - # IP addresses are quick to handle |
67 | | - if( User::isIP( $spec ) ) { |
68 | | - return( array( 'id' => 0, 'text' => $spec, 'valid' => true ) ); |
69 | | - } |
70 | | - |
71 | | - # Need to check the user exists and get ID and canonical username |
72 | | - $user = User::newFromName( $spec ); |
73 | | - if( $user->getID() ) { |
74 | | - # We have them |
75 | | - return( array( 'id' => $user->getID(), 'text' => $user->getName(), 'valid' => true ) ); |
76 | | - } else { |
77 | | - # No such user |
78 | | - return( array( 'id' => 0, 'text' => $spec, 'valid' => false ) ); |
79 | | - } |
80 | | - |
81 | | -} |
82 | | - |
83 | | - |
84 | | -?> |
Index: trunk/phase3/maintenance/reassignEdits.php |
— | — | @@ -6,26 +6,38 @@ |
7 | 7 | * @package MediaWiki |
8 | 8 | * @subpackage Maintenance |
9 | 9 | * @author Rob Church <robchur@gmail.com> |
| 10 | + * @licence GNU General Public Licence 2.0 or later |
10 | 11 | */ |
11 | 12 | |
12 | | -$options = array( 'force' ); |
| 13 | +$options = array( 'force', 'norc', 'quiet', 'report' ); |
13 | 14 | require_once( 'commandLine.inc' ); |
14 | | -require_once( 'reassignEdits.inc' ); |
| 15 | +require_once( 'reassignEdits.inc.php' ); |
15 | 16 | |
16 | | -echo( "Reassign Edits\n\n" ); |
| 17 | +# Set silent mode; --report overrides --quiet |
| 18 | +if( !@$options['report'] && @$options['quiet'] ) |
| 19 | + setSilent(); |
| 20 | + |
| 21 | +out( "Reassign Edits\n\n" ); |
17 | 22 | |
18 | 23 | if( @$args[0] && @$args[1] ) { |
19 | 24 | |
20 | | - $from = GetUserDetails( $args[0] ); |
21 | | - $to = GetUserDetails( $args[1] ); |
22 | | - $tor = $args[1]; |
| 25 | + # Set up the users involved |
| 26 | + $from =& initialiseUser( $args[0] ); |
| 27 | + $to =& initialiseUser( $args[1] ); |
23 | 28 | |
24 | | - if( $to['valid'] || @$options['force'] ) { |
25 | | - ReassignEdits( $from, $to ); |
| 29 | + # If the target doesn't exist, and --force is not set, stop here |
| 30 | + if( $to->getId() || @$options['force'] ) { |
| 31 | + # Reassign the edits |
| 32 | + $report = @$options['report']; |
| 33 | + $count = reassignEdits( $from, $to, !@$options['norc'], $report ); |
| 34 | + # If reporting, and there were items, advise the user to run without --report |
| 35 | + if( $report ) |
| 36 | + out( "Run the script again without --report to update.\n" ); |
26 | 37 | } else { |
27 | | - echo( "User \"$tor\" not found.\n" ); |
| 38 | + $ton = $to->getName(); |
| 39 | + echo( "User '{$ton}' not found.\n" ); |
28 | 40 | } |
29 | | - |
| 41 | + |
30 | 42 | } else { |
31 | 43 | ShowUsage(); |
32 | 44 | } |
— | — | @@ -33,10 +45,13 @@ |
34 | 46 | /** Show script usage information */ |
35 | 47 | function ShowUsage() { |
36 | 48 | echo( "Reassign edits from one user to another.\n\n" ); |
37 | | - echo( "Usage: php reassignEdits.php <from> <to> [--force]\n\n" ); |
| 49 | + echo( "Usage: php reassignEdits.php [--force|--quiet|--norc|--report] <from> <to>\n\n" ); |
38 | 50 | echo( " <from> : Name of the user to assign edits from\n" ); |
39 | 51 | echo( " <to> : Name of the user to assign edits to\n" ); |
40 | | - echo( " --force : Reassign even if the target user doesn't exist\n\n" ); |
| 52 | + echo( " --force : Reassign even if the target user doesn't exist\n" ); |
| 53 | + echo( " --quiet : Don't print status information (except for errors)\n" ); |
| 54 | + echo( " --norc : Don't update the recent changes table\n" ); |
| 55 | + echo( " --report : Print out details of what would be changed, but don't update it\n\n" ); |
41 | 56 | } |
42 | 57 | |
43 | 58 | ?> |
\ No newline at end of file |
Index: trunk/phase3/maintenance/reassignEdits.inc.php |
— | — | @@ -0,0 +1,144 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Support functions for the reassignEdits script |
| 6 | + * |
| 7 | + * @package MediaWiki |
| 8 | + * @subpackage Maintenance |
| 9 | + * @author Rob Church <robchur@gmail.com> |
| 10 | + * @licence GNU General Public Licence 2.0 or later |
| 11 | + */ |
| 12 | + |
| 13 | +/** |
| 14 | + * Reassign edits from one user to another |
| 15 | + * |
| 16 | + * @param $from User to take edits from |
| 17 | + * @param $to User to assign edits to |
| 18 | + * @param $rc Update the recent changes table |
| 19 | + * @param $report Don't change things; just echo numbers |
| 20 | + * @return integer Number of entries changed, or that would be changed |
| 21 | + */ |
| 22 | +function reassignEdits( &$from, &$to, $rc = false, $report = false ) { |
| 23 | + $dbw =& wfGetDB( DB_MASTER ); |
| 24 | + $dbw->immediateBegin(); |
| 25 | + $fname = 'reassignEdits'; |
| 26 | + |
| 27 | + # Count things |
| 28 | + out( "Checking current edits..." ); |
| 29 | + $res = $dbw->select( 'revision', 'COUNT(*) AS count', userConditions( $from, 'rev_user', 'rev_user_text' ), $fname ); |
| 30 | + $row = $dbw->fetchObject( $res ); |
| 31 | + $cur = $row->count; |
| 32 | + out( "found {$cur}.\n" ); |
| 33 | + |
| 34 | + out( "Checking deleted edits..." ); |
| 35 | + $res = $dbw->select( 'archive', 'COUNT(*) AS count', userConditions( $from, 'ar_user', 'ar_user_text' ), $fname ); |
| 36 | + $row = $dbw->fetchObject( $res ); |
| 37 | + $del = $row->count; |
| 38 | + out( "found {$del}.\n" ); |
| 39 | + |
| 40 | + # Don't count recent changes if we're not supposed to |
| 41 | + if( $rc ) { |
| 42 | + out( "Checking recent changes..." ); |
| 43 | + $res = $dbw->select( 'recentchanges', 'COUNT(*) AS count', userConditions( $from, 'rc_user', 'rc_user_text' ), $fname ); |
| 44 | + $row = $dbw->fetchObject( $res ); |
| 45 | + $rec = $row->count; |
| 46 | + out( "found {$rec}.\n" ); |
| 47 | + } else { |
| 48 | + $rec = 0; |
| 49 | + } |
| 50 | + |
| 51 | + $total = $cur + $del + $rec; |
| 52 | + out( "\nTotal entries to change: {$total}\n" ); |
| 53 | + |
| 54 | + if( !$report ) { |
| 55 | + if( $total ) { |
| 56 | + # Reassign edits |
| 57 | + out( "\nReassigning current edits..." ); |
| 58 | + $res = $dbw->update( 'revision', userSpecification( $to, 'rev_user', 'rev_user_text' ), userConditions( $from, 'rev_user', 'rev_user_text' ), $fname ); |
| 59 | + out( "done.\nReassigning deleted edits..." ); |
| 60 | + $res = $dbw->update( 'archive', userSpecification( $to, 'ar_user', 'ar_user_text' ), userConditions( $from, 'ar_user', 'ar_user_text' ), $fname ); |
| 61 | + out( "done.\n" ); |
| 62 | + # Update recent changes if required |
| 63 | + if( $rc ) { |
| 64 | + out( "Updating recent changes..." ); |
| 65 | + $res = $dbw->update( 'recentchanges', userSpecification( $to, 'rc_user', 'rc_user_text' ), userConditions( $from, 'rc_user', 'rc_user_text' ), $fname ); |
| 66 | + out( "done.\n" ); |
| 67 | + } |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | + $dbw->immediateCommit(); |
| 72 | + return (int)$total; |
| 73 | +} |
| 74 | + |
| 75 | +/** |
| 76 | + * Return the most efficient set of user conditions |
| 77 | + * i.e. a user => id mapping, or a user_text => text mapping |
| 78 | + * |
| 79 | + * @param $user User for the condition |
| 80 | + * @param $idfield Field name containing the identifier |
| 81 | + * @param $utfield Field name containing the user text |
| 82 | + * @return array |
| 83 | + */ |
| 84 | +function userConditions( &$user, $idfield, $utfield ) { |
| 85 | + return $user->getId() ? array( $idfield => $user->getID() ) : array( $utfield => $user->getName() ); |
| 86 | +} |
| 87 | + |
| 88 | +/** |
| 89 | + * Return user specifications |
| 90 | + * i.e. user => id, user_text => text |
| 91 | + * |
| 92 | + * @param $user User for the spec |
| 93 | + * @param $idfield Field name containing the identifier |
| 94 | + * @param $utfield Field name containing the user text |
| 95 | + * @return array |
| 96 | + */ |
| 97 | +function userSpecification( &$user, $idfield, $utfield ) { |
| 98 | + return array( $idfield => $user->getId(), $utfield => $user->getName() ); |
| 99 | +} |
| 100 | + |
| 101 | +/** |
| 102 | + * Echo output if $wgSilent is off |
| 103 | + * |
| 104 | + * @param $output Output to echo |
| 105 | + * @return bool True if the output was echoed |
| 106 | + */ |
| 107 | +function out( $output ) { |
| 108 | + global $wgSilent; |
| 109 | + if( !$wgSilent ) { |
| 110 | + echo( $output ); |
| 111 | + return true; |
| 112 | + } else { |
| 113 | + return false; |
| 114 | + } |
| 115 | +} |
| 116 | + |
| 117 | +/** |
| 118 | + * Mutator for $wgSilent |
| 119 | + * |
| 120 | + * @param $silent Switch on $wgSilent |
| 121 | + */ |
| 122 | +function silent( $silent = true ) { |
| 123 | + global $wgSilent; |
| 124 | + $wgSilent = $silent; |
| 125 | +} |
| 126 | + |
| 127 | +/** |
| 128 | + * Initialise the user object |
| 129 | + * |
| 130 | + * @param $username Username or IP address |
| 131 | + * @return User |
| 132 | + */ |
| 133 | +function initialiseUser( $username ) { |
| 134 | + if( User::isIP( $username ) ) { |
| 135 | + $user = new User(); |
| 136 | + $user->setId( 0 ); |
| 137 | + $user->setName( $username ); |
| 138 | + } else { |
| 139 | + $user = User::newFromName( $username ); |
| 140 | + } |
| 141 | + $user->loadFromDatabase(); |
| 142 | + return $user; |
| 143 | +} |
| 144 | + |
| 145 | +?> |
\ No newline at end of file |
Property changes on: trunk/phase3/maintenance/reassignEdits.inc.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 146 | + native |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -142,8 +142,9 @@ |
143 | 143 | * (bug 4737) MediaWiki:Viewcount supports {{PLURAL}} now |
144 | 144 | * Fix bug in wfMsgExt under PHP 5.1.2 |
145 | 145 | * (bug 5761) Project talk namespace broken in Xal, Os, Udm and Cv |
| 146 | +* Rewrite reassignEdits script to be more efficient; support optional updates to |
| 147 | + recent changes table |
146 | 148 | |
147 | | - |
148 | 149 | == Compatibility == |
149 | 150 | |
150 | 151 | Older PHP 4.2 and 4.1 releases are no longer supported; PHP 4 users must |