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 );