MediaWiki master
fixAutoblockLogTitles.php
Go to the documentation of this file.
1<?php
2
4
8
9// @codeCoverageIgnoreStart
10require_once __DIR__ . '/Maintenance.php';
11// @codeCoverageIgnoreEnd
12
14
15 public function __construct() {
16 parent::__construct();
17 $this->addDescription(
18 'Finds and fixes unblock log rows in the logging table where the log_title starts with the ' .
19 'prefix "User:#". These rows are broken because the target is an autoblock and code expects the "#" ' .
20 'character to be the first character in the title (T373929).'
21 );
22 $this->setBatchSize( 200 );
23 }
24
26 protected function doDBUpdates() {
27 $this->output( "Fixing log entries with log_title starting with 'User:#'\n" );
28
29 $dbr = $this->getReplicaDB();
30 $dbw = $this->getPrimaryDB();
31
32 $totalRowsFixed = 0;
33 $lastProcessedLogId = 0;
34 do {
35 // Get a batch of "unblock" log entries from the logging table. The check for the log_title being broken
36 // needs to be performed in batches, as it is expensive when run on the whole logging table on large wikis.
37 $logIds = $dbr->newSelectQueryBuilder()
38 ->select( 'log_id' )
39 ->from( 'logging' )
40 ->where( [
41 'log_type' => 'block',
42 'log_action' => 'unblock',
43 $dbr->expr( 'log_id', '>', $lastProcessedLogId ),
44 ] )
45 ->limit( $this->getBatchSize() )
46 ->orderBy( 'log_id', SelectQueryBuilder::SORT_ASC )
47 ->caller( __METHOD__ )
48 ->fetchFieldValues();
49
50 if ( count( $logIds ) ) {
51 $lastId = end( $logIds );
52 $firstId = reset( $logIds );
53 $this->output( "...Processing unblock rows with IDs $firstId to $lastId\n" );
54
55 // Apply the LIKE query to find the rows with broken log_title values on the batch of log IDs.
56 // If any rows are found, then fix the log_title value.
57 $matchingRows = $dbr->newSelectQueryBuilder()
58 ->select( [ 'log_id', 'log_title' ] )
59 ->from( 'logging' )
60 ->where( $dbr->expr(
61 'log_title',
62 IExpression::LIKE,
63 new LikeValue( 'User:#', $dbr->anyString() )
64 ) )
65 ->andWhere( [ 'log_id' => $logIds ] )
66 ->limit( $this->getBatchSize() )
67 ->caller( __METHOD__ )
68 ->fetchResultSet();
69
70 foreach ( $matchingRows as $row ) {
71 $dbw->newUpdateQueryBuilder()
72 ->update( 'logging' )
73 ->set( [ 'log_title' => substr( $row->log_title, strlen( 'User:' ) ) ] )
74 ->where( [ 'log_id' => $row->log_id ] )
75 ->caller( __METHOD__ )
76 ->execute();
77 $totalRowsFixed += $dbw->affectedRows();
78 }
79
80 $this->waitForReplication();
81 }
82
83 $lastProcessedLogId = end( $logIds );
84 } while ( count( $logIds ) );
85
86 // Say we are done. Only output the total rows fixed if we found rows to fix, otherwise it may be confusing
87 // to see that no rows were fixed (and might imply that there are still rows to fix).
88 $this->output( "done." );
89 if ( $totalRowsFixed ) {
90 $this->output( " Fixed $totalRowsFixed rows." );
91 }
92 $this->output( "\n" );
93
94 return true;
95 }
96
98 protected function getUpdateKey() {
99 return __CLASS__;
100 }
101}
102
103// @codeCoverageIgnoreStart
104$maintClass = FixAutoblockLogTitles::class;
105require_once RUN_MAINTENANCE_IF_MAIN;
106// @codeCoverageIgnoreEnd
doDBUpdates()
Do the actual work.All child classes will need to implement this. Return true to log the update as do...
getUpdateKey()
Get the update key name to go in the update log table.string
Class for scripts that perform database maintenance and want to log the update in updatelog so we can...
getBatchSize()
Returns batch size.
output( $out, $channel=null)
Throw some output to the user.
waitForReplication()
Wait for replica DB servers to catch up.
addDescription( $text)
Set the description text.
Content of like value.
Definition LikeValue.php:14
Build SELECT queries with a fluent interface.
Update the CREDITS list by merging in the list of git commit authors.