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