56 $this->db = $database;
64 private function out( $str ) {
65 call_user_func( $this->outputCallback, $str );
74 $info = $this->db->indexInfo(
'user',
'user_name', __METHOD__ );
76 $this->
out(
"WARNING: doesn't seem to have user_name index at all!\n" );
81 # Confusingly, 'Non_unique' is 0 for *unique* indexes,
82 # and 1 for *non-unique* indexes. Pass the crack, MySQL,
83 # it's obviously some good stuff!
84 return ( $info[0]->Non_unique == 0 );
117 $dbDomain = WikiMap::getCurrentWikiDbDomain()->getId();
119 echo
"$dbDomain already has a unique index on its user table.\n";
126 $this->
out(
"Checking for duplicate accounts...\n" );
128 $count = count( $dupes );
130 $this->
out(
"Found $count accounts with duplicate records on $dbDomain.\n" );
132 $this->reassigned = 0;
134 foreach ( $dupes as $name ) {
135 $this->
examine( $name, $doDelete );
143 if ( $this->reassigned > 0 ) {
145 $this->
out(
"$this->reassigned duplicate accounts had edits "
146 .
"reassigned to a canonical record id.\n" );
148 $this->
out(
"$this->reassigned duplicate accounts need to have edits reassigned.\n" );
153 if ( $this->trimmed > 0 ) {
156 "$this->trimmed duplicate user records were deleted from $dbDomain.\n" );
159 "$this->trimmed duplicate user accounts were found on $dbDomain " .
160 "which can be removed safely.\n"
166 if ( $this->failed > 0 ) {
167 $this->
out(
"Something terribly awry; $this->failed duplicate accounts were not removed.\n" );
173 if ( $this->trimmed == 0 || $doDelete ) {
174 $this->
out(
"It is now safe to apply the unique index on user_name.\n" );
178 $this->
out(
"Run this script again with the --fix option to automatically delete them.\n" );
188 $set = [
'user',
'revision' ];
189 $names = array_map( [ $this,
'lockTable' ], $set );
190 $tables = implode(
',', $names );
192 $this->db->query(
"LOCK TABLES $tables", __METHOD__ );
196 return $this->db->tableName( $table ) .
' WRITE';
203 $this->db->query(
"UNLOCK TABLES", __METHOD__ );
211 $user = $this->db->tableName(
'user' );
212 $result = $this->db->query(
213 "SELECT user_name,COUNT(*) AS n
216 HAVING n > 1", __METHOD__ );
219 foreach ( $result as $row ) {
220 $list[] = $row->user_name;
233 private function examine( $name, $doDelete ) {
234 $result = $this->db->select(
'user',
236 [
'user_name' => $name ],
239 $firstRow = $this->db->fetchObject( $result );
240 $firstId = $firstRow->user_id;
241 $this->
out(
"Record that will be used for '$name' is user_id=$firstId\n" );
243 foreach ( $result as $row ) {
244 $dupeId = $row->user_id;
245 $this->
out(
"... dupe id $dupeId: " );
249 $this->
out(
"has $edits edits! " );
253 if ( $newEdits == 0 ) {
254 $this->
out(
"confirmed cleaned. " );
257 $this->
out(
"WARNING! $newEdits remaining edits for $dupeId; NOT deleting user.\n" );
261 $this->
out(
"(will need to reassign edits on fix)" );
264 $this->
out(
"ok, no edits. " );
282 return intval( $this->db->selectField(
285 [
'rev_user' => $userid ],
294 $this->
out(
'reassigning... ' );
295 $this->db->update(
'revision',
296 [
'rev_user' => $to ],
297 [
'rev_user' => $from ],
299 $this->
out(
"ok. " );
307 $this->
out(
"deleting..." );
308 $this->db->delete(
'user', [
'user_id' => $userid ], __METHOD__ );
Look for duplicate user table entries and optionally prune them.
lock()
We don't want anybody to mess with our stuff...
editCount( $userid)
Count the number of edits attributed to this user.
__construct(&$database, $outputCallback)
getDupes()
Grab usernames for which multiple records are present in the database.
examine( $name, $doDelete)
Examine user records for the given name.
trimAccount( $userid)
Remove a user account line.
out( $str)
Output some text via the output callback provided.
IMaintainableDatabase $db
checkDupes( $doDelete=false)
Checks the database for duplicate user account records in preparation for application of a unique ind...
clearDupes()
Checks the database for duplicate user account records and remove them in preparation for application...
reassignEdits( $from, $to)
hasUniqueIndex()
Check if this database's user table has already had a unique user_name index applied.
Advanced database interface for IDatabase handles that include maintenance methods.