MediaWiki
REL1_22
|
00001 <?php 00028 require_once __DIR__ . '/Maintenance.php'; 00029 00036 class FixTimestamps extends Maintenance { 00037 public function __construct() { 00038 parent::__construct(); 00039 $this->mDescription = ""; 00040 $this->addArg( 'offset', '' ); 00041 $this->addArg( 'start', 'Starting timestamp' ); 00042 $this->addArg( 'end', 'Ending timestamp' ); 00043 } 00044 00045 public function execute() { 00046 $offset = $this->getArg( 0 ) * 3600; 00047 $start = $this->getArg( 1 ); 00048 $end = $this->getArg( 2 ); 00049 $grace = 60; // maximum normal clock offset 00050 00051 # Find bounding revision IDs 00052 $dbw = wfGetDB( DB_MASTER ); 00053 $revisionTable = $dbw->tableName( 'revision' ); 00054 $res = $dbw->query( "SELECT MIN(rev_id) as minrev, MAX(rev_id) as maxrev FROM $revisionTable " . 00055 "WHERE rev_timestamp BETWEEN '{$start}' AND '{$end}'", __METHOD__ ); 00056 $row = $dbw->fetchObject( $res ); 00057 00058 if ( is_null( $row->minrev ) ) { 00059 $this->error( "No revisions in search period.", true ); 00060 } 00061 00062 $minRev = $row->minrev; 00063 $maxRev = $row->maxrev; 00064 00065 # Select all timestamps and IDs 00066 $sql = "SELECT rev_id, rev_timestamp FROM $revisionTable " . 00067 "WHERE rev_id BETWEEN $minRev AND $maxRev"; 00068 if ( $offset > 0 ) { 00069 $sql .= " ORDER BY rev_id DESC"; 00070 $expectedSign = -1; 00071 } else { 00072 $expectedSign = 1; 00073 } 00074 00075 $res = $dbw->query( $sql, __METHOD__ ); 00076 00077 $lastNormal = 0; 00078 $badRevs = array(); 00079 $numGoodRevs = 0; 00080 00081 foreach ( $res as $row ) { 00082 $timestamp = wfTimestamp( TS_UNIX, $row->rev_timestamp ); 00083 $delta = $timestamp - $lastNormal; 00084 $sign = $delta == 0 ? 0 : $delta / abs( $delta ); 00085 if ( $sign == 0 || $sign == $expectedSign ) { 00086 // Monotonic change 00087 $lastNormal = $timestamp; 00088 ++ $numGoodRevs; 00089 continue; 00090 } elseif ( abs( $delta ) <= $grace ) { 00091 // Non-monotonic change within grace interval 00092 ++ $numGoodRevs; 00093 continue; 00094 } else { 00095 // Non-monotonic change larger than grace interval 00096 $badRevs[] = $row->rev_id; 00097 } 00098 } 00099 00100 $numBadRevs = count( $badRevs ); 00101 if ( $numBadRevs > $numGoodRevs ) { 00102 $this->error( 00103 "The majority of revisions in the search interval are marked as bad. 00104 00105 Are you sure the offset ($offset) has the right sign? Positive means the clock 00106 was incorrectly set forward, negative means the clock was incorrectly set back. 00107 00108 If the offset is right, then increase the search interval until there are enough 00109 good revisions to provide a majority reference.", true ); 00110 } elseif ( $numBadRevs == 0 ) { 00111 $this->output( "No bad revisions found.\n" ); 00112 exit( 0 ); 00113 } 00114 00115 $this->output( sprintf( "Fixing %d revisions (%.2f%% of revisions in search interval)\n", 00116 $numBadRevs, $numBadRevs / ( $numGoodRevs + $numBadRevs ) * 100 ) ); 00117 00118 $fixup = -$offset; 00119 $sql = "UPDATE $revisionTable " . 00120 "SET rev_timestamp=DATE_FORMAT(DATE_ADD(rev_timestamp, INTERVAL $fixup SECOND), '%Y%m%d%H%i%s') " . 00121 "WHERE rev_id IN (" . $dbw->makeList( $badRevs ) . ')'; 00122 $dbw->query( $sql, __METHOD__ ); 00123 $this->output( "Done\n" ); 00124 } 00125 } 00126 00127 $maintClass = "FixTimestamps"; 00128 require_once RUN_MAINTENANCE_IF_MAIN;