MediaWiki  master
fixMergeHistoryCorruption.php
Go to the documentation of this file.
1 <?php
22 require_once __DIR__ . '/Maintenance.php';
23 
40 
41  public function __construct() {
42  parent::__construct();
43  $this->addDescription( 'Delete pages corrupted by MergeHistory' );
44  $this->addOption( 'ns', 'Namespace to restrict the query', false, true );
45  $this->addOption( 'dry-run', 'Run in dry-mode' );
46  $this->addOption( 'delete', 'Actually delete the found rows' );
47  }
48 
49  public function execute() {
50  $dbr = $this->getDB( DB_REPLICA );
51  $dbw = $this->getDB( DB_PRIMARY );
52 
53  $dryRun = true;
54  if ( $this->hasOption( 'dry-run' ) && $this->hasOption( 'delete' ) ) {
55  $this->fatalError( 'Cannot do both --dry-run and --delete.' );
56  } elseif ( $this->hasOption( 'delete' ) ) {
57  $dryRun = false;
58  } elseif ( !$this->hasOption( 'dry-run' ) ) {
59  $this->fatalError( 'Either --dry-run or --delete must be specified.' );
60  }
61 
62  $conds = [ 'page_id<>rev_page' ];
63  if ( $this->hasOption( 'ns' ) ) {
64  $conds['page_namespace'] = (int)$this->getOption( 'ns' );
65  }
66 
67  $res = $dbr->newSelectQueryBuilder()
68  ->from( 'page' )
69  ->join( 'revision', null, 'page_latest=rev_id' )
70  ->fields( [ 'page_namespace', 'page_title', 'page_id' ] )
71  ->where( $conds )
72  ->caller( __METHOD__ )
73  ->fetchResultSet();
74 
75  $count = $res->numRows();
76 
77  if ( !$count ) {
78  $this->output( "Nothing was found, no page matches the criteria.\n" );
79  return;
80  }
81 
82  $numDeleted = 0;
83  $numUpdated = 0;
84 
85  foreach ( $res as $row ) {
86  $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
87  if ( !$title ) {
88  $this->output( "Skipping invalid title with page_id: $row->page_id\n" );
89  continue;
90  }
91  $titleText = $title->getPrefixedDBkey();
92 
93  // Check if there are any revisions that have this $row->page_id as their
94  // rev_page and select the largest which should be the newest revision.
95  $revId = $dbr->selectField(
96  'revision',
97  'MAX(rev_id)',
98  [ 'rev_page' => $row->page_id ],
99  __METHOD__
100  );
101 
102  if ( !$revId ) {
103  if ( $dryRun ) {
104  $this->output( "Would delete $titleText with page_id: $row->page_id\n" );
105  } else {
106  $this->output( "Deleting $titleText with page_id: $row->page_id\n" );
107  $dbw->delete( 'page', [ 'page_id' => $row->page_id ], __METHOD__ );
108  }
109  $numDeleted++;
110  } else {
111  if ( $dryRun ) {
112  $this->output( "Would update page_id $row->page_id to page_latest $revId\n" );
113  } else {
114  $this->output( "Updating page_id $row->page_id to page_latest $revId\n" );
115  $dbw->update(
116  'page',
117  [ 'page_latest' => $revId ],
118  [ 'page_id' => $row->page_id ],
119  __METHOD__
120  );
121  }
122  $numUpdated++;
123  }
124  }
125 
126  if ( !$dryRun ) {
127  $this->output( "Updated $numUpdated row(s), deleted $numDeleted row(s)\n" );
128  }
129  }
130 }
131 
132 $maintClass = FixMergeHistoryCorruption::class;
133 require_once RUN_MAINTENANCE_IF_MAIN;
Maintenance\fatalError
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
Definition: Maintenance.php:489
Maintenance\addDescription
addDescription( $text)
Set the description text.
Definition: Maintenance.php:329
Maintenance
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: Maintenance.php:59
$res
$res
Definition: testCompression.php:57
$dbr
$dbr
Definition: testCompression.php:54
FixMergeHistoryCorruption\execute
execute()
Do the actual work.
Definition: fixMergeHistoryCorruption.php:49
Maintenance\addOption
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
Definition: Maintenance.php:249
$title
$title
Definition: testCompression.php:38
FixMergeHistoryCorruption\__construct
__construct()
Default constructor.
Definition: fixMergeHistoryCorruption.php:41
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
FixMergeHistoryCorruption
Maintenance script that clears rows of pages corrupted by MergeHistory, those pages 'exist' but have ...
Definition: fixMergeHistoryCorruption.php:39
$maintClass
$maintClass
Definition: fixMergeHistoryCorruption.php:132
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:677
DB_PRIMARY
const DB_PRIMARY
Definition: defines.php:27
Maintenance\getDB
getDB( $db, $groups=[], $dbDomain=false)
Returns a database to be used by current maintenance script.
Definition: Maintenance.php:1362
Maintenance\getOption
getOption( $name, $default=null)
Get an option, or return the default.
Definition: Maintenance.php:286
Maintenance\output
output( $out, $channel=null)
Throw some output to the user.
Definition: Maintenance.php:435
Maintenance\hasOption
hasOption( $name)
Checks to see if a particular option was set.
Definition: Maintenance.php:271