00001 <?php
00008 $optionsWithArgs = array( 'begin', 'max-slave-lag', 'throttle' );
00009
00010 require_once( dirname(__FILE__) . '/Maintenance.php' );
00011
00012
00013 class PopulateCategory extends Maintenance {
00014
00015 const REPORTING_INTERVAL = 1000;
00016
00017 public function __construct() {
00018 parent::__construct();
00019 $this->mDescription = <<<TEXT
00020 This script will populate the category table, added in MediaWiki 1.13. It will
00021 print out progress indicators every 1000 categories it adds to the table. The
00022 script is perfectly safe to run on large, live wikis, and running it multiple
00023 times is harmless. You may want to use the throttling options if it's causing
00024 too much load; they will not affect correctness.
00025
00026 If the script is stopped and later resumed, you can use the --begin option with
00027 the last printed progress indicator to pick up where you left off. This is
00028 safe, because any newly-added categories before this cutoff will have been
00029 added after the software update and so will be populated anyway.
00030
00031 When the script has finished, it will make a note of this in the database, and
00032 will not run again without the --force option.
00033 TEXT;
00034 $this->addOption( 'begin', 'Only do categories whose names are alphabetically after the provided name', false, true );
00035 $this->addOption( 'max-slave-lag', 'If slave lag exceeds this many seconds, wait until it drops before continuing. Default: 10', false, true );
00036 $this->addOption( 'throttle', 'Wait this many milliseconds after each category. Default: 0', false, true );
00037 $this->addOption( 'force', 'Run regardless of whether the database says it\'s been run already' );
00038 }
00039
00040 public function execute() {
00041 $begin = $this->getOption( 'begin', '' );
00042 $maxSlaveLag = $this->getOption( 'max-slave-lag', 10 );
00043 $throttle = $this->getOption( 'throttle', 0 );
00044 $force = $this->getOption( 'force', false );
00045 $this->doPopulateCategory( $begin, $maxSlaveLag, $throttle, $force );
00046 }
00047
00048 private function doPopulateCategory( $begin, $maxlag, $throttle, $force ) {
00049 $dbw = wfGetDB( DB_MASTER );
00050
00051 if( !$force ) {
00052 $row = $dbw->selectRow(
00053 'updatelog',
00054 '1',
00055 array( 'ul_key' => 'populate category' ),
00056 __FUNCTION__
00057 );
00058 if( $row ) {
00059 $this->output( "Category table already populated. Use php ".
00060 "maintenance/populateCategory.php\n--force from the command line ".
00061 "to override.\n" );
00062 return true;
00063 }
00064 }
00065
00066 $maxlag = intval( $maxlag );
00067 $throttle = intval( $throttle );
00068 $force = (bool)$force;
00069 if( $begin !== '' ) {
00070 $where = 'cl_to > '.$dbw->addQuotes( $begin );
00071 } else {
00072 $where = null;
00073 }
00074 $i = 0;
00075
00076 while( true ) {
00077 # Find which category to update
00078 $row = $dbw->selectRow(
00079 'categorylinks',
00080 'cl_to',
00081 $where,
00082 __FUNCTION__,
00083 array(
00084 'ORDER BY' => 'cl_to'
00085 )
00086 );
00087 if( !$row ) {
00088 # Done, hopefully.
00089 break;
00090 }
00091 $name = $row->cl_to;
00092 $where = 'cl_to > '.$dbw->addQuotes( $name );
00093
00094 # Use the row to update the category count
00095 $cat = Category::newFromName( $name );
00096 if( !is_object( $cat ) ) {
00097 $this->output( "The category named $name is not valid?!\n" );
00098 } else {
00099 $cat->refreshCounts();
00100 }
00101
00102 ++$i;
00103 if( !($i % self::REPORTING_INTERVAL) ) {
00104 $this->output( "$name\n" );
00105 wfWaitForSlaves( $maxlag );
00106 }
00107 usleep( $throttle*1000 );
00108 }
00109
00110 if( $dbw->insert(
00111 'updatelog',
00112 array( 'ul_key' => 'populate category' ),
00113 __FUNCTION__,
00114 'IGNORE'
00115 )
00116 ) {
00117 wfOut( "Category population complete.\n" );
00118 return true;
00119 } else {
00120 wfOut( "Could not insert category population row.\n" );
00121 return false;
00122 }
00123 }
00124 }
00125
00126 $maintClass = "PopulateCategory";
00127 require_once( DO_MAINTENANCE );