aboutsummaryrefslogtreecommitdiffstats
path: root/maintenance/rebuildrecentchanges.php
diff options
context:
space:
mode:
authorChad Horohoe <demon@users.mediawiki.org>2009-08-02 19:35:17 +0000
committerChad Horohoe <demon@users.mediawiki.org>2009-08-02 19:35:17 +0000
commita1c51e18af85a9ac464c5b555921e58ec422cd11 (patch)
treefca5fbda1f0ac6297768f8d8d5e76eb4732f8ea5 /maintenance/rebuildrecentchanges.php
parent0b49cfff10bf3eebc63f38a85a324afa0455847c (diff)
downloadmediawikicore-a1c51e18af85a9ac464c5b555921e58ec422cd11.tar.gz
mediawikicore-a1c51e18af85a9ac464c5b555921e58ec422cd11.zip
Merge maintenance-work branch (now with less errors!):
* Docs have been updated to indicate the standard on how to write maintenance scripts (MW.org docs will follow) Have ported vast majority of maintenance scripts to new format. Remaining ones (mostly FiveUpgrade-related) are a bit more tricky. commandLine.inc is untouched for now. Many have gotten code-style updates as well. Deleted .inc files were only used by their .php counterparts, and have been merged into single files. * (bug 11867) Lock error on redirect table when running orphans.php * (bug 16322) Allow maintenance scripts to accept DB user/pass over input or params * (bug 18566) Maintenance script to un/protect pages * initStats overhaul, now uses class SiteStatsInit. Also fixes bug 18930
Notes
Notes: http://mediawiki.org/wiki/Special:Code/MediaWiki/54225
Diffstat (limited to 'maintenance/rebuildrecentchanges.php')
-rw-r--r--maintenance/rebuildrecentchanges.php276
1 files changed, 265 insertions, 11 deletions
diff --git a/maintenance/rebuildrecentchanges.php b/maintenance/rebuildrecentchanges.php
index 4231ff7f1a5a..13e57053fcb9 100644
--- a/maintenance/rebuildrecentchanges.php
+++ b/maintenance/rebuildrecentchanges.php
@@ -3,22 +3,276 @@
* Rebuild link tracking tables from scratch. This takes several
* hours, depending on the database size and server configuration.
*
- * @file
- * @todo document
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @ingroup Maintenance
+ * @todo Document
*/
-/** */
-require_once( "commandLine.inc" );
-require_once( "rebuildrecentchanges.inc" );
-$wgTitle = Title::newFromText( "Rebuild recent changes script" );
+require_once( "Maintenance.php" );
+
+class RebuildRecentchanges extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Rebuild recent changes";
+ }
+
+ public function execute() {
+ global $wgTitle;
+ $wgTitle = Title::newFromText( "Rebuild recent changes script" );
+ $this->rebuildRecentChangesTablePass1();
+ $this->rebuildRecentChangesTablePass2();
+ $this->rebuildRecentChangesTablePass3();
+ $this->rebuildRecentChangesTablePass4();
+ $this->output( "Done.\n" );
+ }
-$wgDBuser = $wgDBadminuser;
-$wgDBpassword = $wgDBadminpassword;
+ /**
+ * Rebuild pass 1
+ * DOCUMENT ME!
+ */
+ function rebuildRecentChangesTablePass1()
+ {
+ $dbw = wfGetDB( DB_MASTER );
+
+ $dbw->delete( 'recentchanges', '*' );
+
+ $this->output( "Loading from page and revision tables...\n" );
+
+ global $wgRCMaxAge;
+
+ $this->output( '$wgRCMaxAge=' . $wgRCMaxAge );
+ $days = $wgRCMaxAge / 24 / 3600;
+ if ( intval($days) == $days ) {
+ $this->output( " (" . $days . " days)\n" );
+ } else {
+ $this->output( " (approx. " . intval($days) . " days)\n" );
+ }
+
+ $cutoff = time() - $wgRCMaxAge;
+ $dbw->insertSelect( 'recentchanges', array( 'page', 'revision' ),
+ array(
+ 'rc_timestamp' => 'rev_timestamp',
+ 'rc_cur_time' => 'rev_timestamp',
+ 'rc_user' => 'rev_user',
+ 'rc_user_text' => 'rev_user_text',
+ 'rc_namespace' => 'page_namespace',
+ 'rc_title' => 'page_title',
+ 'rc_comment' => 'rev_comment',
+ 'rc_minor' => 'rev_minor_edit',
+ 'rc_bot' => 0,
+ 'rc_new' => 'page_is_new',
+ 'rc_cur_id' => 'page_id',
+ 'rc_this_oldid' => 'rev_id',
+ 'rc_last_oldid' => 0, // is this ok?
+ 'rc_type' => $dbw->conditional( 'page_is_new != 0', RC_NEW, RC_EDIT ),
+ 'rc_deleted' => 'rev_deleted'
+ ), array(
+ 'rev_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $cutoff ) ),
+ 'rev_page=page_id'
+ ), __METHOD__,
+ array(), // INSERT options
+ array( 'ORDER BY' => 'rev_timestamp DESC', 'LIMIT' => 5000 ) // SELECT options
+ );
+ }
-rebuildRecentChangesTable();
+ /**
+ * Rebuild pass 2
+ * DOCUMENT ME!
+ */
+ private function rebuildRecentChangesTablePass2() {
+ $dbw = wfGetDB( DB_MASTER );
+ list ($recentchanges, $revision) = $dbw->tableNamesN( 'recentchanges', 'revision' );
+
+ $this->output( "Updating links and size differences...\n" );
+
+ # Fill in the rc_last_oldid field, which points to the previous edit
+ $sql = "SELECT rc_cur_id,rc_this_oldid,rc_timestamp FROM $recentchanges " .
+ "ORDER BY rc_cur_id,rc_timestamp";
+ $res = $dbw->query( $sql, DB_MASTER );
+
+ $lastCurId = 0;
+ $lastOldId = 0;
+ while ( $obj = $dbw->fetchObject( $res ) ) {
+ $new = 0;
+ if( $obj->rc_cur_id != $lastCurId ) {
+ # Switch! Look up the previous last edit, if any
+ $lastCurId = intval( $obj->rc_cur_id );
+ $emit = $obj->rc_timestamp;
+ $sql2 = "SELECT rev_id,rev_len FROM $revision " .
+ "WHERE rev_page={$lastCurId} ".
+ "AND rev_timestamp<'{$emit}' ORDER BY rev_timestamp DESC LIMIT 1";
+ $res2 = $dbw->query( $sql2 );
+ if( $row = $dbw->fetchObject( $res2 ) ) {
+ $lastOldId = intval($row->rev_id);
+ # Grab the last text size if available
+ $lastSize = !is_null($row->rev_len) ? intval($row->rev_len) : 'NULL';
+ } else {
+ # No previous edit
+ $lastOldId = 0;
+ $lastSize = 'NULL';
+ $new = 1; // probably true
+ }
+ $dbw->freeResult( $res2 );
+ }
+ if( $lastCurId == 0 ) {
+ $this->output( "Uhhh, something wrong? No curid\n" );
+ } else {
+ # Grab the entry's text size
+ $size = $dbw->selectField( 'revision', 'rev_len', array('rev_id' => $obj->rc_this_oldid ) );
+ $size = !is_null($size) ? intval($size) : 'NULL';
+
+ $sql3 = "UPDATE $recentchanges SET rc_last_oldid=$lastOldId,rc_new=$new,rc_type=$new," .
+ "rc_old_len=$lastSize,rc_new_len=$size " .
+ "WHERE rc_cur_id={$lastCurId} AND rc_this_oldid={$obj->rc_this_oldid}";
+ $dbw->query( $sql3 );
+
+ $lastOldId = intval( $obj->rc_this_oldid );
+ $lastSize = $size;
+ }
+ }
+ $dbw->freeResult( $res );
+ }
-print "Done.\n";
-exit(0);
+ /**
+ * Rebuild pass 3
+ * DOCUMENT ME!
+ */
+ private function rebuildRecentChangesTablePass3() {
+ $dbw = wfGetDB( DB_MASTER );
+
+ $this->output( "Loading from user, page, and logging tables...\n" );
+
+ global $wgRCMaxAge, $wgLogTypes, $wgLogRestrictions;
+ // Some logs don't go in RC. This should check for that
+ $basicRCLogs = array_diff( $wgLogTypes, array_keys( $wgLogRestrictions ) );
+
+ // Escape...blah blah
+ $selectLogs = array();
+ foreach( $basicRCLogs as $logtype ) {
+ $safetype = $dbw->strencode( $logtype );
+ $selectLogs[] = "'$safetype'";
+ }
+
+ $cutoff = time() - $wgRCMaxAge;
+ list($logging, $page) = $dbw->tableNamesN( 'logging', 'page' );
+ $dbw->insertSelect( 'recentchanges', array( 'user', "$logging LEFT JOIN $page ON (log_namespace=page_namespace AND log_title=page_title)" ),
+ array(
+ 'rc_timestamp' => 'log_timestamp',
+ 'rc_cur_time' => 'log_timestamp',
+ 'rc_user' => 'log_user',
+ 'rc_user_text' => 'user_name',
+ 'rc_namespace' => 'log_namespace',
+ 'rc_title' => 'log_title',
+ 'rc_comment' => 'log_comment',
+ 'rc_minor' => 0,
+ 'rc_bot' => 0,
+ 'rc_patrolled' => 1,
+ 'rc_new' => 0,
+ 'rc_this_oldid' => 0,
+ 'rc_last_oldid' => 0,
+ 'rc_type' => RC_LOG,
+ 'rc_cur_id' => 'COALESCE(page_id, 0)',
+ 'rc_log_type' => 'log_type',
+ 'rc_log_action' => 'log_action',
+ 'rc_logid' => 'log_id',
+ 'rc_params' => 'log_params',
+ 'rc_deleted' => 'log_deleted'
+ ), array(
+ 'log_timestamp > ' . $dbw->addQuotes( $dbw->timestamp( $cutoff ) ),
+ 'log_user=user_id',
+ 'log_type IN(' . implode(',',$selectLogs) . ')'
+ ), __METHOD__,
+ array(), // INSERT options
+ array( 'ORDER BY' => 'log_timestamp DESC', 'LIMIT' => 5000 ) // SELECT options
+ );
+ }
+ /**
+ * Rebuild pass 4
+ * DOCUMENT ME!
+ */
+ private function rebuildRecentChangesTablePass4() {
+ global $wgGroupPermissions, $wgUseRCPatrol;
+
+ $dbw = wfGetDB( DB_MASTER );
+
+ list($recentchanges,$usergroups,$user) = $dbw->tableNamesN( 'recentchanges', 'user_groups', 'user' );
+
+ $botgroups = $autopatrolgroups = array();
+ foreach( $wgGroupPermissions as $group => $rights ) {
+ if( isset( $rights['bot'] ) && $rights['bot'] == true ) {
+ $botgroups[] = $dbw->addQuotes( $group );
+ }
+ if( $wgUseRCPatrol && isset( $rights['autopatrol'] ) && $rights['autopatrol'] == true ) {
+ $autopatrolgroups[] = $dbw->addQuotes( $group );
+ }
+ }
+ # Flag our recent bot edits
+ if( !empty($botgroups) ) {
+ $botwhere = implode(',',$botgroups);
+ $botusers = array();
+
+ $this->output( "Flagging bot account edits...\n" );
+
+ # Find all users that are bots
+ $sql = "SELECT DISTINCT user_name FROM $usergroups, $user " .
+ "WHERE ug_group IN($botwhere) AND user_id = ug_user";
+ $res = $dbw->query( $sql, DB_MASTER );
+
+ while( $obj = $dbw->fetchObject( $res ) ) {
+ $botusers[] = $dbw->addQuotes( $obj->user_name );
+ }
+ # Fill in the rc_bot field
+ if( !empty($botusers) ) {
+ $botwhere = implode(',',$botusers);
+ $sql2 = "UPDATE $recentchanges SET rc_bot=1 " .
+ "WHERE rc_user_text IN($botwhere)";
+ $dbw->query( $sql2 );
+ }
+ }
+ global $wgMiserMode;
+ # Flag our recent autopatrolled edits
+ if( !$wgMiserMode && !empty($autopatrolgroups) ) {
+ $patrolwhere = implode(',',$autopatrolgroups);
+ $patrolusers = array();
+
+ $this->output( "Flagging auto-patrolled edits...\n" );
+
+ # Find all users in RC with autopatrol rights
+ $sql = "SELECT DISTINCT user_name FROM $usergroups, $user " .
+ "WHERE ug_group IN($patrolwhere) AND user_id = ug_user";
+ $res = $dbw->query( $sql, DB_MASTER );
+
+ while( $obj = $dbw->fetchObject( $res ) ) {
+ $patrolusers[] = $dbw->addQuotes( $obj->user_name );
+ }
+
+ # Fill in the rc_patrolled field
+ if( !empty($patrolusers) ) {
+ $patrolwhere = implode(',',$patrolusers);
+ $sql2 = "UPDATE $recentchanges SET rc_patrolled=1 " .
+ "WHERE rc_user_text IN($patrolwhere)";
+ $dbw->query( $sql2 );
+ }
+ }
+
+ $dbw->freeResult( $res );
+ }
+}
+$maintClass = "RebuildRecentchanges";
+require_once( DO_MAINTENANCE );