Index: trunk/phase3/maintenance/cleanupWatchlist.php |
— | — | @@ -0,0 +1,141 @@ |
| 2 | +<?php |
| 3 | +/* |
| 4 | + * Script to remove broken, unparseable titles in the Watchlist. |
| 5 | + * |
| 6 | + * Usage: php cleanupWatchlist.php [--fix] |
| 7 | + * Options: |
| 8 | + * --fix Actually remove entries; without will only report. |
| 9 | + * |
| 10 | + * Copyright (C) 2005,2006 Brion Vibber <brion@pobox.com> |
| 11 | + * http://www.mediawiki.org/ |
| 12 | + * |
| 13 | + * This program is free software; you can redistribute it and/or modify |
| 14 | + * it under the terms of the GNU General Public License as published by |
| 15 | + * the Free Software Foundation; either version 2 of the License, or |
| 16 | + * (at your option) any later version. |
| 17 | + * |
| 18 | + * This program is distributed in the hope that it will be useful, |
| 19 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 20 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 21 | + * GNU General Public License for more details. |
| 22 | + * |
| 23 | + * You should have received a copy of the GNU General Public License along |
| 24 | + * with this program; if not, write to the Free Software Foundation, Inc., |
| 25 | + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 26 | + * http://www.gnu.org/copyleft/gpl.html |
| 27 | + * |
| 28 | + * @author Brion Vibber <brion at pobox.com> |
| 29 | + * @package MediaWiki |
| 30 | + * @subpackage maintenance |
| 31 | + */ |
| 32 | + |
| 33 | +$options = array( 'fix' ); |
| 34 | + |
| 35 | +require_once( 'commandLine.inc' ); |
| 36 | +require_once( 'FiveUpgrade.inc' ); |
| 37 | + |
| 38 | +class WatchlistCleanup extends FiveUpgrade { |
| 39 | + function WatchlistCleanup( $dryrun = false ) { |
| 40 | + parent::FiveUpgrade(); |
| 41 | + |
| 42 | + $this->maxLag = 10; # if slaves are lagged more than 10 secs, wait |
| 43 | + $this->dryrun = $dryrun; |
| 44 | + } |
| 45 | + |
| 46 | + function cleanup() { |
| 47 | + $this->runTable( 'watchlist', |
| 48 | + '', |
| 49 | + array( &$this, 'processEntry' ) ); |
| 50 | + } |
| 51 | + |
| 52 | + function init( $count, $table ) { |
| 53 | + $this->processed = 0; |
| 54 | + $this->updated = 0; |
| 55 | + $this->count = $count; |
| 56 | + $this->startTime = wfTime(); |
| 57 | + $this->table = $table; |
| 58 | + } |
| 59 | + |
| 60 | + function progress( $updated ) { |
| 61 | + $this->updated += $updated; |
| 62 | + $this->processed++; |
| 63 | + if( $this->processed % 100 != 0 ) { |
| 64 | + return; |
| 65 | + } |
| 66 | + $portion = $this->processed / $this->count; |
| 67 | + $updateRate = $this->updated / $this->processed; |
| 68 | + |
| 69 | + $now = wfTime(); |
| 70 | + $delta = $now - $this->startTime; |
| 71 | + $estimatedTotalTime = $delta / $portion; |
| 72 | + $eta = $this->startTime + $estimatedTotalTime; |
| 73 | + |
| 74 | + global $wgDBname; |
| 75 | + printf( "%s %s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec <%.2f%% updated>\n", |
| 76 | + $wgDBname, |
| 77 | + wfTimestamp( TS_DB, intval( $now ) ), |
| 78 | + $portion * 100.0, |
| 79 | + $this->table, |
| 80 | + wfTimestamp( TS_DB, intval( $eta ) ), |
| 81 | + $this->processed, |
| 82 | + $this->count, |
| 83 | + $this->processed / $delta, |
| 84 | + $updateRate * 100.0 ); |
| 85 | + flush(); |
| 86 | + } |
| 87 | + |
| 88 | + function runTable( $table, $where, $callback ) { |
| 89 | + $fname = 'WatchlistCleanup::runTable'; |
| 90 | + |
| 91 | + $count = $this->dbw->selectField( $table, 'count(*)', '', $fname ); |
| 92 | + $this->init( $count, 'watchlist' ); |
| 93 | + $this->log( "Processing $table..." ); |
| 94 | + |
| 95 | + $tableName = $this->dbr->tableName( $table ); |
| 96 | + $sql = "SELECT * FROM $tableName $where"; |
| 97 | + $result = $this->dbr->query( $sql, $fname ); |
| 98 | + |
| 99 | + while( $row = $this->dbr->fetchObject( $result ) ) { |
| 100 | + $updated = call_user_func( $callback, $row ); |
| 101 | + } |
| 102 | + $this->log( "Finished $table... $this->updated of $this->processed rows updated" ); |
| 103 | + $this->dbr->freeResult( $result ); |
| 104 | + } |
| 105 | + |
| 106 | + function processEntry( $row ) { |
| 107 | + global $wgContLang; |
| 108 | + |
| 109 | + $current = Title::makeTitle( $row->wl_namespace, $row->wl_title ); |
| 110 | + $display = $current->getPrefixedText(); |
| 111 | + |
| 112 | + $verified = UtfNormal::cleanUp( $display ); |
| 113 | + |
| 114 | + $title = Title::newFromText( $verified ); |
| 115 | + |
| 116 | + if( $row->wl_user == 0 || is_null( $title ) || !$title->equals( $current ) ) { |
| 117 | + $this->log( "invalid watch by {$row->wl_user} for ({$row->wl_namespace}, \"{$row->wl_title}\")" ); |
| 118 | + $this->removeWatch( $row ); |
| 119 | + return $this->progress( 1 ); |
| 120 | + } |
| 121 | + |
| 122 | + $this->progress( 0 ); |
| 123 | + } |
| 124 | + |
| 125 | + function removeWatch( $row ) { |
| 126 | + if( !$this->dryrun) { |
| 127 | + $dbw =& wfGetDB( DB_MASTER ); |
| 128 | + $dbw->delete( 'watchlist', array( |
| 129 | + 'wl_user' => $row->wl_user, |
| 130 | + 'wl_namespace' => $row->wl_namespace, |
| 131 | + 'wl_title' => $row->wl_title ), |
| 132 | + 'WatchlistCleanup::removeWatch' ); |
| 133 | + $this->log( '- removed' ); |
| 134 | + } |
| 135 | + } |
| 136 | +} |
| 137 | + |
| 138 | +$wgUser->setName( 'Conversion script' ); |
| 139 | +$caps = new WatchlistCleanup( !isset( $options['fix'] ) ); |
| 140 | +$caps->cleanup(); |
| 141 | + |
| 142 | +?> |
Property changes on: trunk/phase3/maintenance/cleanupWatchlist.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 143 | + native |
Added: svn:keywords |
2 | 144 | + Author Date Id Revision |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -603,6 +603,7 @@ |
604 | 604 | * (bug 4828) Fix genitive month-name variable for cs, pl, uk |
605 | 605 | * (bug 4842) Fix 'show number of watching users' with enhanced RC |
606 | 606 | * (bug 4889) Fix image talk namespace for Tamil |
| 607 | +* (bug 4147) Added cleanupWatchlist.php to clear out bogus watchlist entries |
607 | 608 | |
608 | 609 | |
609 | 610 | === Caveats === |