r91982 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r91981‎ | r91982 | r91983 >
Date:18:02, 12 July 2011
Author:demon
Status:ok
Tags:
Comment:
Followup r91832: move maintenance script from core to Renameuser extension.
Modified paths:
  • /trunk/extensions/Renameuser/renameUserCleanup.php (added) (history)
  • /trunk/phase3/maintenance/renameUserCleanup.php (deleted) (history)

Diff [purge]

Index: trunk/phase3/maintenance/renameUserCleanup.php
@@ -1,185 +0,0 @@
2 -<?php
3 -/**
4 - * Maintenance script to clean up after incomplete user renames
5 - * Sometimes user edits are left lying around under the old name,
6 - * check for that and assign them to the new username
7 - *
8 - * This program is free software; you can redistribute it and/or modify
9 - * it under the terms of the GNU General Public License as published by
10 - * the Free Software Foundation; either version 2 of the License, or
11 - * (at your option) any later version.
12 - *
13 - * This program is distributed in the hope that it will be useful,
14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 - * GNU General Public License for more details.
17 - *
18 - * You should have received a copy of the GNU General Public License along
19 - * with this program; if not, write to the Free Software Foundation, Inc.,
20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 - * http://www.gnu.org/copyleft/gpl.html
22 - *
23 - * @ingroup Maintenance
24 - * @author Ariel Glenn <ariel@wikimedia.orf>
25 - */
26 -
27 -require_once( dirname( __FILE__ ) . '/Maintenance.php' );
28 -
29 -class RenameUserCleanup extends Maintenance {
30 - const BATCH_SIZE = 1000;
31 -
32 - public function __construct() {
33 - parent::__construct();
34 - $this->mDescription = "Maintenance script to finish incomplete rename user, in particular to reassign edits that were missed";
35 - $this->addOption( 'olduser', 'Old user name', true, true );
36 - $this->addOption( 'newuser', 'New user name', true, true );
37 - }
38 -
39 - public function execute() {
40 - $this->output( "Rename User Cleanup starting...\n\n" );
41 - $olduser = User::newFromName( $this->getOption( 'olduser' ) );
42 - $newuser = User::newFromName( $this->getOption( 'newuser' ) );
43 - if ( !$newuser->getId() ) {
44 - $this->error( "No such user: " . $this->getOption( 'newuser' ), true );
45 - exit(1);
46 - }
47 - if ($olduser->getId() ) {
48 - print( "WARNING!!: Old user still exists: " . $this->getOption( 'olduser' ) . "\n");
49 - print("proceed anyways? We'll only re-attribute edits that have the new user uid (or 0) and the old user name. [N/y] ");
50 - $stdin = fopen ("php://stdin","rt");
51 - $line = fgets($stdin);
52 - fclose($stdin);
53 - if ( $line[0] != "Y" && $line[0] != "y" ) {
54 - print("Exiting at user's request\n");
55 - exit(0);
56 - }
57 - }
58 -
59 - $dbr = wfGetDB( DB_SLAVE );
60 - $result = $dbr->select( 'logging', '*',
61 - array( 'log_type' => 'renameuser',
62 - 'log_action' => 'renameuser',
63 - 'log_title' => $olduser->getName(),
64 - 'log_params' => $newuser->getName()
65 - ),
66 - __METHOD__
67 - );
68 - if (! $result ) {
69 - print("No log entry found for a rename of ".$olduser->getName()." to ".$newuser->getName().", giving up\n");
70 - exit(1);
71 - }
72 - foreach ( $result as $row ) {
73 - print("Found log entry of the rename: ".$olduser->getName()." to ".$newuser->getName()." on $row->log_timestamp\n");
74 - }
75 - if ($result->numRows() > 1) {
76 - print("More than one rename entry found in the log, not sure what to do. Continue anyways? [N/y] ");
77 - $stdin = fopen ("php://stdin","rt");
78 - $line = fgets($stdin);
79 - fclose($stdin);
80 - if ( $line[0] != "Y" && $line[0] != "y" ) {
81 - print("Exiting at user's request\n");
82 - exit(1);
83 - }
84 - }
85 - $dbw = wfGetDB( DB_MASTER );
86 -
87 - $this->updateTable('revision', 'rev_user_text', 'rev_user', 'rev_timestamp', $olduser, $newuser, $dbw);
88 - $this->updateTable('archive', 'ar_user_text', 'ar_user', 'ar_timestamp', $olduser, $newuser, $dbw);
89 - $this->updateTable('logging', 'log_user_text', 'log_user', 'log_timestamp', $olduser, $newuser, $dbw);
90 - $this->updateTable('image', 'img_user_text', 'img_user', 'img_timestamp', $olduser, $newuser, $dbw);
91 - $this->updateTable('oldimage', 'oi_user_text', 'oi_user', 'oi_timestamp', $olduser, $newuser, $dbw);
92 -# FIXME: updateTable('filearchive', 'fa_user_text','fa_user', 'fa_timestamp', $olduser, $newuser, $dbw); (not indexed yet)
93 - print "Done!\n";
94 - exit(0);
95 - }
96 -
97 - public function updateTable($table,$usernamefield,$useridfield,$timestampfield,$olduser,$newuser,$dbw) {
98 - $doUid = 0;
99 -
100 - $contribs = $dbw->selectField( $table, 'count(*)',
101 - array( $usernamefield => $olduser->getName(), $useridfield => $newuser->getId() ), __METHOD__ );
102 - if ($contribs == 0) {
103 - $contribs = $dbw->selectField( $table, 'count(*)',
104 - array( $usernamefield => $olduser->getName(), $useridfield => 0 ), __METHOD__ );
105 - if ($contribs > 0) {
106 - print("Found $contribs edits to be re-attributed from table $table but the uid present is 0 (should be ".$newuser->getId().")\n");
107 - print("If you proceed, the uid field will be set to that of the new user name (i.e. ".$newuser->getId().") in these rows.\n");
108 - $doUid = 1;
109 - }
110 - else {
111 - print("No edits to be re-attributed from table $table\n");
112 - return(0);
113 - }
114 - }
115 - else {
116 - print("total number of edits to be re-attributed from table $table: $contribs\n");
117 - }
118 - print("proceed? [N/y] ");
119 - $stdin = fopen ("php://stdin","rt");
120 - $line = fgets($stdin);
121 - fclose($stdin);
122 - if ( $line[0] != "Y" && $line[0] != "y" ) {
123 - print("skipping at user's request\n");
124 - return(0);
125 - }
126 - $selectConds = array( $usernamefield => $olduser->getName() );
127 - $updateFields = array( $usernamefield => $newuser->getName() );
128 - $updateConds = array( $usernamefield => $olduser->getName() );
129 -
130 - $extraConds = array( $useridfield => $newuser->getId() );
131 - $extraCondsNoUid = array( $useridfield => 0 );
132 - # uid in rows is set properly, use as cond to find rows, don't bother to update it
133 - if (! $doUid) {
134 - $selectConds = array_merge( $selectConds, $extraConds );
135 - $updateConds = array_merge( $updateConds, $extraConds );
136 - }
137 - # uid in edit rows is 0, we will set it and we will only update rows with 0 uid and the old user name
138 - else {
139 - $selectConds = array_merge( $selectConds, $extraCondsNoUid );
140 - $updateConds = array_merge( $updateConds, $extraCondsNoUid );
141 - $updateFields = array_merge( $updateFields, $extraConds );
142 - }
143 -
144 - while ($contribs > 0) {
145 - print("doing batch of up to approximately ".self::BATCH_SIZE."\n");
146 - print("do this batch? [N/y] ");
147 - $stdin = fopen ("php://stdin","rt");
148 - $line = fgets($stdin);
149 - fclose($stdin);
150 - if ( $line[0] != "Y" && $line[0] != "y" ) {
151 - print("skipping at user's request\n");
152 - return(0);
153 - }
154 - $dbw->begin();
155 - $result = $dbw->select( $table, $timestampfield, $selectConds , __METHOD__,
156 - array( 'ORDER BY' => $timestampfield.' DESC', 'LIMIT' => self::BATCH_SIZE ) );
157 - if (! $result) {
158 - print("There were rows for updating but now they are gone. Skipping.\n");
159 - $db->rollback();
160 - return(0);
161 - }
162 - $result->seek($result->numRows() -1 );
163 - $row = $result->fetchObject();
164 - $timestamp = $row->$timestampfield;
165 - $updateCondsWithTime = array_merge( $updateConds, array ("$timestampfield >= $timestamp") );
166 - $success = $dbw->update( $table, $updateFields, $updateCondsWithTime, __METHOD__ );
167 - if ($success) {
168 - $rowsDone = $dbw->affectedRows();
169 - $dbw->commit();
170 - }
171 - else {
172 - print("problem with the update, rolling back and exiting\n");
173 - $db->rollback();
174 - exit(1);
175 - }
176 - $contribs = User::edits( $olduser->getId() );
177 - $contribs = $dbw->selectField( $table, 'count(*)', $selectConds, __METHOD__ );
178 - print("updated $rowsDone edits; $contribs edits remaining to be re-attributed\n");
179 - }
180 - return(0);
181 - }
182 -
183 -}
184 -
185 -$maintClass = "RenameUserCleanup";
186 -require_once( RUN_MAINTENANCE_IF_MAIN );
Index: trunk/extensions/Renameuser/renameUserCleanup.php
@@ -0,0 +1,189 @@
 2+<?php
 3+/**
 4+ * Maintenance script to clean up after incomplete user renames
 5+ * Sometimes user edits are left lying around under the old name,
 6+ * check for that and assign them to the new username
 7+ *
 8+ * This program is free software; you can redistribute it and/or modify
 9+ * it under the terms of the GNU General Public License as published by
 10+ * the Free Software Foundation; either version 2 of the License, or
 11+ * (at your option) any later version.
 12+ *
 13+ * This program is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 16+ * GNU General Public License for more details.
 17+ *
 18+ * You should have received a copy of the GNU General Public License along
 19+ * with this program; if not, write to the Free Software Foundation, Inc.,
 20+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 21+ * http://www.gnu.org/copyleft/gpl.html
 22+ *
 23+ * @ingroup Maintenance
 24+ * @author Ariel Glenn <ariel@wikimedia.orf>
 25+ */
 26+
 27+$IP = getenv( 'MW_INSTALL_PATH' );
 28+if ( $IP === false ) {
 29+ $IP = dirname( __FILE__ ) . '/../..';
 30+}
 31+require( "$IP/maintenance/Maintenance.php" );
 32+
 33+class RenameUserCleanup extends Maintenance {
 34+ const BATCH_SIZE = 1000;
 35+
 36+ public function __construct() {
 37+ parent::__construct();
 38+ $this->mDescription = "Maintenance script to finish incomplete rename user, in particular to reassign edits that were missed";
 39+ $this->addOption( 'olduser', 'Old user name', true, true );
 40+ $this->addOption( 'newuser', 'New user name', true, true );
 41+ }
 42+
 43+ public function execute() {
 44+ $this->output( "Rename User Cleanup starting...\n\n" );
 45+ $olduser = User::newFromName( $this->getOption( 'olduser' ) );
 46+ $newuser = User::newFromName( $this->getOption( 'newuser' ) );
 47+ if ( !$newuser->getId() ) {
 48+ $this->error( "No such user: " . $this->getOption( 'newuser' ), true );
 49+ exit(1);
 50+ }
 51+ if ($olduser->getId() ) {
 52+ print( "WARNING!!: Old user still exists: " . $this->getOption( 'olduser' ) . "\n");
 53+ print("proceed anyways? We'll only re-attribute edits that have the new user uid (or 0) and the old user name. [N/y] ");
 54+ $stdin = fopen ("php://stdin","rt");
 55+ $line = fgets($stdin);
 56+ fclose($stdin);
 57+ if ( $line[0] != "Y" && $line[0] != "y" ) {
 58+ print("Exiting at user's request\n");
 59+ exit(0);
 60+ }
 61+ }
 62+
 63+ $dbr = wfGetDB( DB_SLAVE );
 64+ $result = $dbr->select( 'logging', '*',
 65+ array( 'log_type' => 'renameuser',
 66+ 'log_action' => 'renameuser',
 67+ 'log_title' => $olduser->getName(),
 68+ 'log_params' => $newuser->getName()
 69+ ),
 70+ __METHOD__
 71+ );
 72+ if (! $result ) {
 73+ print("No log entry found for a rename of ".$olduser->getName()." to ".$newuser->getName().", giving up\n");
 74+ exit(1);
 75+ }
 76+ foreach ( $result as $row ) {
 77+ print("Found log entry of the rename: ".$olduser->getName()." to ".$newuser->getName()." on $row->log_timestamp\n");
 78+ }
 79+ if ($result->numRows() > 1) {
 80+ print("More than one rename entry found in the log, not sure what to do. Continue anyways? [N/y] ");
 81+ $stdin = fopen ("php://stdin","rt");
 82+ $line = fgets($stdin);
 83+ fclose($stdin);
 84+ if ( $line[0] != "Y" && $line[0] != "y" ) {
 85+ print("Exiting at user's request\n");
 86+ exit(1);
 87+ }
 88+ }
 89+ $dbw = wfGetDB( DB_MASTER );
 90+
 91+ $this->updateTable('revision', 'rev_user_text', 'rev_user', 'rev_timestamp', $olduser, $newuser, $dbw);
 92+ $this->updateTable('archive', 'ar_user_text', 'ar_user', 'ar_timestamp', $olduser, $newuser, $dbw);
 93+ $this->updateTable('logging', 'log_user_text', 'log_user', 'log_timestamp', $olduser, $newuser, $dbw);
 94+ $this->updateTable('image', 'img_user_text', 'img_user', 'img_timestamp', $olduser, $newuser, $dbw);
 95+ $this->updateTable('oldimage', 'oi_user_text', 'oi_user', 'oi_timestamp', $olduser, $newuser, $dbw);
 96+# FIXME: updateTable('filearchive', 'fa_user_text','fa_user', 'fa_timestamp', $olduser, $newuser, $dbw); (not indexed yet)
 97+ print "Done!\n";
 98+ exit(0);
 99+ }
 100+
 101+ public function updateTable($table,$usernamefield,$useridfield,$timestampfield,$olduser,$newuser,$dbw) {
 102+ $doUid = 0;
 103+
 104+ $contribs = $dbw->selectField( $table, 'count(*)',
 105+ array( $usernamefield => $olduser->getName(), $useridfield => $newuser->getId() ), __METHOD__ );
 106+ if ($contribs == 0) {
 107+ $contribs = $dbw->selectField( $table, 'count(*)',
 108+ array( $usernamefield => $olduser->getName(), $useridfield => 0 ), __METHOD__ );
 109+ if ($contribs > 0) {
 110+ print("Found $contribs edits to be re-attributed from table $table but the uid present is 0 (should be ".$newuser->getId().")\n");
 111+ print("If you proceed, the uid field will be set to that of the new user name (i.e. ".$newuser->getId().") in these rows.\n");
 112+ $doUid = 1;
 113+ }
 114+ else {
 115+ print("No edits to be re-attributed from table $table\n");
 116+ return(0);
 117+ }
 118+ }
 119+ else {
 120+ print("total number of edits to be re-attributed from table $table: $contribs\n");
 121+ }
 122+ print("proceed? [N/y] ");
 123+ $stdin = fopen ("php://stdin","rt");
 124+ $line = fgets($stdin);
 125+ fclose($stdin);
 126+ if ( $line[0] != "Y" && $line[0] != "y" ) {
 127+ print("skipping at user's request\n");
 128+ return(0);
 129+ }
 130+ $selectConds = array( $usernamefield => $olduser->getName() );
 131+ $updateFields = array( $usernamefield => $newuser->getName() );
 132+ $updateConds = array( $usernamefield => $olduser->getName() );
 133+
 134+ $extraConds = array( $useridfield => $newuser->getId() );
 135+ $extraCondsNoUid = array( $useridfield => 0 );
 136+ # uid in rows is set properly, use as cond to find rows, don't bother to update it
 137+ if (! $doUid) {
 138+ $selectConds = array_merge( $selectConds, $extraConds );
 139+ $updateConds = array_merge( $updateConds, $extraConds );
 140+ }
 141+ # uid in edit rows is 0, we will set it and we will only update rows with 0 uid and the old user name
 142+ else {
 143+ $selectConds = array_merge( $selectConds, $extraCondsNoUid );
 144+ $updateConds = array_merge( $updateConds, $extraCondsNoUid );
 145+ $updateFields = array_merge( $updateFields, $extraConds );
 146+ }
 147+
 148+ while ($contribs > 0) {
 149+ print("doing batch of up to approximately ".self::BATCH_SIZE."\n");
 150+ print("do this batch? [N/y] ");
 151+ $stdin = fopen ("php://stdin","rt");
 152+ $line = fgets($stdin);
 153+ fclose($stdin);
 154+ if ( $line[0] != "Y" && $line[0] != "y" ) {
 155+ print("skipping at user's request\n");
 156+ return(0);
 157+ }
 158+ $dbw->begin();
 159+ $result = $dbw->select( $table, $timestampfield, $selectConds , __METHOD__,
 160+ array( 'ORDER BY' => $timestampfield.' DESC', 'LIMIT' => self::BATCH_SIZE ) );
 161+ if (! $result) {
 162+ print("There were rows for updating but now they are gone. Skipping.\n");
 163+ $db->rollback();
 164+ return(0);
 165+ }
 166+ $result->seek($result->numRows() -1 );
 167+ $row = $result->fetchObject();
 168+ $timestamp = $row->$timestampfield;
 169+ $updateCondsWithTime = array_merge( $updateConds, array ("$timestampfield >= $timestamp") );
 170+ $success = $dbw->update( $table, $updateFields, $updateCondsWithTime, __METHOD__ );
 171+ if ($success) {
 172+ $rowsDone = $dbw->affectedRows();
 173+ $dbw->commit();
 174+ }
 175+ else {
 176+ print("problem with the update, rolling back and exiting\n");
 177+ $db->rollback();
 178+ exit(1);
 179+ }
 180+ $contribs = User::edits( $olduser->getId() );
 181+ $contribs = $dbw->selectField( $table, 'count(*)', $selectConds, __METHOD__ );
 182+ print("updated $rowsDone edits; $contribs edits remaining to be re-attributed\n");
 183+ }
 184+ return(0);
 185+ }
 186+
 187+}
 188+
 189+$maintClass = "RenameUserCleanup";
 190+require_once( RUN_MAINTENANCE_IF_MAIN );
Property changes on: trunk/extensions/Renameuser/renameUserCleanup.php
___________________________________________________________________
Added: svn:eol-style
1191 + native

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r91832fix issues after failed renameUser; this script will ask for lots of confirma...ariel14:20, 10 July 2011

Status & tagging log