26$IP = getenv(
'MW_INSTALL_PATH' );
28 $IP = __DIR__ .
'/../../..';
30require_once
"$IP/maintenance/Maintenance.php";
34 parent::__construct();
35 $this->
addDescription(
'Maintenance script to finish incomplete rename user,'
36 .
' in particular to reassign edits that were missed' );
37 $this->
addOption(
'olduser',
'Old user name',
true,
true );
38 $this->
addOption(
'newuser',
'New user name',
true,
true );
39 $this->
addOption(
'olduid',
'Old user id in revision records (DANGEROUS)',
false,
true );
47 $this->
output(
"Core xx_user_text fields are no longer used, no updates should be needed.\n" );
51 $this->
output(
"Rename User Cleanup starting...\n\n" );
60 $this->
doUpdates( $olduser, $newuser, $olduid );
62 $this->
doUpdates( $olduser, $newuser, $newuser->getId() );
63 $this->
doUpdates( $olduser, $newuser, 0 );
65 $this->
output(
"Done!\n" );
73 if ( !$newuser->getId() ) {
74 $this->
error(
'No such user: ' . $this->
getOption(
'newuser' ),
true );
76 if ( $olduser->getId() ) {
77 $this->
output(
'WARNING!!: Old user still exists: ' . $this->
getOption(
'olduser' ) .
"\n" );
78 $this->
output(
'We\'ll only re-attribute edits that have the new user uid (or 0) ' );
79 $this->
output(
'or the uid specified by the caller, and the old user name.' );
80 $this->
output(
'Proceed anyway? [N/y] ' );
82 $stdin = fopen(
'php://stdin',
'rt' );
83 $line = fgets( $stdin );
87 $this->
output(
"Exiting at users request\n" );
99 $oldTitle = Title::makeTitle( NS_USER, $olduser->getName() );
101 $result =
$dbr->select(
'logging',
'*',
102 [
'log_type' =>
'renameuser',
103 'log_action' =>
'renameuser',
104 'log_namespace' => NS_USER,
106 'log_params' => $newuser->getName()
110 if ( !$result || !$result->numRows() ) {
112 if ( class_exists( CommentStore::class ) ) {
113 $commentStore = CommentStore::getStore();
114 $commentQuery = $commentStore->getJoin(
'log_comment' );
116 $commentStore =
null;
119 'fields' => [
'log_comment' =>
'log_comment' ],
123 $result =
$dbr->select(
124 [
'logging' ] + $commentQuery[
'tables'],
125 [
'log_title',
'log_timestamp' ] + $commentQuery[
'fields'],
127 'log_type' =>
'renameuser',
128 'log_action' =>
'renameuser',
129 'log_namespace' => NS_USER,
130 'log_title' => $olduser->getName(),
134 $commentQuery[
'joins']
136 if ( !$result || !$result->numRows() ) {
137 $this->
output(
'No log entry found for a rename of ' . $olduser->getName() .
138 ' to ' . $newuser->getName() .
', proceed anyways? [N/y] ' );
140 $stdin = fopen(
'php://stdin',
'rt' );
141 $line = fgets( $stdin );
145 $this->
output(
"Exiting at user's request\n" );
149 foreach ( $result as $row ) {
150 $comment = $commentStore
151 ? $commentStore->getComment(
'log_comment', $row )->text
153 $this->
output(
'Found possible log entry of the rename, please check: ' .
154 $row->log_title .
' with comment ' . $comment .
155 " on $row->log_timestamp\n" );
159 foreach ( $result as $row ) {
160 $this->
output(
'Found log entry of the rename: ' . $olduser->getName() .
161 ' to ' . $newuser->getName() .
" on $row->log_timestamp\n" );
164 if ( $result && $result->numRows() > 1 ) {
165 print 'More than one rename entry found in the log, not sure ' .
166 'what to do. Proceed anyways? [N/y] ';
168 $stdin = fopen(
'php://stdin',
'rt' );
169 $line = fgets( $stdin );
173 $this->
output(
"Exiting at users request\n" );
250 public function updateTable( $table, $usernamefield, $useridfield,
251 $timestampfield, $olduser, $newuser, $uid
255 $contribs = $dbw->selectField(
259 $usernamefield => $olduser->getName(),
265 if ( $contribs === 0 ) {
266 $this->
output(
"No edits to be re-attributed from table $table for uid $uid\n" );
271 $this->
output(
"Found $contribs edits to be re-attributed from table $table for uid $uid\n" );
272 if ( $uid !== $newuser->getId() ) {
273 $this->
output(
'If you proceed, the uid field will be set to that ' .
274 'of the new user name (i.e. ' . $newuser->getId() .
") in these rows.\n" );
277 $this->
output(
'Proceed? [N/y] ' );
279 $stdin = fopen(
'php://stdin',
'rt' );
280 $line = fgets( $stdin );
284 $this->
output(
"Skipping at user's request\n" );
288 $selectConds = [ $usernamefield => $olduser->getName(), $useridfield => $uid ];
289 $updateFields = [ $usernamefield => $newuser->getName(), $useridfield => $newuser->getId() ];
291 while ( $contribs > 0 ) {
292 $this->
output(
'Doing batch of up to approximately ' . $this->mBatchSize .
"\n" );
293 $this->
output(
'Do this batch? [N/y] ' );
295 $stdin = fopen(
'php://stdin',
'rt' );
296 $line = fgets( $stdin );
300 $this->
output(
"Skipping at user's request\n" );
305 $result = $dbw->select(
311 'ORDER BY' => $timestampfield .
' DESC',
312 'LIMIT' => $this->mBatchSize
317 $this->
output(
"There were rows for updating but now they are gone. Skipping.\n" );
323 $result->seek( $result->numRows() - 1 );
324 $row = $result->fetchObject();
325 $timestamp = $dbw->addQuotes( $row->$timestampfield );
326 $updateCondsWithTime = array_merge( $selectConds, [
"$timestampfield >= $timestamp" ] );
330 $updateCondsWithTime,
335 $rowsDone = $dbw->affectedRows();
339 $this->
error(
"Problem with the update, rolling back and exiting\n",
true );
343 $contribs = $dbw->selectField( $table,
'count(*)', $selectConds, __METHOD__ );
344 $this->
output(
"Updated $rowsDone edits; $contribs edits remaining to be re-attributed\n" );
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
requireExtension( $name)
Indicate that the specified extension must be loaded before the script can run.
beginTransaction(IDatabase $dbw, $fname)
Begin a transcation on a DB.
commitTransaction(IDatabase $dbw, $fname)
Commit the transcation on a DB handle and wait for replica DBs to catch up.
output( $out, $channel=null)
Throw some output to the user.
addDescription( $text)
Set the description text.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
getOption( $name, $default=null)
Get an option, or return the default.
rollbackTransaction(IDatabase $dbw, $fname)
Rollback the transcation on a DB handle.
setBatchSize( $s=0)
Set the batch size.
__construct()
Default constructor.
checkUserExistence( $olduser, $newuser)
doUpdates( $olduser, $newuser, $uid)
updateTable( $table, $usernamefield, $useridfield, $timestampfield, $olduser, $newuser, $uid)
execute()
Do the actual work.
checkRenameLog( $olduser, $newuser)
static getActorMigrationStage()
Fetch the core actor table schema migration stage.
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults error
while(( $__line=Maintenance::readconsole()) !==false) print
$IP
Maintenance script to clean up after incomplete user renames Sometimes user edits are left lying arou...
require_once RUN_MAINTENANCE_IF_MAIN