MediaWiki
REL1_19
|
00001 <?php 00025 require_once( dirname( __FILE__ ) . '/Maintenance.php' ); 00026 00027 class RebuildRecentchanges extends Maintenance { 00028 public function __construct() { 00029 parent::__construct(); 00030 $this->mDescription = "Rebuild recent changes"; 00031 } 00032 00033 public function execute() { 00034 $this->rebuildRecentChangesTablePass1(); 00035 $this->rebuildRecentChangesTablePass2(); 00036 $this->rebuildRecentChangesTablePass3(); 00037 $this->rebuildRecentChangesTablePass4(); 00038 $this->purgeFeeds(); 00039 $this->output( "Done.\n" ); 00040 } 00041 00046 private function rebuildRecentChangesTablePass1() { 00047 $dbw = wfGetDB( DB_MASTER ); 00048 00049 $dbw->delete( 'recentchanges', '*' ); 00050 00051 $this->output( "Loading from page and revision tables...\n" ); 00052 00053 global $wgRCMaxAge; 00054 00055 $this->output( '$wgRCMaxAge=' . $wgRCMaxAge ); 00056 $days = $wgRCMaxAge / 24 / 3600; 00057 if ( intval( $days ) == $days ) { 00058 $this->output( " (" . $days . " days)\n" ); 00059 } else { 00060 $this->output( " (approx. " . intval( $days ) . " days)\n" ); 00061 } 00062 00063 $cutoff = time() - $wgRCMaxAge; 00064 $dbw->insertSelect( 'recentchanges', array( 'page', 'revision' ), 00065 array( 00066 'rc_timestamp' => 'rev_timestamp', 00067 'rc_cur_time' => 'rev_timestamp', 00068 'rc_user' => 'rev_user', 00069 'rc_user_text' => 'rev_user_text', 00070 'rc_namespace' => 'page_namespace', 00071 'rc_title' => 'page_title', 00072 'rc_comment' => 'rev_comment', 00073 'rc_minor' => 'rev_minor_edit', 00074 'rc_bot' => 0, 00075 'rc_new' => 'page_is_new', 00076 'rc_cur_id' => 'page_id', 00077 'rc_this_oldid' => 'rev_id', 00078 'rc_last_oldid' => 0, // is this ok? 00079 'rc_type' => $dbw->conditional( 'page_is_new != 0', RC_NEW, RC_EDIT ), 00080 'rc_deleted' => 'rev_deleted' 00081 ), array( 00082 'rev_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $cutoff ) ), 00083 'rev_page=page_id' 00084 ), __METHOD__, 00085 array(), // INSERT options 00086 array( 'ORDER BY' => 'rev_timestamp DESC', 'LIMIT' => 5000 ) // SELECT options 00087 ); 00088 } 00089 00094 private function rebuildRecentChangesTablePass2() { 00095 $dbw = wfGetDB( DB_MASTER ); 00096 list ( $recentchanges, $revision ) = $dbw->tableNamesN( 'recentchanges', 'revision' ); 00097 00098 $this->output( "Updating links and size differences...\n" ); 00099 00100 # Fill in the rc_last_oldid field, which points to the previous edit 00101 $sql = "SELECT rc_cur_id,rc_this_oldid,rc_timestamp FROM $recentchanges " . 00102 "ORDER BY rc_cur_id,rc_timestamp"; 00103 $res = $dbw->query( $sql, DB_MASTER ); 00104 00105 $lastCurId = 0; 00106 $lastOldId = 0; 00107 foreach ( $res as $obj ) { 00108 $new = 0; 00109 if ( $obj->rc_cur_id != $lastCurId ) { 00110 # Switch! Look up the previous last edit, if any 00111 $lastCurId = intval( $obj->rc_cur_id ); 00112 $emit = $obj->rc_timestamp; 00113 $sql2 = "SELECT rev_id,rev_len FROM $revision " . 00114 "WHERE rev_page={$lastCurId} " . 00115 "AND rev_timestamp<'{$emit}' ORDER BY rev_timestamp DESC"; 00116 $sql2 = $dbw->limitResult( $sql2, 1, false ); 00117 $res2 = $dbw->query( $sql2 ); 00118 $row = $dbw->fetchObject( $res2 ); 00119 if ( $row ) { 00120 $lastOldId = intval( $row->rev_id ); 00121 # Grab the last text size if available 00122 $lastSize = !is_null( $row->rev_len ) ? intval( $row->rev_len ) : null; 00123 } else { 00124 # No previous edit 00125 $lastOldId = 0; 00126 $lastSize = null; 00127 $new = 1; // probably true 00128 } 00129 } 00130 if ( $lastCurId == 0 ) { 00131 $this->output( "Uhhh, something wrong? No curid\n" ); 00132 } else { 00133 # Grab the entry's text size 00134 $size = $dbw->selectField( 'revision', 'rev_len', array( 'rev_id' => $obj->rc_this_oldid ) ); 00135 00136 $dbw->update( 'recentchanges', 00137 array( 00138 'rc_last_oldid' => $lastOldId, 00139 'rc_new' => $new, 00140 'rc_type' => $new, 00141 'rc_old_len' => $lastSize, 00142 'rc_new_len' => $size, 00143 ), array( 00144 'rc_cur_id' => $lastCurId, 00145 'rc_this_oldid' => $obj->rc_this_oldid, 00146 ), 00147 __METHOD__ 00148 ); 00149 00150 $lastOldId = intval( $obj->rc_this_oldid ); 00151 $lastSize = $size; 00152 } 00153 } 00154 } 00155 00160 private function rebuildRecentChangesTablePass3() { 00161 $dbw = wfGetDB( DB_MASTER ); 00162 00163 $this->output( "Loading from user, page, and logging tables...\n" ); 00164 00165 global $wgRCMaxAge, $wgLogTypes, $wgLogRestrictions; 00166 // Some logs don't go in RC. This should check for that 00167 $basicRCLogs = array_diff( $wgLogTypes, array_keys( $wgLogRestrictions ) ); 00168 00169 // Escape...blah blah 00170 $selectLogs = array(); 00171 foreach ( $basicRCLogs as $logtype ) { 00172 $safetype = $dbw->strencode( $logtype ); 00173 $selectLogs[] = "'$safetype'"; 00174 } 00175 00176 $cutoff = time() - $wgRCMaxAge; 00177 list( $logging, $page ) = $dbw->tableNamesN( 'logging', 'page' ); 00178 $dbw->insertSelect( 'recentchanges', array( 'user', "$logging LEFT JOIN $page ON (log_namespace=page_namespace AND log_title=page_title)" ), 00179 array( 00180 'rc_timestamp' => 'log_timestamp', 00181 'rc_cur_time' => 'log_timestamp', 00182 'rc_user' => 'log_user', 00183 'rc_user_text' => 'user_name', 00184 'rc_namespace' => 'log_namespace', 00185 'rc_title' => 'log_title', 00186 'rc_comment' => 'log_comment', 00187 'rc_minor' => 0, 00188 'rc_bot' => 0, 00189 'rc_patrolled' => 1, 00190 'rc_new' => 0, 00191 'rc_this_oldid' => 0, 00192 'rc_last_oldid' => 0, 00193 'rc_type' => RC_LOG, 00194 'rc_cur_id' => $dbw->cascadingDeletes() ? 'page_id' : 'COALESCE(page_id, 0)', 00195 'rc_log_type' => 'log_type', 00196 'rc_log_action' => 'log_action', 00197 'rc_logid' => 'log_id', 00198 'rc_params' => 'log_params', 00199 'rc_deleted' => 'log_deleted' 00200 ), array( 00201 'log_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $cutoff ) ), 00202 'log_user=user_id', 00203 'log_type IN(' . implode( ',', $selectLogs ) . ')' 00204 ), __METHOD__, 00205 array(), // INSERT options 00206 array( 'ORDER BY' => 'log_timestamp DESC', 'LIMIT' => 5000 ) // SELECT options 00207 ); 00208 } 00209 00214 private function rebuildRecentChangesTablePass4() { 00215 global $wgGroupPermissions, $wgUseRCPatrol; 00216 00217 $dbw = wfGetDB( DB_MASTER ); 00218 00219 list( $recentchanges, $usergroups, $user ) = $dbw->tableNamesN( 'recentchanges', 'user_groups', 'user' ); 00220 00221 $botgroups = $autopatrolgroups = array(); 00222 foreach ( $wgGroupPermissions as $group => $rights ) { 00223 if ( isset( $rights['bot'] ) && $rights['bot'] ) { 00224 $botgroups[] = $dbw->addQuotes( $group ); 00225 } 00226 if ( $wgUseRCPatrol && isset( $rights['autopatrol'] ) && $rights['autopatrol'] ) { 00227 $autopatrolgroups[] = $dbw->addQuotes( $group ); 00228 } 00229 } 00230 # Flag our recent bot edits 00231 if ( !empty( $botgroups ) ) { 00232 $botwhere = implode( ',', $botgroups ); 00233 $botusers = array(); 00234 00235 $this->output( "Flagging bot account edits...\n" ); 00236 00237 # Find all users that are bots 00238 $sql = "SELECT DISTINCT user_name FROM $usergroups, $user " . 00239 "WHERE ug_group IN($botwhere) AND user_id = ug_user"; 00240 $res = $dbw->query( $sql, DB_MASTER ); 00241 00242 foreach ( $res as $obj ) { 00243 $botusers[] = $dbw->addQuotes( $obj->user_name ); 00244 } 00245 # Fill in the rc_bot field 00246 if ( !empty( $botusers ) ) { 00247 $botwhere = implode( ',', $botusers ); 00248 $sql2 = "UPDATE $recentchanges SET rc_bot=1 " . 00249 "WHERE rc_user_text IN($botwhere)"; 00250 $dbw->query( $sql2 ); 00251 } 00252 } 00253 global $wgMiserMode; 00254 # Flag our recent autopatrolled edits 00255 if ( !$wgMiserMode && !empty( $autopatrolgroups ) ) { 00256 $patrolwhere = implode( ',', $autopatrolgroups ); 00257 $patrolusers = array(); 00258 00259 $this->output( "Flagging auto-patrolled edits...\n" ); 00260 00261 # Find all users in RC with autopatrol rights 00262 $sql = "SELECT DISTINCT user_name FROM $usergroups, $user " . 00263 "WHERE ug_group IN($patrolwhere) AND user_id = ug_user"; 00264 $res = $dbw->query( $sql, DB_MASTER ); 00265 00266 foreach ( $res as $obj ) { 00267 $patrolusers[] = $dbw->addQuotes( $obj->user_name ); 00268 } 00269 00270 # Fill in the rc_patrolled field 00271 if ( !empty( $patrolusers ) ) { 00272 $patrolwhere = implode( ',', $patrolusers ); 00273 $sql2 = "UPDATE $recentchanges SET rc_patrolled=1 " . 00274 "WHERE rc_user_text IN($patrolwhere)"; 00275 $dbw->query( $sql2 ); 00276 } 00277 } 00278 } 00279 00283 private function purgeFeeds() { 00284 global $wgFeedClasses, $messageMemc; 00285 00286 $this->output( "Deleting feed timestamps.\n" ); 00287 00288 foreach ( $wgFeedClasses as $feed => $className ) { 00289 $messageMemc->delete( wfMemcKey( 'rcfeed', $feed, 'timestamp' ) ); # Good enough for now. 00290 } 00291 } 00292 00293 } 00294 00295 $maintClass = "RebuildRecentchanges"; 00296 require_once( RUN_MAINTENANCE_IF_MAIN );