From: Brion Vibber Date: Wed, 24 Jun 2009 02:49:24 +0000 (+0000) Subject: Revert r52336 "Merge maintenance-work branch:" X-Git-Tag: 1.31.0-rc.0~41230 X-Git-Url: http://git.cyclocoop.org/%22%20.%20%20%20%24self2%20.%20%20%20%22&var_mode_affiche=boucle?a=commitdiff_plain;h=1c9773bd015adbf8aedb3b1777f0e087906baf6f;p=lhc%2Fweb%2Fwiklou.git Revert r52336 "Merge maintenance-work branch:" Seems to have broken a bunch of stuff. Don't commit giant non-critical changes that break Setup.php and all maint scripts. Thanks! --- diff --git a/AdminSettings.sample b/AdminSettings.sample new file mode 100644 index 0000000000..8b6fe99351 --- /dev/null +++ b/AdminSettings.sample @@ -0,0 +1,32 @@ +Environment check $conf->RootUser = importPost( "RootUser", "root" ); $conf->RootPW = importPost( "RootPW", "" ); $useRoot = importCheck( 'useroot', false ); - $conf->populateadmin = importCheck( 'populateadmin', false ); $conf->LanguageCode = importPost( "LanguageCode", "en" ); ## MySQL specific: $conf->DBprefix = importPost( "DBprefix" ); @@ -1528,8 +1527,6 @@ if( count( $errs ) ) { checked="checked" />   - populateadmin ) { ?>checked="checked" /> -  
@@ -1795,11 +1792,6 @@ function writeLocalSettings( $conf ) { # Needs literal string interpolation for the current style path $slconf['RightsIcon'] = $conf->RightsIcon; } - - if( $conf->populateadmin ) { - $slconf['DBadminuser'] = $conf->RootUser; - $slconf['DBadminpassword'] = $conf->RootPW; - } if( $conf->DBtype == 'mysql' ) { $dbsettings = @@ -1907,10 +1899,6 @@ if ( \$wgCommandLineMode ) { {$dbsettings} -## Database admin settings, used for maintenance scripts -\$wgDBadminuser = \"{$slconf['DBadminuser']}\"; -\$wgDBadminpassword = \"{$slconf['DBadminpassword']}\"; - ## Shared memory settings \$wgMainCacheType = $cacheType; \$wgMemCachedServers = $mcservers; diff --git a/docs/maintenance.txt b/docs/maintenance.txt deleted file mode 100644 index d46d12e27c..0000000000 --- a/docs/maintenance.txt +++ /dev/null @@ -1,54 +0,0 @@ -Prior to version 1.16, maintenance scripts were a hodgepodge of code that -had no cohesion or formal method of action. Beginning in 1.16, maintenance -scripts have been cleaned up to use a unified class. - -1. Directory structure -2. How to run a script -3. How to write your own - -1. DIRECTORY STRUCTURE - The /maintenance directory of a MediaWiki installation contains several -subdirectories, all of which have unique purposes. - -2. HOW TO RUN A SCRIPT - Ridiculously simple, just call 'php someScript.php' that's in the top- -level /maintenance directory. - -Example: - php clear_stats.php - -The following parameters are available to all maintenance scripts ---help : Print a help message ---quiet : Quiet non-error output ---dbuser : The database user to use for the script (if needed) ---dbpass : Same as above (if needed) - -3. HOW TO WRITE YOUR OWN -Make a file in the maintenance directory called myScript.php or something. -In it, write the following: - -==BEGIN== - -selectField( 'revision', 'COUNT(*)', '', __METHOD__ ); - $edits += $dbr->selectField( 'archive', 'COUNT(*)', '', __METHOD__ ); - wfOut( "{$edits}\nCounting number of articles..." ); - - global $wgContentNamespaces; - $good = $dbr->selectField( 'page', 'COUNT(*)', array( 'page_namespace' => $wgContentNamespaces, 'page_is_redirect' => 0, 'page_len > 0' ), __METHOD__ ); - wfOut( "{$good}\nCounting total pages..." ); - - $pages = $dbr->selectField( 'page', 'COUNT(*)', '', __METHOD__ ); - wfOut( "{$pages}\nCounting number of users..." ); - - $users = $dbr->selectField( 'user', 'COUNT(*)', '', __METHOD__ ); - wfOut( "{$users}\nCounting number of admins..." ); - - $admin = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), __METHOD__ ); - wfOut( "{$admin}\nCounting number of images..." ); - - $image = $dbr->selectField( 'image', 'COUNT(*)', '', __METHOD__ ); - wfOut( "{$image}\n" ); - - if( !$noViews ) { - wfOut( "Counting total page views..." ); - $views = $dbr->selectField( 'page', 'SUM(page_counter)', '', __METHOD__ ); - wfOut( "{$views}\n" ); - } - - wfOut( "\nUpdating site statistics..." ); - - $dbw = wfGetDB( DB_MASTER ); - $values = array( 'ss_total_edits' => $edits, - 'ss_good_articles' => $good, - 'ss_total_pages' => $pages, - 'ss_users' => $users, - 'ss_admins' => $admin, - 'ss_images' => $image ); - $conds = array( 'ss_row_id' => 1 ); - $views = array( 'ss_total_views' => isset( $views ) ? $views : 0 ); - - if( $update ) { - $dbw->update( 'site_stats', $values, $conds, __METHOD__ ); - } else { - $dbw->delete( 'site_stats', $conds, __METHOD__ ); - $dbw->insert( 'site_stats', array_merge( $values, $conds, $views ), __METHOD__ ); - } - - wfOut( "done.\n" ); - } } diff --git a/maintenance/Doxyfile b/maintenance/Doxyfile index e4014e83db..cdc748d8e9 100644 --- a/maintenance/Doxyfile +++ b/maintenance/Doxyfile @@ -135,7 +135,7 @@ FILE_PATTERNS = *.c \ RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = YES -EXCLUDE_PATTERNS = LocalSettings.php +EXCLUDE_PATTERNS = LocalSettings.php AdminSettings.php EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO diff --git a/maintenance/Maintenance.php b/maintenance/Maintenance.php deleted file mode 100644 index 6b5eda599a..0000000000 --- a/maintenance/Maintenance.php +++ /dev/null @@ -1,639 +0,0 @@ - - * @since 1.16 - * @ingroup Maintenance - */ -abstract class Maintenance { - - /** - * Constants for DB access type - * @see Maintenance::getDbType() - */ - const NO_DB = 0; - const NORMAL_DB = 1; - const ADMIN_DB = 2; - - // This is the desired params - private $mParams = array(); - - // Array of desired args - private $mArgList = array(); - - // This is the list of options that were actually passed - private $mOptions = array(); - - // This is the list of arguments that were actually passed - protected $mArgs = array(); - - // Name of the script currently running - protected $mSelf; - - // Special vars for params that are always used - private $mQuiet = false; - private $mDbUser, $mDbPass; - - // A description of the script, children should change this - protected $mDescription = ''; - - // Have we already loaded our user input? - private $inputLoaded = false; - - // Batch size - protected $mBatchSize = 100; - - /** - * Default constructor. Children should call this if implementing - * their own constructors - */ - public function __construct() { - $this->addDefaultParams(); - } - - /** - * Do the actual work. All child classes will need to implement this - */ - abstract public function execute(); - - /** - * Add a parameter to the script. Will be displayed on --help - * with the associated description - * - * @param $name String The name of the param (help, version, etc) - * @param $description String The description of the param to show on --help - * @param $required boolean Is the param required? - * @param $withArg Boolean Is an argument required with this option? - */ - protected function addParam( $name, $description, $required = false, $withArg = false ) { - $this->mParams[ $name ] = array( 'desc' => $description, 'require' => $required, 'withArg' => $withArg ); - } - - /** - * Checks to see if a particular param exists. - * @param $name String The name of the param - * @return boolean - */ - protected function hasOption( $name ) { - return isset( $this->mOptions[ $name ] ); - } - - /** - * Get an option, or return the default - * @param $name String The name of the param - * @param $default mixed Anything you want, default null - * @return mixed - */ - protected function getOption( $name, $default = null ) { - if( $this->hasOption($name) ) { - return $this->mOptions[$name]; - } else { - // Set it so we don't have to provide the default again - $this->mOptions[$name] = $default; - return $this->mOptions[$name]; - } - } - - /** - * Add some args that are needed. Used in formatting help - */ - protected function addArgs( $args ) { - $this->mArgList = array_merge( $this->mArgList, $args ); - } - - /** - * Does a given argument exist? - * @param $argId int The integer value (from zero) for the arg - * @return boolean - */ - protected function hasArg( $argId = 0 ) { - return isset( $this->mArgs[ $argId ] ) ; - } - - /** - * Get an argument. - * @param $argId int The integer value (from zero) for the arg - * @param $default mixed The default if it doesn't exist - * @return mixed - */ - protected function getArg( $argId = 0, $default = null ) { - return $this->hasArg($name) ? $this->mArgs[$name] : $default; - } - - /** - * Set the batch size. - * @param $s int The number of operations to do in a batch - */ - protected function setBatchSize( $s = 0 ) { - $this->mBatchSize = $s; - } - - /** - * Return input from stdin. - * @param $length int The number of bytes to read. If null, - * just return the handle - * @return mixed - */ - protected function getStdin( $len = null ) { - $f = fopen( 'php://stdin', 'rt' ); - if( !$len ) { - return $f; - } - $input = fgets( $f, $len ); - fclose ( $f ); - return rtrim( $input ); - } - - /** - * Throw some output to the user. Scripts can call this with no fears, - * as we handle all --quiet stuff here - * @param $out String The text to show to the user - */ - protected function output( $out ) { - if( $this->mQuiet ) { - return; - } - $f = fopen( 'php://stdout', 'w' ); - fwrite( $f, $out ); - fclose( $f ); - } - - /** - * Throw an error to the user. Doesn't respect --quiet, so don't use - * this for non-error output - * @param $err String The error to display - * @param $die boolean If true, go ahead and die out. - */ - protected function error( $err, $die = false ) { - $f = fopen( 'php://stderr', 'w' ); - fwrite( $f, $err ); - fclose( $f ); - if( $die ) die(); - } - - /** - * Does the script need normal DB access? By default, we give Maintenance - * scripts admin rights to the DB (when available). Sometimes, a script needs - * normal access for a reason and sometimes they want no access. Subclasses - * should override and return one of the following values, as needed: - * Maintenance::NO_DB - For no DB access at all - * Maintenance::NORMAL_DB - For normal DB access - * Maintenance::ADMIN_DB - For admin DB access, default - * @return int - */ - protected function getDbType() { - return Maintenance :: ADMIN_DB; - } - - /** - * Add the default parameters to the scripts - */ - private function addDefaultParams() { - $this->addParam( 'help', "Display this help message" ); - $this->addParam( 'quiet', "Whether to supress non-error output" ); - $this->addParam( 'conf', "Location of LocalSettings.php, if not default", false, true ); - $this->addParam( 'wiki', "For specifying the wiki ID", false, true ); - if( $this->getDbType() > 0 ) { - $this->addParam( 'dbuser', "The DB user to use for this script", false, true ); - $this->addParam( 'dbpass', "The password to use for this script", false, true ); - } - } - - /** - * Spawn a child maintenance script. Pass all of the current arguments - * to it. - * @param $maintClass String A name of a child maintenance class - * @param $classFile String Full path of where the child is - * @return Maintenance child - */ - protected function spawnChild( $maintClass, $classFile = null ) { - // If we haven't already specified, kill setup procedures - // for child scripts, we've already got a sane environment - if( !defined( 'MW_NO_SETUP' ) ) { - define( 'MW_NO_SETUP', true ); - } - - // Make sure the class is loaded first - if( !class_exists( $maintClass ) ) { - if( $classFile ) { - require_once( $classFile ); - } - if( !class_exists( $maintClass ) ) { - $this->error( "Cannot spawn child: $maintClass\n" ); - } - } - - $child = new $maintClass(); - $child->loadParamsAndArgs( $this->mSelf, $this->mOptions, $this->mArgs ); - return $child; - } - - /** - * Do some sanity checking and basic setup - */ - public function setup() { - global $IP, $wgCommandLineMode, $wgUseNormalUser, $wgRequestTime; - - # Abort if called from a web server - if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) { - $this->error( "This script must be run from the command line\n", true ); - } - - # Make sure we can handle script parameters - if( !ini_get( 'register_argc_argv' ) ) { - $this->error( "Cannot get command line arguments, register_argc_argv is set to false", true ); - } - - # Make sure we're on PHP5 or better - if( version_compare( PHP_VERSION, '5.0.0' ) < 0 ) { - $this->error( "Sorry! This version of MediaWiki requires PHP 5; you are running " . - PHP_VERSION . ".\n\n" . - "If you are sure you already have PHP 5 installed, it may be installed\n" . - "in a different path from PHP 4. Check with your system administrator.\n", true ); - } - - if( version_compare( phpversion(), '5.2.4' ) >= 0 ) { - // Send PHP warnings and errors to stderr instead of stdout. - // This aids in diagnosing problems, while keeping messages - // out of redirected output. - if( ini_get( 'display_errors' ) ) { - ini_set( 'display_errors', 'stderr' ); - } - - // Don't touch the setting on earlier versions of PHP, - // as setting it would disable output if you'd wanted it. - - // Note that exceptions are also sent to stderr when - // command-line mode is on, regardless of PHP version. - } - - # Set the memory limit - ini_set( 'memory_limit', -1 ); - - $wgRequestTime = microtime(true); - - # Define us as being in Mediawiki - define( 'MEDIAWIKI', true ); - - # Setup $IP, using MW_INSTALL_PATH if it exists - $IP = strval( getenv('MW_INSTALL_PATH') ) !== '' - ? getenv('MW_INSTALL_PATH') - : realpath( dirname( __FILE__ ) . '/..' ); - - $wgCommandLineMode = true; - # Turn off output buffering if it's on - @ob_end_flush(); - - if (!isset( $wgUseNormalUser ) ) { - $wgUseNormalUser = false; - } - - $this->loadParamsAndArgs(); - $this->maybeHelp(); - } - - /** - * Clear all params and arguments. - */ - public function clearParamsAndArgs() { - $this->mOptions = array(); - $this->mArgs = array(); - $this->inputLoaded = false; - } - - /** - * Process command line arguments - * $mOptions becomes an array with keys set to the option names - * $mArgs becomes a zero-based array containing the non-option arguments - * - * @param $self String The name of the script, if any - * @param $opts Array An array of options, in form of key=>value - * @param $args Array An array of command line arguments - */ - public function loadParamsAndArgs( $self = null, $opts = null, $args = null ) { - # If we were given opts or args, set those and return early - if( $self ) { - $this->mSelf = $self; - $this->inputLoaded = true; - } - if( $opts ) { - $this->mOptions = $opts; - $this->inputLoaded = true; - } - if( $args ) { - $this->mArgs = $args; - $this->inputLoaded = true; - } - - # If we've already loaded input (either by user values or from $argv) - # skip on loading it again. The array_shift() will corrupt values if - # it's run again and again - if( $this->inputLoaded ) { - $this->loadSpecialVars(); - return; - } - - global $argv; - $this->mSelf = array_shift( $argv ); - - $options = array(); - $args = array(); - - # Parse arguments - for( $arg = reset( $argv ); $arg !== false; $arg = next( $argv ) ) { - if ( $arg == '--' ) { - # End of options, remainder should be considered arguments - $arg = next( $argv ); - while( $arg !== false ) { - $args[] = $arg; - $arg = next( $argv ); - } - break; - } elseif ( substr( $arg, 0, 2 ) == '--' ) { - # Long options - $option = substr( $arg, 2 ); - if ( isset( $this->mParams[$option] ) && $this->mParams[$option]['withArg'] ) { - $param = next( $argv ); - if ( $param === false ) { - $this->error( "$arg needs a value after it\n", true ); - } - $options[$option] = $param; - } else { - $bits = explode( '=', $option, 2 ); - if( count( $bits ) > 1 ) { - $option = $bits[0]; - $param = $bits[1]; - } else { - $param = 1; - } - $options[$option] = $param; - } - } elseif ( substr( $arg, 0, 1 ) == '-' ) { - # Short options - for ( $p=1; $pmParams[$option]['withArg'] ) ) { - $param = next( $argv ); - if ( $param === false ) { - $this->error( "$arg needs a value after it\n", true ); - } - $options[$option] = $param; - } else { - $options[$option] = 1; - } - } - } else { - $args[] = $arg; - } - } - - # Check to make sure we've got all the required ones - foreach( $this->mParams as $opt => $info ) { - if( $info['require'] && !$this->hasOption($opt) ) { - $this->error( "Param $opt required.\n", true ); - } - } - - # Also make sure we've got enough arguments - if ( count( $args ) < count( $this->mArgList ) ) { - $this->error( "Not enough arguments passed", true ); - } - - $this->mOptions = $options; - $this->mArgs = $args; - $this->loadSpecialVars(); - $this->inputLoaded = true; - } - - /** - * Handle the special variables that are global to all scripts - */ - private function loadSpecialVars() { - if( $this->hasOption( 'dbuser' ) ) - $this->mDbUser = $this->getOption( 'dbuser' ); - if( $this->hasOption( 'dbpass' ) ) - $this->mDbPass = $this->getOption( 'dbpass' ); - if( $this->hasOption( 'quiet' ) ) - $this->mQuiet = true; - } - - /** - * Maybe show the help. - * @param $force boolean Whether to force the help to show, default false - */ - private function maybeHelp( $force = false ) { - if( $this->hasOption('help') || in_array( 'help', $this->mArgs ) || $force ) { - $this->mQuiet = false; - if( $this->mDescription ) { - $this->output( $this->mDescription . "\n" ); - } - $this->output( "\nUsage: php " . $this->mSelf ); - if( $this->mParams ) { - $this->output( " [--" . implode( array_keys( $this->mParams ), "|--" ) . "]" ); - } - if( $this->mArgList ) { - $this->output( " <" . implode( $this->mArgList, "> <" ) . ">" ); - } - $this->output( "\n" ); - foreach( $this->mParams as $par => $info ) { - $this->output( "\t$par : " . $info['desc'] . "\n" ); - } - die( 1 ); - } - } - - /** - * Handle some last-minute setup here. - */ - private function finalSetup() { - global $wgCommandLineMode, $wgUseNormalUser, $wgShowSQLErrors; - global $wgTitle, $wgProfiling, $IP, $wgDBadminuser, $wgDBadminpassword; - global $wgDBuser, $wgDBpassword, $wgDBservers, $wgLBFactoryConf; - - # Turn off output buffering again, it might have been turned on in the settings files - if( ob_get_level() ) { - ob_end_flush(); - } - # Same with these - $wgCommandLineMode = true; - - # If these were passed, use them - if( $this->mDbUser ) - $wgDBadminuser = $this->mDbUser; - if( $this->mDbPass ) - $wgDBadminpass = $this->mDbPass; - - if ( empty( $wgUseNormalUser ) && isset( $wgDBadminuser ) ) { - $wgDBuser = $wgDBadminuser; - $wgDBpassword = $wgDBadminpassword; - - if( $wgDBservers ) { - foreach ( $wgDBservers as $i => $server ) { - $wgDBservers[$i]['user'] = $wgDBuser; - $wgDBservers[$i]['password'] = $wgDBpassword; - } - } - if( isset( $wgLBFactoryConf['serverTemplate'] ) ) { - $wgLBFactoryConf['serverTemplate']['user'] = $wgDBuser; - $wgLBFactoryConf['serverTemplate']['password'] = $wgDBpassword; - } - } - - if ( defined( 'MW_CMDLINE_CALLBACK' ) ) { - $fn = MW_CMDLINE_CALLBACK; - $fn(); - } - - $wgShowSQLErrors = true; - @set_time_limit( 0 ); - - $wgProfiling = false; // only for Profiler.php mode; avoids OOM errors - } - - /** - * Do setup specific to WMF - */ - public function loadWikimediaSettings() { - global $IP, $wgNoDBParam, $wgUseNormalUser, $wgConf; - - if ( empty( $wgNoDBParam ) ) { - # Check if we were passed a db name - if ( isset( $this->mOptions['wiki'] ) ) { - $db = $this->mOptions['wiki']; - } else { - $db = array_shift( $this->mArgs ); - } - list( $site, $lang ) = $wgConf->siteFromDB( $db ); - - # If not, work out the language and site the old way - if ( is_null( $site ) || is_null( $lang ) ) { - if ( !$db ) { - $lang = 'aa'; - } else { - $lang = $db; - } - if ( isset( $this->mArgs[0] ) ) { - $site = array_shift( $this->mArgs ); - } else { - $site = 'wikipedia'; - } - } - } else { - $lang = 'aa'; - $site = 'wikipedia'; - } - - # This is for the IRC scripts, which now run as the apache user - # The apache user doesn't have access to the wikiadmin_pass command - if ( $_ENV['USER'] == 'apache' ) { - #if ( posix_geteuid() == 48 ) { - $wgUseNormalUser = true; - } - - putenv( 'wikilang=' . $lang ); - - $DP = $IP; - ini_set( 'include_path', ".:$IP:$IP/includes:$IP/languages:$IP/maintenance" ); - - if ( $lang == 'test' && $site == 'wikipedia' ) { - define( 'TESTWIKI', 1 ); - } - } - - /** - * Generic setup for most installs. Returns the location of LocalSettings - * @return String - */ - public function loadSettings() { - global $wgWikiFarm, $wgCommandLineMode, $IP, $DP; - - $wgWikiFarm = false; - if ( isset( $this->mOptions['conf'] ) ) { - $settingsFile = $this->mOptions['conf']; - } else { - $settingsFile = "$IP/LocalSettings.php"; - } - if ( isset( $this->mOptions['wiki'] ) ) { - $bits = explode( '-', $this->mOptions['wiki'] ); - if ( count( $bits ) == 1 ) { - $bits[] = ''; - } - define( 'MW_DB', $bits[0] ); - define( 'MW_PREFIX', $bits[1] ); - } - - if ( ! is_readable( $settingsFile ) ) { - $this->error( "A copy of your installation's LocalSettings.php\n" . - "must exist and be readable in the source directory.\n", true ); - } - $wgCommandLineMode = true; - $DP = $IP; - $this->finalSetup(); - return $settingsFile; - } - - /** - * Support function for cleaning up redundant text records - * @param $delete boolean Whether or not to actually delete the records - * @author Rob Church - */ - protected function purgeRedundantText( $delete = true ) { - # Data should come off the master, wrapped in a transaction - $dbw = wfGetDB( DB_MASTER ); - $dbw->begin(); - - $tbl_arc = $dbw->tableName( 'archive' ); - $tbl_rev = $dbw->tableName( 'revision' ); - $tbl_txt = $dbw->tableName( 'text' ); - - # Get "active" text records from the revisions table - $this->output( "Searching for active text records in revisions table..." ); - $res = $dbw->query( "SELECT DISTINCT rev_text_id FROM $tbl_rev" ); - while( $row = $dbw->fetchObject( $res ) ) { - $cur[] = $row->rev_text_id; - } - $this->output( "done.\n" ); - - # Get "active" text records from the archive table - $this->output( "Searching for active text records in archive table..." ); - $res = $dbw->query( "SELECT DISTINCT ar_text_id FROM $tbl_arc" ); - while( $row = $dbw->fetchObject( $res ) ) { - $cur[] = $row->ar_text_id; - } - $this->output( "done.\n" ); - - # Get the IDs of all text records not in these sets - $this->output( "Searching for inactive text records..." ); - $set = implode( ', ', $cur ); - $res = $dbw->query( "SELECT old_id FROM $tbl_txt WHERE old_id NOT IN ( $set )" ); - $old = array(); - while( $row = $dbw->fetchObject( $res ) ) { - $old[] = $row->old_id; - } - $this->output( "done.\n" ); - - # Inform the user of what we're going to do - $count = count( $old ); - $this->output( "$count inactive items found.\n" ); - - # Delete as appropriate - if( $delete && $count ) { - $this->output( "Deleting..." ); - $set = implode( ', ', $old ); - $dbw->query( "DELETE FROM $tbl_txt WHERE old_id IN ( $set )" ); - $this->output( "done.\n" ); - } - - # Done - $dbw->commit(); - - } -} - diff --git a/maintenance/README b/maintenance/README index 6b23937ae0..e2215c1dd9 100644 --- a/maintenance/README +++ b/maintenance/README @@ -10,8 +10,8 @@ proper installation. Certain scripts will require elevated access to the database. In order to provide this, first create a MySQL user with "all" permissions on the wiki -database, and then set $wgDBadminuser and $wgDBadminpassword in your -LocalSettings.php +database, and then place their username and password in an AdminSettings.php +file in the directory above. See AdminSettings.sample for specifics on this. === Brief explanation of files === diff --git a/maintenance/attachLatest.php b/maintenance/attachLatest.php index ca8d1aa7d5..8d680afaaa 100644 --- a/maintenance/attachLatest.php +++ b/maintenance/attachLatest.php @@ -25,58 +25,49 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +require_once( 'commandLine.inc' ); -class AttachLatest extends Maintenance { - - public function __construct() { - parent::__construct(); - $this->addParam( "fix", "Actually fix the entries, will dry run otherwise" ); - $this->mDescription = "Fix page_latest entries in the page table"; +$fixit = isset( $options['fix'] ); +$fname = 'attachLatest'; + +echo "Looking for pages with page_latest set to 0...\n"; +$dbw = wfGetDB( DB_MASTER ); +$result = $dbw->select( 'page', + array( 'page_id', 'page_namespace', 'page_title' ), + array( 'page_latest' => 0 ), + $fname ); + +$n = 0; +while( $row = $dbw->fetchObject( $result ) ) { + $pageId = intval( $row->page_id ); + $title = Title::makeTitle( $row->page_namespace, $row->page_title ); + $name = $title->getPrefixedText(); + $latestTime = $dbw->selectField( 'revision', + 'MAX(rev_timestamp)', + array( 'rev_page' => $pageId ), + $fname ); + if( !$latestTime ) { + echo wfWikiID()." $pageId [[$name]] can't find latest rev time?!\n"; + continue; } - - public function execute() { - $this->output( "Looking for pages with page_latest set to 0...\n" ); - $dbw = wfGetDB( DB_MASTER ); - $result = $dbw->select( 'page', - array( 'page_id', 'page_namespace', 'page_title' ), - array( 'page_latest' => 0 ), - __METHOD__ ); - $n = 0; - while( $row = $dbw->fetchObject( $result ) ) { - $pageId = intval( $row->page_id ); - $title = Title::makeTitle( $row->page_namespace, $row->page_title ); - $name = $title->getPrefixedText(); - $latestTime = $dbw->selectField( 'revision', - 'MAX(rev_timestamp)', - array( 'rev_page' => $pageId ), - __METHOD__ ); - if( !$latestTime ) { - $this->output( wfWikiID()." $pageId [[$name]] can't find latest rev time?!\n" ); - continue; - } - - $revision = Revision::loadFromTimestamp( $dbw, $title, $latestTime ); - if( is_null( $revision ) ) { - $this->output( wfWikiID()." $pageId [[$name]] latest time $latestTime, can't find revision id\n" ); - continue; - } - $id = $revision->getId(); - $this->output( wfWikiID()." $pageId [[$name]] latest time $latestTime, rev id $id\n" ); - if( $this->hasOption('fix') ) { - $article = new Article( $title ); - $article->updateRevisionOn( $dbw, $revision ); - } - $n++; - } - $dbw->freeResult( $result ); - $this->output( "Done! Processed $n pages.\n" ); - if( !$this->hasOption('fix') ) { - $this->output( "This was a dry run; rerun with --fix to update page_latest.\n" ); - } + $revision = Revision::loadFromTimestamp( $dbw, $title, $latestTime ); + if( is_null( $revision ) ) { + echo wfWikiID()." $pageId [[$name]] latest time $latestTime, can't find revision id\n"; + continue; + } + $id = $revision->getId(); + echo wfWikiID()." $pageId [[$name]] latest time $latestTime, rev id $id\n"; + if( $fixit ) { + $article = new Article( $title ); + $article->updateRevisionOn( $dbw, $revision ); } + $n++; } +$dbw->freeResult( $result ); +echo "Done! Processed $n pages.\n"; +if( !$fixit ) { + echo "This was a dry run; rerun with --fix to update page_latest.\n"; +} + -$maintClass = "AttachLatest"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/benchmarkPurge.php b/maintenance/benchmarkPurge.php index f67c6c811d..796e1da207 100644 --- a/maintenance/benchmarkPurge.php +++ b/maintenance/benchmarkPurge.php @@ -6,87 +6,74 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +/** */ +require_once( "commandLine.inc" ); -class BenchmarkPurge extends Maintenance { - - public function __construct() { - parent::__construct(); - $this->addParams( "count", "How many URLs to feed to Squid for purging", false, true ); - $this->mDescription = "Benchmark the Squid purge functions."; - } - - public function execute() { - global $wgUseSquid; - if( !$wgUseSquid ) { - $this->error( "Squid purge benchmark doesn't do much without squid support on.\n". true ); - } else { - $this->output( "There are " . count( $wgSquidServers ) . " defined squid servers:\n" ); - if( $this->hasOption( 'count' ) ) { - $lengths = array( intval( $this->getOption('count') ) ); - } else { - $lengths = array( 1, 10, 100 ); - } - foreach( $lengths as $length ) { - $urls = $this->randomUrlList( $length ); - $trial = $this->benchSquid( $urls ); - $this->output( $trial . "\n" ); - } - } +/** + * Run a bunch of URLs through SquidUpdate::purge() + * to benchmark Squid response times. + * @param $urls array A bunch of URLs to purge + * @param $trials int How many times to run the test? + */ +function benchSquid( $urls, $trials = 1 ) { + $start = wfTime(); + for( $i = 0; $i < $trials; $i++) { + SquidUpdate::purge( $urls ); } - - /** - * Run a bunch of URLs through SquidUpdate::purge() - * to benchmark Squid response times. - * @param $urls array A bunch of URLs to purge - * @param $trials int How many times to run the test? - */ - private function benchSquid( $urls, $trials = 1 ) { - $start = wfTime(); - for( $i = 0; $i < $trials; $i++) { - SquidUpdate::purge( $urls ); - } - $delta = wfTime() - $start; - $pertrial = $delta / $trials; - $pertitle = $pertrial / count( $urls ); - return sprintf( "%4d titles in %6.2fms (%6.2fms each)", - count( $urls ), $pertrial * 1000.0, $pertitle * 1000.0 ); + $delta = wfTime() - $start; + $pertrial = $delta / $trials; + $pertitle = $pertrial / count( $urls ); + return sprintf( "%4d titles in %6.2fms (%6.2fms each)", + count( $urls ), $pertrial * 1000.0, $pertitle * 1000.0 ); +} + +/** + * Get an array of randomUrl()'s. + * @param $length int How many urls to add to the array + */ +function randomUrlList( $length ) { + $list = array(); + for( $i = 0; $i < $length; $i++ ) { + $list[] = randomUrl(); } - - /** - * Get an array of randomUrl()'s. - * @param $length int How many urls to add to the array - */ - private function randomUrlList( $length ) { - $list = array(); - for( $i = 0; $i < $length; $i++ ) { - $list[] = $this->randomUrl(); - } - return $list; + return $list; +} + +/** + * Return a random URL of the wiki. Not necessarily an actual title in the + * database, but at least a URL that looks like one. + */ +function randomUrl() { + global $wgServer, $wgArticlePath; + return $wgServer . str_replace( '$1', randomTitle(), $wgArticlePath ); +} + +/** + * Create a random title string (not necessarily a Title object). + * For use with randomUrl(). + */ +function randomTitle() { + $str = ''; + $length = mt_rand( 1, 20 ); + for( $i = 0; $i < $length; $i++ ) { + $str .= chr( mt_rand( ord('a'), ord('z') ) ); } - - /** - * Return a random URL of the wiki. Not necessarily an actual title in the - * database, but at least a URL that looks like one. - */ - private function randomUrl() { - global $wgServer, $wgArticlePath; - return $wgServer . str_replace( '$1', $this->randomTitle(), $wgArticlePath ); + return ucfirst( $str ); +} + +if( !$wgUseSquid ) { + wfDie( "Squid purge benchmark doesn't do much without squid support on.\n" ); +} else { + printf( "There are %d defined squid servers:\n", count( $wgSquidServers ) ); + #echo implode( "\n", $wgSquidServers ) . "\n"; + if( isset( $options['count'] ) ) { + $lengths = array( intval( $options['count'] ) ); + } else { + $lengths = array( 1, 10, 100 ); } - - /** - * Create a random title string (not necessarily a Title object). - * For use with randomUrl(). - */ - private function randomTitle() { - $str = ''; - $length = mt_rand( 1, 20 ); - for( $i = 0; $i < $length; $i++ ) { - $str .= chr( mt_rand( ord('a'), ord('z') ) ); - } - return ucfirst( $str ); + foreach( $lengths as $length ) { + $urls = randomUrlList( $length ); + $trial = benchSquid( $urls ); + print "$trial\n"; } } - -$maintClass = "BenchmarkPurge"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/changePassword.php b/maintenance/changePassword.php index 006562a06f..0fe8c0bea3 100644 --- a/maintenance/changePassword.php +++ b/maintenance/changePassword.php @@ -10,32 +10,47 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later */ -require_once( "Maintenance.php" ); - -class ChangePassword extends Maintenance { - public function __construct() { - parent::__construct(); - $this->addParam( "user", "The username to operate on", true, true ); - $this->addParam( "password", "The password to use", true, true ); - $this->mDescription = "Change a user's password." - } - - public function execute() { - if( !$this->hasOption('user') || !$this->hasOption('password') ) { - $this->error( "Username or password not provided, halting.", true ); - } - $user = User::newFromName( $this->getOption('user') ); - if( !$user->getId() ) { - $this->error( "No such user: " . $this->getOption('user') . "\n", true ); +$optionsWithArgs = array( 'user', 'password' ); +require_once 'commandLine.inc'; + +$USAGE = + "Usage: php changePassword.php [--user=user --password=password | --help]\n" . + "\toptions:\n" . + "\t\t--help show this message\n" . + "\t\t--user the username to operate on\n" . + "\t\t--password the password to use\n"; + +if( in_array( '--help', $argv ) ) + wfDie( $USAGE ); + +$cp = new ChangePassword( @$options['user'], @$options['password'] ); +$cp->main(); + +/** + * @ingroup Maintenance + */ +class ChangePassword { + var $dbw; + var $user, $password; + + function ChangePassword( $user, $password ) { + global $USAGE; + if( !strlen( $user ) or !strlen( $password ) ) { + wfDie( $USAGE ); } - try { - $user->setPassword( $this->getOption('password') ); - $user->saveSettings(); - } catch( PasswordError $pwe ) { - $this->error( $pwe->getText(), true ); + + $this->user = User::newFromName( $user ); + if ( !$this->user->getId() ) { + die ( "No such user: $user\n" ); } + + $this->password = $password; + + $this->dbw = wfGetDB( DB_MASTER ); } -} -$maintClass = "ChangePassword"; -require_once( DO_MAINTENANCE ); + function main() { + $this->user->setPassword( $this->password ); + $this->user->saveSettings(); + } +} diff --git a/maintenance/checkAutoLoader.php b/maintenance/checkAutoLoader.php index 30e9069a32..554395ca68 100644 --- a/maintenance/checkAutoLoader.php +++ b/maintenance/checkAutoLoader.php @@ -1,40 +1,29 @@ mDescription = "AutoLoader sanity checks"; +foreach ( $files as $file ) { + if( function_exists( 'parsekit_compile_file' ) ){ + $parseInfo = parsekit_compile_file( "$IP/$file" ); + $classes = array_keys( $parseInfo['class_table'] ); + } else { + $contents = file_get_contents( "$IP/$file" ); + $m = array(); + preg_match_all( '/\n\s*class\s+([a-zA-Z0-9_]+)/', $contents, $m, PREG_PATTERN_ORDER ); + $classes = $m[1]; } - public function execute() { - global $wgAutoloadLocalClasses, $IP; - $files = array_unique( $wgAutoloadLocalClasses ); - - foreach( $files as $file ) { - if( function_exists( 'parsekit_compile_file' ) ){ - $parseInfo = parsekit_compile_file( "$IP/$file" ); - $classes = array_keys( $parseInfo['class_table'] ); - } else { - $contents = file_get_contents( "$IP/$file" ); - $m = array(); - preg_match_all( '/\n\s*class\s+([a-zA-Z0-9_]+)/', $contents, $m, PREG_PATTERN_ORDER ); - $classes = $m[1]; - } - foreach ( $classes as $class ) { - if ( !isset( $wgAutoloadLocalClasses[$class] ) ) { - //printf( "%-50s Unlisted, in %s\n", $class, $file ); - $this->output( "\t'$class' => '$file',\n" ); - } elseif ( $wgAutoloadLocalClasses[$class] !== $file ) { - $this->output( "$class: Wrong file: found in $file, listed in " . $wgAutoloadLocalClasses[$class] . "\n" ); - } - } + foreach ( $classes as $class ) { + if ( !isset( $wgAutoloadLocalClasses[$class] ) ) { + //printf( "%-50s Unlisted, in %s\n", $class, $file ); + echo " '$class' => '$file',\n"; + } elseif ( $wgAutoloadLocalClasses[$class] !== $file ) { + echo "$class: Wrong file: found in $file, listed in " . $wgAutoloadLocalClasses[$class] . "\n"; } } + } -$maintClass = "CheckAutoLoader"; -require_once( DO_MAINTENANCE ); + diff --git a/maintenance/checkBadRedirects.php b/maintenance/checkBadRedirects.php index 6a49f25285..48a4b0e6d1 100644 --- a/maintenance/checkBadRedirects.php +++ b/maintenance/checkBadRedirects.php @@ -1,42 +1,30 @@ mDescription = "Look for bad redirects"; - } +require "commandLine.inc"; + +echo "Fetching redirects...\n"; +$dbr = wfGetDB( DB_SLAVE ); +$result = $dbr->select( + array( 'page' ), + array( 'page_namespace','page_title', 'page_latest' ), + array( 'page_is_redirect' => 1 ) ); + +$count = $result->numRows(); +echo "Found $count total redirects.\n"; +echo "Looking for bad redirects:\n"; +echo "\n"; - public function execute() { - $this->output( "Fetching redirects...\n" ); - $dbr = wfGetDB( DB_SLAVE ); - $result = $dbr->select( - array( 'page' ), - array( 'page_namespace','page_title', 'page_latest' ), - array( 'page_is_redirect' => 1 ) ); - - $count = $result->numRows(); - $this->output( "Found $count total redirects.\n" . - "Looking for bad redirects:\n\n" ); - - foreach( $result as $row ) { - $title = Title::makeTitle( $row->page_namespace, $row->page_title ); - $rev = Revision::newFromId( $row->page_latest ); - if( $rev ) { - $target = Title::newFromRedirect( $rev->getText() ); - if( !$target ) { - $this->output( $title->getPrefixedText() . "\n" ); - } - } +foreach( $result as $row ) { + $title = Title::makeTitle( $row->page_namespace, $row->page_title ); + $rev = Revision::newFromId( $row->page_latest ); + if( $rev ) { + $target = Title::newFromRedirect( $rev->getText() ); + if( !$target ) { + echo $title->getPrefixedText(); + echo "\n"; } - $this->output( "\ndone.\n" ); } } -$maintClass = "CheckBadRedirects"; -require_once( DO_MAINTENANCE ); +echo "\n"; +echo "done.\n"; diff --git a/maintenance/checkImages.php b/maintenance/checkImages.php index 2102bcf60c..378caa348b 100644 --- a/maintenance/checkImages.php +++ b/maintenance/checkImages.php @@ -1,63 +1,51 @@ mDescription = "Check images to see if they exist, are readable, etc"; - } - - public function execute() { - $batchSize = 1000; - $start = ''; - $dbr = wfGetDB( DB_SLAVE ); - - $numImages = 0; - $numGood = 0; - - do { - $res = $dbr->select( 'image', '*', array( 'img_name > ' . $dbr->addQuotes( $start ) ), - __METHOD__, array( 'LIMIT' => $batchSize ) ); - foreach ( $res as $row ) { - $numImages++; - $start = $row->img_name; - $file = RepoGroup::singleton()->getLocalRepo()->newFileFromRow( $row ); - $path = $file->getPath(); - if ( !$path ) { - $this->output( "{$row->img_name}: not locally accessible\n"; - continue; - } - $stat = @stat( $file->getPath() ); - if ( !$stat ) { - $this->output( "{$row->img_name}: missing\n" ); - continue; - } - - if ( $stat['mode'] & 040000 ) { - $this->output( "{$row->img_name}: is a directory\n" ); - continue; - } - - if ( $stat['size'] == 0 && $row->img_size != 0 ) { - $this->output( "{$row->img_name}: truncated, was {$row->img_size}\n" ); - continue; - } - - if ( $stat['size'] != $row->img_size ) { - $this->output( "{$row->img_name}: size mismatch DB={$row->img_size}, actual={$stat['size']}\n" ); - continue; - } - - $numGood++; - } - - } while ( $res->numRows() ); - - $this->output( "Good images: $numGood/$numImages\n" ); +$batchSize = 1000; +$start = ''; +$dbr = wfGetDB( DB_SLAVE ); +$localRepo = RepoGroup::singleton()->getLocalRepo(); + +$numImages = 0; +$numGood = 0; + +do { + $res = $dbr->select( 'image', '*', array( 'img_name > ' . $dbr->addQuotes( $start ) ), + 'checkImages.php', array( 'LIMIT' => $batchSize ) ); + foreach ( $res as $row ) { + $numImages++; + $start = $row->img_name; + $file = $localRepo->newFileFromRow( $row ); + $path = $file->getPath(); + if ( !$path ) { + echo "{$row->img_name}: not locally accessible\n"; + continue; + } + $stat = @stat( $file->getPath() ); + if ( !$stat ) { + echo "{$row->img_name}: missing\n"; + continue; + } + + if ( $stat['mode'] & 040000 ) { + echo "{$row->img_name}: is a directory\n"; + continue; + } + + if ( $stat['size'] == 0 && $row->img_size != 0 ) { + echo "{$row->img_name}: truncated, was {$row->img_size}\n"; + continue; + } + + if ( $stat['size'] != $row->img_size ) { + echo "{$row->img_name}: size mismatch DB={$row->img_size}, actual={$stat['size']}\n"; + continue; + } + + $numGood++; } -} +} while ( $res->numRows() ); + +echo "Good images: $numGood/$numImages\n"; diff --git a/maintenance/checkUsernames.php b/maintenance/checkUsernames.php index e530a3bcb7..77565b9906 100644 --- a/maintenance/checkUsernames.php +++ b/maintenance/checkUsernames.php @@ -7,33 +7,36 @@ * @ingroup Maintenance */ +error_reporting(E_ALL ^ E_NOTICE); +require_once 'commandLine.inc'; -require_once( "Maintenance.php" ); +class checkUsernames { + var $stderr, $log; -class CheckUsernames extends Maintenance { - - public function __construct() { - parent::__construct(); - $this->mDescription = "Verify that database usernames are actually valid"; + function checkUsernames() { + $this->stderr = fopen( 'php://stderr', 'wt' ); } + function main() { + $fname = 'checkUsernames::main'; - function execute() { $dbr = wfGetDB( DB_SLAVE ); $res = $dbr->select( 'user', array( 'user_id', 'user_name' ), null, - __METHOD__ + $fname ); while ( $row = $dbr->fetchObject( $res ) ) { if ( ! User::isValidUserName( $row->user_name ) ) { - $this->error( sprintf( "%s: %6d: '%s'\n", wfWikiID(), $row->user_id, $row->user_name ) ); + $out = sprintf( "%s: %6d: '%s'\n", wfWikiID(), $row->user_id, $row->user_name ); + fwrite( $this->stderr, $out ); wfDebugLog( 'checkUsernames', $out ); } } } } -$maintClass = "CheckUsernames"; -require_once( "doMaintenance.php" ); +$cun = new checkUsernames(); +$cun->main(); + diff --git a/maintenance/clear_interwiki_cache.php b/maintenance/clear_interwiki_cache.php index 88d08ba858..ce154779c1 100644 --- a/maintenance/clear_interwiki_cache.php +++ b/maintenance/clear_interwiki_cache.php @@ -3,36 +3,25 @@ * This script is used to clear the interwiki links for ALL languages in * memcached. * + * @file * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +/** */ +require_once('commandLine.inc'); -class ClearInterwikiCache extends Maintenance { - - public function __construct() { - parent::__construct(); - $this->mDescription = "Clear all interwiki links for all languages from the cache"; - } - - public function execute() { - global $wgLocalDatabases; - $dbr = wfGetDB( DB_SLAVE ); - $res = $dbr->select( 'interwiki', array( 'iw_prefix' ), false ); - $prefixes = array(); - while ( $row = $dbr->fetchObject( $res ) ) { - $prefixes[] = $row->iw_prefix; - } +$dbr = wfGetDB( DB_SLAVE ); +$res = $dbr->select( 'interwiki', array( 'iw_prefix' ), false ); +$prefixes = array(); +while ( $row = $dbr->fetchObject( $res ) ) { + $prefixes[] = $row->iw_prefix; +} - foreach ( $wgLocalDatabases as $db ) { - $this->output( "$db..." ); - foreach ( $prefixes as $prefix ) { - $wgMemc->delete("$db:interwiki:$prefix"); - } - $this->output( "done\n" ); - } +foreach ( $wgLocalDatabases as $db ) { + print "$db "; + foreach ( $prefixes as $prefix ) { + $wgMemc->delete("$db:interwiki:$prefix"); } } +print "\n"; -$maintClass = "ClearInterwikiCache"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/clear_stats.php b/maintenance/clear_stats.php index f2a128f4ca..4cacd74c3d 100644 --- a/maintenance/clear_stats.php +++ b/maintenance/clear_stats.php @@ -6,34 +6,33 @@ * @ingroup Maintenance */ -require_once( 'Maintenance.php' ); +require_once('commandLine.inc'); -class clear_stats extends Maintenance { - - public function __construct() { - parent::__construct(); - $this->mDescription = "Remove all statistics tracking from memcached"; - } +foreach ( $wgLocalDatabases as $db ) { + noisyDelete("$db:stats:request_with_session"); + noisyDelete("$db:stats:request_without_session"); + noisyDelete("$db:stats:pcache_hit"); + noisyDelete("$db:stats:pcache_miss_invalid"); + noisyDelete("$db:stats:pcache_miss_expired"); + noisyDelete("$db:stats:pcache_miss_absent"); + noisyDelete("$db:stats:pcache_miss_stub"); + noisyDelete("$db:stats:image_cache_hit"); + noisyDelete("$db:stats:image_cache_miss"); + noisyDelete("$db:stats:image_cache_update"); + noisyDelete("$db:stats:diff_cache_hit"); + noisyDelete("$db:stats:diff_cache_miss"); + noisyDelete("$db:stats:diff_uncacheable"); +} - public function execute() { - global $wgLocalDatabases, $wgMemc; - foreach ( $wgLocalDatabases as $db ) { - $wgMemc->delete("$db:stats:request_with_session"); - $wgMemc->delete("$db:stats:request_without_session"); - $wgMemc->delete("$db:stats:pcache_hit"); - $wgMemc->delete("$db:stats:pcache_miss_invalid"); - $wgMemc->delete("$db:stats:pcache_miss_expired"); - $wgMemc->delete("$db:stats:pcache_miss_absent"); - $wgMemc->delete("$db:stats:pcache_miss_stub"); - $wgMemc->delete("$db:stats:image_cache_hit"); - $wgMemc->delete("$db:stats:image_cache_miss"); - $wgMemc->delete("$db:stats:image_cache_update"); - $wgMemc->delete("$db:stats:diff_cache_hit"); - $wgMemc->delete("$db:stats:diff_cache_miss"); - $wgMemc->delete("$db:stats:diff_uncacheable"); - } - } +function noisyDelete( $key ) { + global $wgMemc; + /* + print "$key "; + if ( $wgMemc->delete($key) ) { + print "deleted\n"; + } else { + print "FAILED\n"; + }*/ + $wgMemc->delete($key); } -$maintClass = "clear_stats"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/createAndPromote.php b/maintenance/createAndPromote.php index a424336ebd..a5a8f88d34 100644 --- a/maintenance/createAndPromote.php +++ b/maintenance/createAndPromote.php @@ -8,53 +8,61 @@ * @author Rob Church */ -require_once( "Maintenance.php" ); - -class CreateAndPromote extends Maintenance { - - public function __construct() { - parent::__construct(); - $this->mDescription = "Create a new user account with administrator rights"; - $this->addParam( "bureaucrat", "Grant the account bureaucrat rights" ); - $this->addArgs( array( "username", "password" ) ); - } - - public function execute() { - $username = $this->getArg(0); - $password = $this->getArg(1); - - $this->output( wfWikiID() . ": Creating and promoting User:{$username}..." ); - - $user = User::newFromName( $username ); - if( !is_object( $user ) ) { - $this->error( "invalid username.\n", true ); - } elseif( 0 != $user->idForName() ) { - $this->error( "account exists.\n", true ); - } - - # Try to set the password - try { - $user->setPassword( $password ); - } catch( PasswordError $pwe ) { - $this->error( $pwe->getText(), true ); - } - - # Insert the account into the database - $user->addToDatabase(); - $user->saveSettings(); - - # Promote user - $user->addGroup( 'sysop' ); - if( $this->hasOption( 'bureaucrat' ) ) - $user->addGroup( 'bureaucrat' ); - - # Increment site_stats.ss_users - $ssu = new SiteStatsUpdate( 0, 0, 0, 0, 1 ); - $ssu->doUpdate(); - - $this->output( "done.\n" ); - } +$options = array( 'help', 'bureaucrat' ); +require_once( 'commandLine.inc' ); + +if( isset( $options['help'] ) ) { + showHelp(); + exit( 1 ); +} + +if( count( $args ) < 2 ) { + echo( "Please provide a username and password for the new account.\n" ); + die( 1 ); +} + +$username = $args[0]; +$password = $args[1]; + +echo( wfWikiID() . ": Creating and promoting User:{$username}..." ); + +# Validate username and check it doesn't exist +$user = User::newFromName( $username ); +if( !is_object( $user ) ) { + echo( "invalid username.\n" ); + die( 1 ); +} elseif( 0 != $user->idForName() ) { + echo( "account exists.\n" ); + die( 1 ); } -$maintClass = "CreateAndPromote"; -require_once( DO_MAINTENANCE ); +# Insert the account into the database +$user->addToDatabase(); +$user->setPassword( $password ); +$user->saveSettings(); + +# Promote user +$user->addGroup( 'sysop' ); +if( isset( $option['bureaucrat'] ) ) + $user->addGroup( 'bureaucrat' ); + +# Increment site_stats.ss_users +$ssu = new SiteStatsUpdate( 0, 0, 0, 0, 1 ); +$ssu->doUpdate(); + +echo( "done.\n" ); + +function showHelp() { + echo( << + + --bureaucrat + Grant the account bureaucrat rights + --help + Show this help information + +EOT + ); +} \ No newline at end of file diff --git a/maintenance/deleteBatch.php b/maintenance/deleteBatch.php index 6e44d63f47..5aeea7816b 100644 --- a/maintenance/deleteBatch.php +++ b/maintenance/deleteBatch.php @@ -1,4 +1,5 @@ ] [-r ] [-i ] [listfile] @@ -12,87 +13,86 @@ * @file * @ingroup Maintenance */ - -require_once( "Maintenance.php" ); - -class DeleteBatch extends Maintenance { - - public function __construct() { - parent::__construct(); - $this->mDescription = "Deletes a batch of pages"; - $this->addParam( 'u', "User to perform deletion", false, true ); - $this->addParam( 'r', "Reason to delete page", false, true ); - $this->addParam( 'i', "Interval to sleep between deletions" ); - $this->addArgs( array( 'listfile' ) ); + +$oldCwd = getcwd(); +$optionsWithArgs = array( 'u', 'r', 'i' ); +require_once( 'commandLine.inc' ); + +chdir( $oldCwd ); + +# Options processing + +$filename = 'php://stdin'; +$user = 'Delete page script'; +$reason = ''; +$interval = 0; + +if ( isset( $args[0] ) ) { + $filename = $args[0]; +} +if ( isset( $options['u'] ) ) { + $user = $options['u']; +} +if ( isset( $options['r'] ) ) { + $reason = $options['r']; +} +if ( isset( $options['i'] ) ) { + $interval = $options['i']; +} + +$wgUser = User::newFromName( $user ); + + +# Setup complete, now start + +$file = fopen( $filename, 'r' ); +if ( !$file ) { + print "Unable to read file, exiting\n"; + exit; +} + +$dbw = wfGetDB( DB_MASTER ); + +for ( $linenum = 1; !feof( $file ); $linenum++ ) { + $line = trim( fgets( $file ) ); + if ( $line == '' ) { + continue; } - - public function execute() { - global $wgUser; - - # Change to current working directory - $oldCwd = getcwd(); - chdir( $oldCwd ); - - # Options processing - $user = $this->getOption( 'u', 'Delete page script' ); - $reason = $this->getOption( 'r', '' ); - $interval = $this->getOption( 'i', 0 ); - if( $this->hasArg() ) { - $file = fopen( $this->getArg(), 'r' ); - } else { - $file = $this->getStdin(); - } + $page = Title::newFromText( $line ); + if ( is_null( $page ) ) { + print "Invalid title '$line' on line $linenum\n"; + continue; + } + if( !$page->exists() ) { + print "Skipping nonexistent page '$line'\n"; + continue; + } + - # Setup - if( !$file ) { - $this->error( "Unable to read file, exiting\n", true ); + print $page->getPrefixedText(); + $dbw->begin(); + if( $page->getNamespace() == NS_FILE ) { + $art = new ImagePage( $page ); + $img = wfFindFile( $art->mTitle ); + if( !$img || !$img->delete( $reason ) ) { + print "FAILED to delete image file... "; } - $wgUser = User::newFromName( $user ); - $dbw = wfGetDB( DB_MASTER ); - - # Handle each entry - for ( $linenum = 1; !feof( $file ); $linenum++ ) { - $line = trim( fgets( $file ) ); - if ( $line == '' ) { - continue; - } - $page = Title::newFromText( $line ); - if ( is_null( $page ) ) { - $this->output( "Invalid title '$line' on line $linenum\n" ); - continue; - } - if( !$page->exists() ) { - $this->output( "Skipping nonexistent page '$line'\n" ); - continue; - } - - - $this->output( $page->getPrefixedText() ); - $dbw->begin(); - if( $page->getNamespace() == NS_FILE ) { - $art = new ImagePage( $page ); - $img = wfFindFile( $art->mTitle ); - if( !$img || !$img->delete( $reason ) ) { - $this->output( "FAILED to delete image file... " ); - } - } else { - $art = new Article( $page ); - } - $success = $art->doDeleteArticle( $reason ); - $dbw->immediateCommit(); - if ( $success ) { - $this->output( "\n" ); - } else { - $this->output( " FAILED to delete article\n" ); - } - - if ( $interval ) { - sleep( $interval ); - } - wfWaitForSlaves( 5 ); -} + } else { + $art = new Article( $page ); + } + $success = $art->doDeleteArticle( $reason ); + $dbw->immediateCommit(); + if ( $success ) { + print "\n"; + } else { + print " FAILED to delete image page\n"; + } + + if ( $interval ) { + sleep( $interval ); } + wfWaitForSlaves( 5 ); } -$maintClass = "DeleteBatch"; -require_once( DO_MAINTENANCE ); + + diff --git a/maintenance/deleteDefaultMessages.php b/maintenance/deleteDefaultMessages.php index 868fe7d626..77e8574194 100644 --- a/maintenance/deleteDefaultMessages.php +++ b/maintenance/deleteDefaultMessages.php @@ -1,53 +1,48 @@ mDescription = "Deletes all pages in the MediaWiki namespace" . - " which were last edited by \"MediaWiki default\""; - } +if ( !defined( 'MEDIAWIKI' ) ) { + require_once( 'commandLine.inc' ); + deleteDefaultMessages(); +} - public function execute() { - $user = 'MediaWiki default'; - $reason = 'No longer required'; +function deleteDefaultMessages() { + $user = 'MediaWiki default'; + $reason = 'No longer required'; - global $wgUser; - $wgUser = User::newFromName( $user ); - $wgUser->addGroup( 'bot' ); + global $wgUser; + $wgUser = User::newFromName( $user ); + $wgUser->addGroup( 'bot' ); + + $dbr = wfGetDB( DB_SLAVE ); + $res = $dbr->select( array( 'page', 'revision' ), + array( 'page_namespace', 'page_title' ), + array( + 'page_namespace' => NS_MEDIAWIKI, + 'page_latest=rev_id', + 'rev_user_text' => 'MediaWiki default', + ) + ); - $dbr = wfGetDB( DB_SLAVE ); - $res = $dbr->select( array( 'page', 'revision' ), - array( 'page_namespace', 'page_title' ), - array( - 'page_namespace' => NS_MEDIAWIKI, - 'page_latest=rev_id', - 'rev_user_text' => 'MediaWiki default', - ) - ); + $dbw = wfGetDB( DB_MASTER ); - $dbw = wfGetDB( DB_MASTER ); - - while ( $row = $dbr->fetchObject( $res ) ) { - if ( function_exists( 'wfWaitForSlaves' ) ) { - wfWaitForSlaves( 5 ); - } - $dbw->ping(); - $title = Title::makeTitle( $row->page_namespace, $row->page_title ); - $article = new Article( $title ); - $dbw->begin(); - $article->doDeleteArticle( $reason ); - $dbw->commit(); + while ( $row = $dbr->fetchObject( $res ) ) { + if ( function_exists( 'wfWaitForSlaves' ) ) { + wfWaitForSlaves( 5 ); } + $dbw->ping(); + $title = Title::makeTitle( $row->page_namespace, $row->page_title ); + $article = new Article( $title ); + $dbw->begin(); + $article->doDeleteArticle( $reason ); + $dbw->commit(); } } -$maintClass = "DeleteDefaultMessages"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/deleteImageMemcached.php b/maintenance/deleteImageMemcached.php index caa48a186a..2c3afa86ef 100644 --- a/maintenance/deleteImageMemcached.php +++ b/maintenance/deleteImageMemcached.php @@ -3,27 +3,31 @@ * This script delete image information from memcached. * * Usage example: - * php deleteImageMemcached.php --until "2005-09-05 00:00:00" --sleep 0 + * php deleteImageMemcached.php --until "2005-09-05 00:00:00" --sleep 0 --report 10 * * @file * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +$optionsWithArgs = array( 'until', 'sleep', 'report' ); -class DeleteImageCache extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Delete image information from memcached"; - $this->addParam( 'sleep', 'How many seconds to sleep between deletions', true, true ); - $this->addParam( 'until', 'Timestamp to delete all entries prior to', true, true ); +require_once 'commandLine.inc'; + +/** + * @ingroup Maintenance + */ +class DeleteImageCache { + var $until, $sleep, $report; + + function DeleteImageCache( $until, $sleep, $report ) { + $this->until = $until; + $this->sleep = $sleep; + $this->report = $report; } - public function execute() { + function main() { global $wgMemc; - - $until = preg_replace( "/[^\d]/", '', $this->getOption('until') ); - $sleep = (int)$this->getOption('sleep') * 1000; // milliseconds + $fname = 'DeleteImageCache::main'; ini_set( 'display_errors', false ); @@ -31,8 +35,8 @@ class DeleteImageCache extends Maintenance { $res = $dbr->select( 'image', array( 'img_name' ), - array( "img_timestamp < {$until}" ), - __METHOD__ + array( "img_timestamp < {$this->until}" ), + $fname ); $i = 0; @@ -40,22 +44,29 @@ class DeleteImageCache extends Maintenance { while ( $row = $dbr->fetchObject( $res ) ) { if ($i % $this->report == 0) - $this->output( sprintf("%s: %13s done (%s)\n", wfWikiID(), "$i/$total", wfPercent( $i / $total * 100 ) ) ); + printf("%s: %13s done (%s)\n", wfWikiID(), "$i/$total", wfPercent( $i / $total * 100 )); $md5 = md5( $row->img_name ); $wgMemc->delete( wfMemcKey( 'Image', $md5 ) ); - if ($sleep != 0) - usleep( $sleep ); + if ($this->sleep != 0) + usleep( $this->sleep ); ++$i; } } - private function getImageCount() { + function getImageCount() { + $fname = 'DeleteImageCache::getImageCount'; + $dbr = wfGetDB( DB_SLAVE ); - return $dbr->selectField( 'image', 'COUNT(*)', array(), __METHOD__ ); + return $dbr->selectField( 'image', 'COUNT(*)', array(), $fname ); } } -$maintClass = "DeleteImageCache"; -require_once( DO_MAINTENANCE ); +$until = preg_replace( "/[^\d]/", '', $options['until'] ); +$sleep = (int)$options['sleep'] * 1000; // milliseconds +$report = (int)$options['report']; + +$dic = new DeleteImageCache( $until, $sleep, $report ); +$dic->main(); + diff --git a/maintenance/deleteRevision.php b/maintenance/deleteRevision.php index 6623de1a3d..0c203ab050 100644 --- a/maintenance/deleteRevision.php +++ b/maintenance/deleteRevision.php @@ -6,52 +6,42 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +require_once( 'commandLine.inc' ); -class DeleteRevision extends Maintenance { - - public function __construct() { - parent::__construct(); - $this->mDescription = "Delete one or more revisions by moving them to the archive table"; - } - - public function execute() { - if( count( $this->mArgs ) == 0 ) { - $this->error( "No revisions specified", true ); - } +$dbw = wfGetDB( DB_MASTER ); + +if ( count( $args ) == 0 ) { + echo "Usage: php deleteRevision.php [ ...]\n"; + exit(1); +} - $this->output( "Deleting revision(s) " . implode( ',', $this->mArgs ) . - " from " . wfWikiID() . "...\n" ); - $dbw = wfGetDB( DB_MASTER ); - - $affected = 0; - foreach ( $this->mArgs as $revID ) { - $dbw->insertSelect( 'archive', array( 'page', 'revision' ), - array( - 'ar_namespace' => 'page_namespace', - 'ar_title' => 'page_title', - 'ar_comment' => 'rev_comment', - 'ar_user' => 'rev_user', - 'ar_user_text' => 'rev_user_text', - 'ar_timestamp' => 'rev_timestamp', - 'ar_minor_edit' => 'rev_minor_edit', - 'ar_rev_id' => 'rev_id', - 'ar_text_id' => 'rev_text_id', - ), array( - 'rev_id' => $revID, - 'page_id = rev_page' - ), __METHOD__ - ); - if ( !$dbw->affectedRows() ) { - $this->output( "Revision $revID not found\n" ); - } else { - $affected += $dbw->affectedRows(); - $dbw->delete( 'revision', array( 'rev_id' => $revID ) ); - } - } - $this->output( "Deleted $affected revisions\n" ); +echo "Deleting revision(s) " . implode( ',', $args ) . " from ".wfWikiID()."...\n"; + +$affected = 0; +foreach ( $args as $revID ) { + $dbw->insertSelect( 'archive', array( 'page', 'revision' ), + array( + 'ar_namespace' => 'page_namespace', + 'ar_title' => 'page_title', + 'ar_comment' => 'rev_comment', + 'ar_user' => 'rev_user', + 'ar_user_text' => 'rev_user_text', + 'ar_timestamp' => 'rev_timestamp', + 'ar_minor_edit' => 'rev_minor_edit', + 'ar_rev_id' => 'rev_id', + 'ar_text_id' => 'rev_text_id', + ), array( + 'rev_id' => $revID, + 'page_id = rev_page' + ), $fname + ); + if ( !$dbw->affectedRows() ) { + echo "Revision $revID not found\n"; + } else { + $affected += $dbw->affectedRows(); + $dbw->delete( 'revision', array( 'rev_id' => $revID ) ); } } -$maintClass = "DeleteRevision"; -require_once( DO_MAINTENANCE ); +print "Deleted $affected revisions\n"; + diff --git a/maintenance/doMaintenance.php b/maintenance/doMaintenance.php deleted file mode 100644 index dbb03529bb..0000000000 --- a/maintenance/doMaintenance.php +++ /dev/null @@ -1,60 +0,0 @@ -setup(); - -# Setup the profiler -if ( file_exists( "$IP/StartProfiler.php" ) ) { - require_once( "$IP/StartProfiler.php" ); -} else { - require_once( "$IP/includes/ProfilerStub.php" ); -} - -// Load settings, using wikimedia-mode if needed -if( file_exists( dirname(__FILE__).'/wikimedia-mode' ) ) { - # TODO FIXME! Wikimedia-specific stuff needs to go away to an ext - # Maybe a hook? - global $cluster; - $wgWikiFarm = true; - $cluster = 'pmtma'; - require_once( "$IP/includes/AutoLoader.php" ); - require_once( "$IP/includes/SiteConfiguration.php" ); - require( "$IP/wgConf.php" ); - $maintenance->loadWikimediaSettings(); - require( $IP.'/includes/Defines.php' ); - require( $IP.'/CommonSettings.php' ); -} else { - require_once( "$IP/includes/AutoLoader.php" ); - require_once( "$IP/includes/Defines.php" ); - require_once( $maintenance->loadSettings() ); -} -// Some last includes -require_once( "$IP/includes/Setup.php" ); -require_once( "$IP/install-utils.inc" ); - -$wgTitle = null; # Much much faster startup than creating a title object - -try { - $maintenance->execute(); -} catch( MWException $mwe ) { - echo( $mwe->getText() ); -} \ No newline at end of file diff --git a/maintenance/eval.php b/maintenance/eval.php index 7b90012d2e..a990a4d845 100644 --- a/maintenance/eval.php +++ b/maintenance/eval.php @@ -16,66 +16,57 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +$wgUseNormalUser = (bool)getenv('MW_WIKIUSER'); -class EvalPrompt extends Maintenance { +$optionsWithArgs = array( 'd' ); - public function __construct() { - parent::__construct(); - $this->mDescription = "This script lets a command-line user start up the wiki engine and then poke\n" . - "about by issuing PHP commands directly."; - $this->addParam( 'd', "Enable MediaWiki debug output", false, true ); +/** */ +require_once( "commandLine.inc" ); + +if ( isset( $options['d'] ) ) { + $d = $options['d']; + if ( $d > 0 ) { + $wgDebugLogFile = '/dev/stdout'; } - - public function execute() { - global $wgUseNormalUser; - $wgUseNormalUser = (bool)getenv('MW_WIKIUSER'); - if ( $this->hasOption('d') ) { - $d = $this->getOption('d'); - if ( $d > 0 ) { - $wgDebugLogFile = '/dev/stdout'; - } - if ( $d > 1 ) { - $lb = wfGetLB(); - foreach ( $lb->mServers as $i => $server ) { - $lb->mServers[$i]['flags'] |= DBO_DEBUG; - } - } - if ( $d > 2 ) { - $wgDebugFunctionEntry = true; - } - } - - if ( function_exists( 'readline_add_history' ) - && function_exists( 'posix_isatty' ) && posix_isatty( 0 /*STDIN*/ ) ) - { - $useReadline = true; - } else { - $useReadline = false; - } - - if ( $useReadline ) { - $historyFile = "{$_ENV['HOME']}/.mweval_history"; - readline_read_history( $historyFile ); - } - - while ( ( $line = readconsole( '> ' ) ) !== false ) { - if ( $useReadline ) { - readline_add_history( $line ); - readline_write_history( $historyFile ); - } - $val = eval( $line . ";" ); - if( is_null( $val ) ) { - echo "\n"; - } elseif( is_string( $val ) || is_numeric( $val ) ) { - echo "$val\n"; - } else { - var_dump( $val ); - } + if ( $d > 1 ) { + $lb = wfGetLB(); + foreach ( $lb->mServers as $i => $server ) { + $lb->mServers[$i]['flags'] |= DBO_DEBUG; } - print "\n"; } + if ( $d > 2 ) { + $wgDebugFunctionEntry = true; + } +} + +if ( function_exists( 'readline_add_history' ) + && function_exists( 'posix_isatty' ) && posix_isatty( 0 /*STDIN*/ ) ) +{ + $useReadline = true; +} else { + $useReadline = false; } -$maintClass = "EvalPrompt"; -require_once( DO_MAINTENANCE ); +if ( $useReadline ) { + $historyFile = "{$_ENV['HOME']}/.mweval_history"; + readline_read_history( $historyFile ); +} + +while ( ( $line = readconsole( '> ' ) ) !== false ) { + if ( $useReadline ) { + readline_add_history( $line ); + readline_write_history( $historyFile ); + } + $val = eval( $line . ";" ); + if( is_null( $val ) ) { + echo "\n"; + } elseif( is_string( $val ) || is_numeric( $val ) ) { + echo "$val\n"; + } else { + var_dump( $val ); + } +} + +print "\n"; + + diff --git a/maintenance/fetchText.php b/maintenance/fetchText.php index f300318e37..91b78be3fe 100644 --- a/maintenance/fetchText.php +++ b/maintenance/fetchText.php @@ -6,48 +6,34 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +require "commandLine.inc"; -class FetchText extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Fetch the revision text from an old_id"; +$db = wfGetDB( DB_SLAVE ); +$stdin = fopen( "php://stdin", "rt" ); +while( !feof( $stdin ) ) { + $line = fgets( $stdin ); + if( $line === false ) { + // We appear to have lost contact... + break; } + $textId = intval( $line ); + $text = doGetText( $db, $textId ); + echo strlen( $text ) . "\n"; + echo $text; +} - public function execute() { - $db = wfGetDB( DB_SLAVE ); - $stdin = $this->getStdin(); - while( !feof( $stdin ) ) { - $line = fgets( $stdin ); - if( $line === false ) { - // We appear to have lost contact... - break; - } - $textId = intval( $line ); - $text = $this->doGetText( $db, $textId ); - $this->output( strlen( $text ) . "\n". $text ); - } - } - - /** - * May throw a database error if, say, the server dies during query. - * @param $db Database object - * @param $id int The old_id - * @return String - */ - private function doGetText( $db, $id ) { - $id = intval( $id ); - $row = $db->selectRow( 'text', - array( 'old_text', 'old_flags' ), - array( 'old_id' => $id ), - 'TextPassDumper::getText' ); - $text = Revision::getRevisionText( $row ); - if( $text === false ) { - return false; - } - return $text; +/** + * May throw a database error if, say, the server dies during query. + */ +function doGetText( $db, $id ) { + $id = intval( $id ); + $row = $db->selectRow( 'text', + array( 'old_text', 'old_flags' ), + array( 'old_id' => $id ), + 'TextPassDumper::getText' ); + $text = Revision::getRevisionText( $row ); + if( $text === false ) { + return false; } + return $text; } - -$maintClass = "FetchText"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/getLagTimes.php b/maintenance/getLagTimes.php index 49197e6fb7..0f750caf59 100644 --- a/maintenance/getLagTimes.php +++ b/maintenance/getLagTimes.php @@ -4,37 +4,26 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +require 'commandLine.inc'; -class GetLagTimes extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Dump replication lag times"; - } - - public function execute() { - $lb = wfGetLB(); +$lb = wfGetLB(); - if( $lb->getServerCount() == 1 ) { - $this->error( "This script dumps replication lag times, but you don't seem to have\n" - . "a multi-host db server configuration.\n" ); +if( $lb->getServerCount() == 1 ) { + echo "This script dumps replication lag times, but you don't seem to have\n"; + echo "a multi-host db server configuration.\n"; +} else { + $lags = $lb->getLagTimes(); + foreach( $lags as $n => $lag ) { + $host = $lb->getServerName( $n ); + if( IP::isValid( $host ) ) { + $ip = $host; + $host = gethostbyaddr( $host ); } else { - $lags = $lb->getLagTimes(); - foreach( $lags as $n => $lag ) { - $host = $lb->getServerName( $n ); - if( IP::isValid( $host ) ) { - $ip = $host; - $host = gethostbyaddr( $host ); - } else { - $ip = gethostbyname( $host ); - } - $starLen = min( intval( $lag ), 40 ); - $stars = str_repeat( '*', $starLen ); - $this->output( sprintf( "%10s %20s %3d %s\n", $ip, $host, $lag, $stars ) ); - } + $ip = gethostbyname( $host ); } + $starLen = min( intval( $lag ), 40 ); + $stars = str_repeat( '*', $starLen ); + printf( "%10s %20s %3d %s\n", $ip, $host, $lag, $stars ); } } -$maintClass = "GetLagTimes"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/getSlaveServer.php b/maintenance/getSlaveServer.php index 72bc1387a3..25258267e2 100644 --- a/maintenance/getSlaveServer.php +++ b/maintenance/getSlaveServer.php @@ -5,32 +5,24 @@ * @file * @ingroup Maintenance */ - -require_once( "Maintenance.php" ); -class GetSlaveServer extends Maintenance { - public function __construct() { - parent::__construct(); - $this->addParam( "group", "Query group to check specifically" ); - $this->mDescription = "Report the hostname of a slave server"; - } - public function execute() { - global $wgAllDBsAreLocalhost; - if( $wgAllDBsAreLocalhost ) { - $host = 'localhost'; - } else { - if( $this->hasOption('group') ) { - $db = wfGetDB( DB_SLAVE, $this->getOption('group') ); - $host = $db->getServer(); - } else { - $lb = wfGetLB(); - $i = $lb->getReaderIndex(); - $host = $lb->getServerName( $i ); - } - } - $this->output( "$host\n" ); - } +require_once( dirname(__FILE__).'/commandLine.inc' ); + +if ( $wgAllDBsAreLocalhost ) { + # Can't fool the backup script + print "localhost\n"; + exit; +} + +if( isset( $options['group'] ) ) { + $db = wfGetDB( DB_SLAVE, $options['group'] ); + $host = $db->getServer(); +} else { + $lb = wfGetLB(); + $i = $lb->getReaderIndex(); + $host = $lb->getServerName( $i ); } -$maintClass = "GetSlaveServer"; -require_once( DO_MAINTENANCE ); +print "$host\n"; + + diff --git a/maintenance/initStats.php b/maintenance/initStats.php index 2365718cc6..bb0cf304f5 100644 --- a/maintenance/initStats.php +++ b/maintenance/initStats.php @@ -9,22 +9,23 @@ * @author Rob Church * @licence GNU General Public Licence 2.0 or later */ + +$options = array( 'help', 'update', 'noviews' ); +require_once( 'commandLine.inc' ); +echo( "Refresh Site Statistics\n\n" ); -require_once( "Maintenance.php" ); +if( isset( $options['help'] ) ) { + showHelp(); + exit(1); +} -class InitStats extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Re-initialise the site statistics tables"; - $this->addParam( 'update', 'Update the existing statistics (preserves the ss_total_views field)' ); - $this->addParam( 'noviews', "Don't update the page view counter" ); - } +require "$IP/maintenance/initStats.inc"; +wfInitStats( $options ); - public function execute() { - $this->output( "Refresh Site Statistics\n\n" ); - SiteStats::init( $this->hasOption('update'), $this->hasOption('noviews') ); - } +function showHelp() { + echo( "Re-initialise the site statistics tables.\n\n" ); + echo( "Usage: php initStats.php [--update|--noviews]\n\n" ); + echo( " --update : Update the existing statistics (preserves the ss_total_views field)\n" ); + echo( "--noviews : Don't update the page view counter\n\n" ); } -$maintClass = "InitStats"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/mctest.php b/maintenance/mctest.php index 7cd5172db4..64fea06f31 100644 --- a/maintenance/mctest.php +++ b/maintenance/mctest.php @@ -8,63 +8,58 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +$optionsWithArgs = array( 'i' ); -class mcTest extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Makes several 'set', 'incr' and 'get' requests on every" - . " memcached server and shows a report"; - $this->addParam( 'i', 'Number of iterations', false, true ); - $this->addArgs( array( 'server' ) ); - } +require_once('commandLine.inc'); + +function microtime_float() +{ + list($usec, $sec) = explode(" ", microtime()); + return ((float)$usec + (float)$sec); +} - public function execute() { - global $wgMemCachedServers; - $iterations = $this->getOption( 'i', 100 ); - if( $this->hasArg() ) - $wgMemCachedServers = array( $this->getArg() ); +#$wgDebugLogFile = '/dev/stdout'; - foreach ( $wgMemCachedServers as $server ) { - $this->output( $server . " " ); - $mcc = new MemCachedClientforWiki( array('persistant' => true) ); - $mcc->set_servers( array( $server ) ); - $set = 0; - $incr = 0; - $get = 0; - $time_start = $this->microtime_float(); - for ( $i=1; $i<=$iterations; $i++ ) { - if ( !is_null( $mcc->set( "test$i", $i ) ) ) { - $set++; - } - } - for ( $i=1; $i<=$iterations; $i++ ) { - if ( !is_null( $mcc->incr( "test$i", $i ) ) ) { - $incr++; - } - } - for ( $i=1; $i<=$iterations; $i++ ) { - $value = $mcc->get( "test$i" ); - if ( $value == $i*2 ) { - $get++; - } - } - $exectime = $this->microtime_float() - $time_start; - - $this->output( "set: $set incr: $incr get: $get time: $exectime\n" ); +if ( isset( $args[0] ) ) { + $wgMemCachedServers = array( $args[0] ); +} +if ( isset( $options['i'] ) ) { + $iterations = $options['i']; +} else { + $iterations = 100; +} + +foreach ( $wgMemCachedServers as $server ) { + print "$server "; + $mcc = new MemCachedClientforWiki( array('persistant' => true) ); + $mcc->set_servers( array( $server ) ); + $set = 0; + $incr = 0; + $get = 0; + $time_start=microtime_float(); + for ( $i=1; $i<=$iterations; $i++ ) { + if ( !is_null( $mcc->set( "test$i", $i ) ) ) { + $set++; } } - /** - * Return microtime() as a float - * @return float - */ - private function microtime_float() { - list($usec, $sec) = explode(" ", microtime()); - return ((float)$usec + (float)$sec); + for ( $i=1; $i<=$iterations; $i++ ) { + if ( !is_null( $mcc->incr( "test$i", $i ) ) ) { + $incr++; + } } + + for ( $i=1; $i<=$iterations; $i++ ) { + $value = $mcc->get( "test$i" ); + if ( $value == $i*2 ) { + $get++; + } + } + $exectime=microtime_float()-$time_start; + + print "set: $set incr: $incr get: $get time: $exectime\n"; } -$maintClass = "mcTest"; -require_once( DO_MAINTENANCE ); + + diff --git a/maintenance/moveBatch.php b/maintenance/moveBatch.php index 13dd40a459..427e5d091d 100644 --- a/maintenance/moveBatch.php +++ b/maintenance/moveBatch.php @@ -1,7 +1,9 @@ mDescription = "Moves a batch of pages"; - $this->addParam( 'u', "User to perform move", false, true ); - $this->addParam( 'r', "Reason to move page", false, true ); - $this->addParam( 'i', "Interval to sleep between moves" ); - $this->addArgs( array( 'listfile' ) ); +$file = fopen( $filename, 'r' ); +if ( !$file ) { + print "Unable to read file, exiting\n"; + exit; +} + +$dbw = wfGetDB( DB_MASTER ); + +for ( $linenum = 1; !feof( $file ); $linenum++ ) { + $line = fgets( $file ); + if ( $line === false ) { + break; } - - public function execute() { - global $wgUser; - - # Change to current working directory - $oldCwd = getcwd(); - chdir( $oldCwd ); - - # Options processing - $user = $this->getOption( 'u', 'Move page script' ); - $reason = $this->getOption( 'r', '' ); - $interval = $this->getOption( 'i', 0 ); - if( $this->hasArg() ) { - $file = fopen( $this->getArg(), 'r' ); - } else { - $file = $this->getStdin(); - } - - # Setup - if( !$file ) { - $this->error( "Unable to read file, exiting\n", true ); - } - $wgUser = User::newFromName( $user ); - - # Setup complete, now start - $dbw = wfGetDB( DB_MASTER ); - for ( $linenum = 1; !feof( $file ); $linenum++ ) { - $line = fgets( $file ); - if ( $line === false ) { - break; - } - $parts = array_map( 'trim', explode( '|', $line ) ); - if ( count( $parts ) != 2 ) { - $this->error( "Error on line $linenum, no pipe character\n" ); - continue; - } - $source = Title::newFromText( $parts[0] ); - $dest = Title::newFromText( $parts[1] ); - if ( is_null( $source ) || is_null( $dest ) ) { - $this->error( "Invalid title on line $linenum\n" ); - continue; - } - - - $this->output( $source->getPrefixedText() . ' --> ' . $dest->getPrefixedText() ); - $dbw->begin(); - $err = $source->moveTo( $dest, false, $reason ); - if( $err !== true ) { - $this->output( "\nFAILED: $err" ); - } - $dbw->immediateCommit(); - $this->output( "\n" ); - - if ( $interval ) { - sleep( $interval ); - } - wfWaitForSlaves( 5 ); - } + $parts = array_map( 'trim', explode( '|', $line ) ); + if ( count( $parts ) != 2 ) { + print "Error on line $linenum, no pipe character\n"; + continue; } + $source = Title::newFromText( $parts[0] ); + $dest = Title::newFromText( $parts[1] ); + if ( is_null( $source ) || is_null( $dest ) ) { + print "Invalid title on line $linenum\n"; + continue; + } + + + print $source->getPrefixedText() . ' --> ' . $dest->getPrefixedText(); + $dbw->begin(); + $err = $source->moveTo( $dest, false, $reason ); + if( $err !== true ) { + print "\nFAILED: $err"; + } + $dbw->immediateCommit(); + print "\n"; + + if ( $interval ) { + sleep( $interval ); + } + wfWaitForSlaves( 5 ); } -$maintClass = "MoveBatch"; -require_once( DO_MAINTENANCE ); + + diff --git a/maintenance/nextJobDB.php b/maintenance/nextJobDB.php index fde6b49ec2..6af5cbecec 100644 --- a/maintenance/nextJobDB.php +++ b/maintenance/nextJobDB.php @@ -6,71 +6,55 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +$options = array( 'type' ); -class nextJobDB extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Pick a database that has pending jobs"; - $this->addParam( 'type', "The type of job to search for", false, true ); - } - public function execute() { - global $wgMemc; - $type = $this->getParam( 'type', false ); - $mckey = $type === false - ? "jobqueue:dbs" - : "jobqueue:dbs:$type"; - $pendingDBs = $wgMemcKey->get( $mckey ); - - # If we didn't get it from the cache - if( !$pendingDBs ) { - $pendingDBs = $this->getPendingDbs( $type ); - $wgMemc->get( $mckey, $pendingDBs, 300 ) - } - # If we've got a pending job in a db, display it. - if ( $pendingDBs ) { - $this->output( $pendingDBs[mt_rand(0, count( $pendingDBs ) - 1)] ); - } +require_once( 'commandLine.inc' ); + +$type = isset($options['type']) + ? $options['type'] + : false; + +$mckey = $type === false + ? "jobqueue:dbs" + : "jobqueue:dbs:$type"; + +$pendingDBs = $wgMemc->get( $mckey ); +if ( !$pendingDBs ) { + $pendingDBs = array(); + # Cross-reference DBs by master DB server + $dbsByMaster = array(); + foreach ( $wgLocalDatabases as $db ) { + $lb = wfGetLB( $db ); + $dbsByMaster[$lb->getServerName(0)][] = $db; } - - /** - * Get all databases that have a pending job - * @param $type String Job type - * @return array - */ - private function getPendingDbs( $type ) { - $pendingDBs = array(); - # Cross-reference DBs by master DB server - $dbsByMaster = array(); - foreach ( $wgLocalDatabases as $db ) { - $lb = wfGetLB( $db ); - $dbsByMaster[$lb->getServerName(0)][] = $db; - } - - foreach ( $dbsByMaster as $master => $dbs ) { - $dbConn = wfGetDB( DB_MASTER, array(), $dbs[0] ); - $stype = $dbConn->addQuotes($type); - $jobTable = $dbConn->getTable( 'job' ); - - # Padding row for MySQL bug - $sql = "(SELECT '-------------------------------------------')"; - foreach ( $dbs as $dbName ) { - if ( $sql != '' ) { - $sql .= ' UNION '; - } - if ($type === false) - $sql .= "(SELECT '$dbName' FROM `$dbName`.$jobTable LIMIT 1)"; - else - $sql .= "(SELECT '$dbName' FROM `$dbName`.$jobTable WHERE job_cmd=$stype LIMIT 1)"; - } - $res = $dbConn->query( $sql, __METHOD__ ); - $row = $dbConn->fetchRow( $res ); // discard padding row - while ( $row = $dbConn->fetchRow( $res ) ) { - $pendingDBs[] = $row[0]; + + foreach ( $dbsByMaster as $master => $dbs ) { + $dbConn = wfGetDB( DB_MASTER, array(), $dbs[0] ); + $stype = $dbConn->addQuotes($type); + + # Padding row for MySQL bug + $sql = "(SELECT '-------------------------------------------')"; + foreach ( $dbs as $dbName ) { + if ( $sql != '' ) { + $sql .= ' UNION '; } + if ($type === false) + $sql .= "(SELECT '$dbName' FROM `$dbName`.job LIMIT 1)"; + else + $sql .= "(SELECT '$dbName' FROM `$dbName`.job WHERE job_cmd=$stype LIMIT 1)"; + } + $res = $dbConn->query( $sql, 'nextJobDB.php' ); + $row = $dbConn->fetchRow( $res ); // discard padding row + while ( $row = $dbConn->fetchRow( $res ) ) { + $pendingDBs[] = $row[0]; } } + + $wgMemc->set( $mckey, $pendingDBs, 300 ); } -$maintClass = "nextJobDb"; -require_once( DO_MAINTENANCE ); +if ( $pendingDBs ) { + echo $pendingDBs[mt_rand(0, count( $pendingDBs ) - 1)]; +} + + diff --git a/maintenance/nukeNS.php b/maintenance/nukeNS.php index bd4eae093b..4f9fe926d2 100644 --- a/maintenance/nukeNS.php +++ b/maintenance/nukeNS.php @@ -19,80 +19,90 @@ * based on nukePage by Rob Church */ -require_once( "Maintenance.php" ); +require_once( 'commandLine.inc' ); +require_once( 'nukePage.inc' ); -class NukeNS extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Remove pages with only 1 revision from any namespace"; - $this->addParam( 'delete', "Actually delete the page" ); - $this->addParam( 'ns', 'Namespace to delete from, default NS_MEDIAWIKI', false, true ); - } +$ns = NS_MEDIAWIKI; +$delete = false; - public function execute() { - $ns = $this->getOption( 'ns', NS_MEDIAWIKI ); - $delete = $this->getOption( 'delete', false ); - $dbw = wfGetDB( DB_MASTER ); - $dbw->begin(); +if (isset($options['ns'])) +{ + $ns = $options['ns']; +} - $tbl_pag = $dbw->tableName( 'page' ); - $tbl_rev = $dbw->tableName( 'revision' ); - $res = $dbw->query( "SELECT page_title FROM $tbl_pag WHERE page_namespace = $ns" ); +if (isset( $options['delete'] ) and $options['delete']) +{ + $delete = true; +} - $n_deleted = 0; - while( $row = $dbw->fetchObject( $res ) ) { - //echo "$ns_name:".$row->page_title, "\n"; - $title = Title::newFromText($row->page_title, $ns); - $id = $title->getArticleID(); +NukeNS( $ns, $delete); - // Get corresponding revisions - $res2 = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_page = $id" ); - $revs = array(); +function NukeNS($ns_no, $delete) { - while( $row2 = $dbw->fetchObject( $res2 ) ) { - $revs[] = $row2->rev_id; - } - $count = count( $revs ); + $dbw = wfGetDB( DB_MASTER ); + $dbw->begin(); + + $tbl_pag = $dbw->tableName( 'page' ); + $tbl_rev = $dbw->tableName( 'revision' ); + $res = $dbw->query( "SELECT page_title FROM $tbl_pag WHERE page_namespace = $ns_no" ); - //skip anything that looks modified (i.e. multiple revs) - if (($count == 1)) { - #echo $title->getPrefixedText(), "\t", $count, "\n"; - $this->output( "delete: ", $title->getPrefixedText(), "\n" ); + $n_deleted = 0; + + while( $row = $dbw->fetchObject( $res ) ) { + //echo "$ns_name:".$row->page_title, "\n"; + $title = Title::newFromText($row->page_title, $ns_no); + $id = $title->getArticleID(); - //as much as I hate to cut & paste this, it's a little different, and - //I already have the id & revs - if( $delete ) { - $dbw->query( "DELETE FROM $tbl_pag WHERE page_id = $id" ); - $dbw->commit(); - // Delete revisions as appropriate - $child = $this->spawnChild( 'NukePage', 'NukePage.php' ); - $child->deleteRevisions( $revs ); - $this->purgeRedundantText( true ); - $n_deleted ++; - } - } else { - $this->output( "skip: ", $title->getPrefixedText(), "\n" ); - } - } - $dbw->commit(); + // Get corresponding revisions + $res2 = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_page = $id" ); + $revs = array(); + + while( $row2 = $dbw->fetchObject( $res2 ) ) { + $revs[] = $row2->rev_id; + } + $count = count( $revs ); - if ($n_deleted > 0) { - #update statistics - better to decrement existing count, or just count - #the page table? - $pages = $dbw->selectField('site_stats', 'ss_total_pages'); - $pages -= $n_deleted; - $dbw->update( 'site_stats', - array('ss_total_pages' => $pages ), - array( 'ss_row_id' => 1), - __METHOD__ ); - } - - if (!$delete) { - $this->output( "To update the database, run the script with the --delete option.\n" ); - } - } + //skip anything that looks modified (i.e. multiple revs) + if (($count == 1)) { + #echo $title->getPrefixedText(), "\t", $count, "\n"; + echo "delete: ", $title->getPrefixedText(), "\n"; + + //as much as I hate to cut & paste this, it's a little different, and + //I already have the id & revs + + if( $delete ) { + $dbw->query( "DELETE FROM $tbl_pag WHERE page_id = $id" ); + $dbw->commit(); + // Delete revisions as appropriate + DeleteRevisions( $revs ); + PurgeRedundantText( true ); + $n_deleted ++; + } + } else { + echo "skip: ", $title->getPrefixedText(), "\n"; + } + + + } + $dbw->commit(); + + if ($n_deleted > 0) { + #update statistics - better to decrement existing count, or just count + #the page table? + $pages = $dbw->selectField('site_stats', 'ss_total_pages'); + $pages -= $n_deleted; + $dbw->update( 'site_stats', + array('ss_total_pages' => $pages ), + array( 'ss_row_id' => 1), + __METHOD__ ); + + } + + if (!$delete) { + echo( "To update the database, run the script with the --delete option.\n" ); + } + } -$maintClass = "NukeNS"; -require_once( DO_MAINTENANCE ); + diff --git a/maintenance/nukePage.php b/maintenance/nukePage.php index ac2059f223..b3bfc7626d 100644 --- a/maintenance/nukePage.php +++ b/maintenance/nukePage.php @@ -1,4 +1,5 @@ */ -require_once( "Maintenance.php" ); - -class NukePage extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Remove a page record from the database"; - $this->addParam( 'delete', "Actually delete the page" ); - $this->addArgs( array( 'title' ) ); - } - - public function execute() { - - $name = $this->getArg(); - $delete = $this->getOption( 'delete', false ); - - $dbw = wfGetDB( DB_MASTER ); - $dbw->begin(); - - $tbl_pag = $dbw->tableName( 'page' ); - $tbl_rec = $dbw->tableName( 'recentchanges' ); - $tbl_rev = $dbw->tableName( 'revision' ); - - # Get page ID - $this->output( "Searching for \"$name\"..." ); - $title = Title::newFromText( $name ); - if( $title ) { - $id = $title->getArticleID(); - $real = $title->getPrefixedText(); - $isGoodArticle = $title->isContentPage(); - $this->output( "found \"$real\" with ID $id.\n" ); +require_once( 'commandLine.inc' ); +require_once( 'nukePage.inc' ); - # Get corresponding revisions - $this->output( "Searching for revisions..." ); - $res = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_page = $id" ); - while( $row = $dbw->fetchObject( $res ) ) { - $revs[] = $row->rev_id; - } - $count = count( $revs ); - $this->output( "found $count.\n" ); +echo( "Erase Page Record\n\n" ); - # Delete the page record and associated recent changes entries - if( $delete ) { - $this->output( "Deleting page record..." ); - $dbw->query( "DELETE FROM $tbl_pag WHERE page_id = $id" ); - $this->output( "done.\n" ); - $this->output( "Cleaning up recent changes..." ); - $dbw->query( "DELETE FROM $tbl_rec WHERE rc_cur_id = $id" ); - $this->output( "done.\n" ); - } - - $dbw->commit(); - - # Delete revisions as appropriate - if( $delete && $count ) { - $this->output( "Deleting revisions..." ); - $this->deleteRevisions( $revs ); - $this->output( "done.\n" ); - $this->purgeRedundantText( true ); - } - - # Update stats as appropriate - if ( $delete ) { - $this->output( "Updating site stats..." ); - $ga = $isGoodArticle ? -1 : 0; // if it was good, decrement that too - $stats = new SiteStatsUpdate( 0, -$count, $ga, -1 ); - $stats->doUpdate(); - $this->output( "done.\n" ); - } - } else { - $this->output( "not found in database.\n" ); - $dbw->commit(); - } - } - - public function deleteRevisions( $ids ) { - $dbw = wfGetDB( DB_MASTER ); - $dbw->begin(); - - $tbl_rev = $dbw->tableName( 'revision' ); - - $set = implode( ', ', $ids ); - $dbw->query( "DELETE FROM $tbl_rev WHERE rev_id IN ( $set )" ); +if( isset( $args[0] ) ) { + NukePage( $args[0], true ); +} else { + ShowUsage(); +} - $dbw->commit(); - } +/** Show script usage information */ +function ShowUsage() { + echo( "Remove a page record from the database.\n\n" ); + echo( "Usage: php nukePage.php \n\n" ); + echo( " <title> : Page title; spaces escaped with underscores\n\n" ); } -$maintClass = "NukePage"; -require_once( DO_MAINTENANCE ); \ No newline at end of file diff --git a/maintenance/populateLogSearch.php b/maintenance/populateLogSearch.php index 01b04b5f01..3679f7efee 100644 --- a/maintenance/populateLogSearch.php +++ b/maintenance/populateLogSearch.php @@ -9,88 +9,13 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); - -class PopulateLogSearch extends Maintenance { - - const LOG_SEARCH_BATCH_SIZE = 100; - - public function __construct() { - parent::__construct(); - $this->mDescription = "Migrate log params to new table and index for searching"; - } - - public function execute() { - $db = wfGetDB( DB_MASTER ); - if ( !$db->tableExists( 'log_search' ) ) { - $this->error( "log_search does not exist\n", true ); - } - $start = $db->selectField( 'logging', 'MIN(log_id)', false, __FUNCTION__ ); - if( !$start ) { - $this->output( "Nothing to do.\n" ); - return true; - } - $end = $db->selectField( 'logging', 'MAX(log_id)', false, __FUNCTION__ ); +require_once 'commandLine.inc'; +require_once 'populateLogSearch.inc'; - # Do remaining chunk - $end += self::LOG_SEARCH_BATCH_SIZE - 1; - $blockStart = $start; - $blockEnd = $start + self::LOG_SEARCH_BATCH_SIZE - 1; - while( $blockEnd <= $end ) { - $this->output( "...doing log_id from $blockStart to $blockEnd\n" ); - $cond = "log_id BETWEEN $blockStart AND $blockEnd"; - $res = $db->select( 'logging', '*', $cond, __FUNCTION__ ); - $batch = array(); - while( $row = $db->fetchObject( $res ) ) { - // RevisionDelete logs - revisions - if( LogEventsList::typeAction( $row, array('delete','suppress'), 'revision' ) ) { - $params = LogPage::extractParams( $row->log_params ); - // Param format: <urlparam> <item CSV> [<ofield> <nfield>] - if( count($params) >= 2 ) { - $field = RevisionDeleter::getRelationType($params[0]); - // B/C, the params may start with a title key - if( $field == null ) { - array_shift($params); - $field = RevisionDeleter::getRelationType($params[0]); - } - if( $field == null ) { - $this->output( "Invalid param type for $row->log_id\n" ); - continue; // skip this row - } - $items = explode(',',$params[1]); - $log = new LogPage( $row->log_type ); - $log->addRelations( $field, $items, $row->log_id ); - } - // RevisionDelete logs - log events - } else if( LogEventsList::typeAction( $row, array('delete','suppress'), 'event' ) ) { - $params = LogPage::extractParams( $row->log_params ); - // Param format: <item CSV> [<ofield> <nfield>] - if( count($params) >= 1 ) { - $items = explode(',',$params[0]); - $log = new LogPage( $row->log_type ); - $log->addRelations( 'log_id', $items, $row->log_id ); - } - } - } - $blockStart += self::LOG_SEARCH_BATCH_SIZE; - $blockEnd += self::LOG_SEARCH_BATCH_SIZE; - wfWaitForSlaves( 5 ); - } - if( $db->insert( - 'updatelog', - array( 'ul_key' => 'populate log_search' ), - __FUNCTION__, - 'IGNORE' - ) - ) { - $this->output( "log_search population complete.\n" ); - return true; - } else { - $this->output( "Could not insert log_search population row.\n" ); - return false; - } - } +$db =& wfGetDB( DB_MASTER ); +if ( !$db->tableExists( 'log_search' ) ) { + echo "log_search does not exist\n"; + exit( 1 ); } -$maintClass = "PopulateLogSearch"; -require_once( DO_MAINTENANCE ); +migrate_log_params( $db ); diff --git a/maintenance/populateParentId.php b/maintenance/populateParentId.php index dd114fdd26..0173003342 100644 --- a/maintenance/populateParentId.php +++ b/maintenance/populateParentId.php @@ -1,105 +1,18 @@ <?php + /* * Makes the required database updates for rev_parent_id * to be of any use. It can be used for some simple tracking * and to find new page edits by users. */ -require_once( "Maintenance.php" ); - -class PopulateParentId extends Maintenance { - - // Batch size - const BATCH_SIZE = 200; - - public function __construct() { - parent::__construct(); - $this->mDescription = "Populates rev_parent_id"; - } - - public function execute() { - $db = wfGetDB( DB_MASTER ); - if ( !$db->tableExists( 'revision' ) ) { - $this->error( "revision table does not exist\n", true ); - } - $this->output( "Populating rev_parent_id column\n" ); - $start = $db->selectField( 'revision', 'MIN(rev_id)', false, __FUNCTION__ ); - $end = $db->selectField( 'revision', 'MAX(rev_id)', false, __FUNCTION__ ); - if( is_null( $start ) || is_null( $end ) ){ - $this->output( "...revision table seems to be empty.\n" ); - $db->insert( 'updatelog', - array( 'ul_key' => 'populate rev_parent_id' ), - __FUNCTION__, - 'IGNORE' ); - return; - } - # Do remaining chunk - $end += self::BATCH_SIZE - 1; - $blockStart = intval( $start ); - $blockEnd = intval( $start ) + self::BATCH_SIZE - 1; - $count = 0; - $changed = 0; - while( $blockEnd <= $end ) { - $this->output( "...doing rev_id from $blockStart to $blockEnd\n" ); - $cond = "rev_id BETWEEN $blockStart AND $blockEnd"; - $res = $db->select( 'revision', - array('rev_id','rev_page','rev_timestamp','rev_parent_id'), - $cond, __FUNCTION__ ); - # Go through and update rev_parent_id from these rows. - # Assume that the previous revision of the title was - # the original previous revision of the title when the - # edit was made... - foreach( $res as $row ) { - # First, check rows with the same timestamp other than this one - # with a smaller rev ID. The highest ID "wins". This avoids loops - # as timestamp can only decrease and never loops with IDs (from parent to parent) - $previousID = $db->selectField( 'revision', 'rev_id', - array( 'rev_page' => $row->rev_page, 'rev_timestamp' => $row->rev_timestamp, - "rev_id < " . intval( $row->rev_id ) ), - __FUNCTION__, - array( 'ORDER BY' => 'rev_id DESC' ) ); - # If there are none, check the the highest ID with a lower timestamp - if( !$previousID ) { - # Get the highest older timestamp - $lastTimestamp = $db->selectField( 'revision', 'rev_timestamp', - array( 'rev_page' => $row->rev_page, "rev_timestamp < " . $db->addQuotes( $row->rev_timestamp ) ), - __FUNCTION__, - array( 'ORDER BY' => 'rev_timestamp DESC' ) ); - # If there is one, let the highest rev ID win - if( $lastTimestamp ) { - $previousID = $db->selectField( 'revision', 'rev_id', - array( 'rev_page' => $row->rev_page, 'rev_timestamp' => $lastTimestamp ), - __FUNCTION__, - array( 'ORDER BY' => 'rev_id DESC' ) ); - } - } - $previousID = intval($previousID); - if( $previousID != $row->rev_parent_id ) - $changed++; - # Update the row... - $db->update( 'revision', - array( 'rev_parent_id' => $previousID ), - array( 'rev_id' => $row->rev_id ), - __FUNCTION__ ); - $count++; - } - $blockStart += self::BATCH_SIZE - 1; - $blockEnd += self::BATCH_SIZE - 1; - wfWaitForSlaves( 5 ); - } - $logged = $db->insert( 'updatelog', - array( 'ul_key' => 'populate rev_parent_id' ), - __FUNCTION__, - 'IGNORE' ); - if( $logged ) { - $this->output( "rev_parent_id population complete ... {$count} rows [{$changed} changed]\n" ); - return true; - } else { - $this->output( "Could not insert rev_parent_id population row.\n" ); - return false; - } - } +require_once 'commandLine.inc'; +require_once 'populateParentId.inc'; + +$db =& wfGetDB( DB_MASTER ); +if ( !$db->tableExists( 'revision' ) ) { + echo "revision table does not exist\n"; + exit( 1 ); } -$maintClass = "PopulateParentId"; -require_once( DO_MAINTENANCE ); +populate_rev_parent_id( $db ); diff --git a/maintenance/purgeOldText.php b/maintenance/purgeOldText.php index 08f5ef1aac..4a4be4822b 100644 --- a/maintenance/purgeOldText.php +++ b/maintenance/purgeOldText.php @@ -1,24 +1,29 @@ <?php + /** * Purge old text records from the database * + * @file * @ingroup Maintenance * @author Rob Church <robchur@gmail.com> */ -require_once( "Maintenance.php" ); +$options = array( 'purge', 'help' ); +require_once( 'commandLine.inc' ); +require_once( 'purgeOldText.inc' ); + +echo( "Purge Old Text\n\n" ); + +if( @$options['help'] ) { + ShowUsage(); +} else { + PurgeRedundantText( @$options['purge'] ); +} -class PurgeOldText extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Purge old text records from the database"; - $this->addOption( 'purge', 'Performs the deletion' ); - } - - public function execute() { - $this->purgeRedundantText( $this->hasOption('purge') ); - } +function ShowUsage() { + echo( "Prunes unused text records from the database.\n\n" ); + echo( "Usage: php purgeOldText.php [--purge]\n\n" ); + echo( "purge : Performs the deletion\n" ); + echo( " help : Show this usage information\n" ); } -$maintClass = "PurgeOldText"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/reassignEdits.php b/maintenance/reassignEdits.php index daed21954c..5825644e80 100644 --- a/maintenance/reassignEdits.php +++ b/maintenance/reassignEdits.php @@ -1,153 +1,56 @@ <?php + /** * Reassign edits from a user or IP address to another user * + * @file * @ingroup Maintenance * @author Rob Church <robchur@gmail.com> * @licence GNU General Public Licence 2.0 or later */ -require_once( "Maintenance.php" ); - -class ReassignEdits extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Reassign edits from one user to another"; - $this->addParam( "force", "Reassign even if the target user doesn't exist" ); - $this->addParam( "norc", "Don't update the recent changes table" ); - $this->addParam( "report", "Print out details of what would be changed, but don't update it" ); - $this->addArgs( array( 'from', 'to' ) ); - } - - public function execute() { - if( $this->hasArg(0) && $this->hasArg(1) ) { - # Set up the users involved - $from =& $this->initialiseUser( $this->getArg(0) ); - $to =& $this->initialiseUser( $this->getArg(1) ); - - # If the target doesn't exist, and --force is not set, stop here - if( $to->getId() || $this->hasOption('force') ) { - # Reassign the edits - $report = $this->hasOption('report'); - $count = $this->reassignEdits( $from, $to, !$this->hasOption('norc'), $report ); - # If reporting, and there were items, advise the user to run without --report - if( $report ) - $this->output( "Run the script again without --report to update.\n" ); - } else { - $ton = $to->getName(); - $this->error( "User '{$ton}' not found.\n" ); - } - } +$options = array( 'force', 'norc', 'quiet', 'report' ); +require_once( 'commandLine.inc' ); +require_once( 'reassignEdits.inc' ); + +# Set silent mode; --report overrides --quiet +if( !@$options['report'] && @$options['quiet'] ) + setSilent(); + +out( "Reassign Edits\n\n" ); + +if( @$args[0] && @$args[1] ) { + + # Set up the users involved + $from =& initialiseUser( $args[0] ); + $to =& initialiseUser( $args[1] ); + + # If the target doesn't exist, and --force is not set, stop here + if( $to->getId() || @$options['force'] ) { + # Reassign the edits + $report = @$options['report']; + $count = reassignEdits( $from, $to, !@$options['norc'], $report ); + # If reporting, and there were items, advise the user to run without --report + if( $report ) + out( "Run the script again without --report to update.\n" ); + } else { + $ton = $to->getName(); + echo( "User '{$ton}' not found.\n" ); } - - /** - * Reassign edits from one user to another - * - * @param $from User to take edits from - * @param $to User to assign edits to - * @param $rc Update the recent changes table - * @param $report Don't change things; just echo numbers - * @return integer Number of entries changed, or that would be changed - */ - private function reassignEdits( &$from, &$to, $rc = false, $report = false ) { - $dbw = wfGetDB( DB_MASTER ); - $dbw->immediateBegin(); - - # Count things - $this->output( "Checking current edits..." ); - $res = $dbw->select( 'revision', 'COUNT(*) AS count', $this->userConditions( $from, 'rev_user', 'rev_user_text' ), __METHOD__ ); - $row = $dbw->fetchObject( $res ); - $cur = $row->count; - $this->output( "found {$cur}.\n" ); - - $this->output( "Checking deleted edits..." ); - $res = $dbw->select( 'archive', 'COUNT(*) AS count', $this->userConditions( $from, 'ar_user', 'ar_user_text' ), __METHOD__ ); - $row = $dbw->fetchObject( $res ); - $del = $row->count; - $this->output( "found {$del}.\n" ); - - # Don't count recent changes if we're not supposed to - if( $rc ) { - $this->output( "Checking recent changes..." ); - $res = $dbw->select( 'recentchanges', 'COUNT(*) AS count', $this->userConditions( $from, 'rc_user', 'rc_user_text' ), __METHOD__ ); - $row = $dbw->fetchObject( $res ); - $rec = $row->count; - $this->output( "found {$rec}.\n" ); - } else { - $rec = 0; - } - - $total = $cur + $del + $rec; - $this->output( "\nTotal entries to change: {$total}\n" ); - - if( !$report ) { - if( $total ) { - # Reassign edits - $this->output( "\nReassigning current edits..." ); - $res = $dbw->update( 'revision', userSpecification( $to, 'rev_user', 'rev_user_text' ), $this->userConditions( $from, 'rev_user', 'rev_user_text' ), __METHOD__ ); - $this->output( "done.\nReassigning deleted edits..." ); - $res = $dbw->update( 'archive', userSpecification( $to, 'ar_user', 'ar_user_text' ), $this->userConditions( $from, 'ar_user', 'ar_user_text' ), __METHOD__ ); - $this->output( "done.\n" ); - # Update recent changes if required - if( $rc ) { - $this->output( "Updating recent changes..." ); - $res = $dbw->update( 'recentchanges', $this->userSpecification( $to, 'rc_user', 'rc_user_text' ), $this->userConditions( $from, 'rc_user', 'rc_user_text' ), __METHOD__ ); - $this->output( "done.\n" ); - } - } - } - $dbw->immediateCommit(); - return (int)$total; - } - - /** - * Return the most efficient set of user conditions - * i.e. a user => id mapping, or a user_text => text mapping - * - * @param $user User for the condition - * @param $idfield Field name containing the identifier - * @param $utfield Field name containing the user text - * @return array - */ - private function userConditions( &$user, $idfield, $utfield ) { - return $user->getId() ? array( $idfield => $user->getId() ) : array( $utfield => $user->getName() ); - } - - /** - * Return user specifications - * i.e. user => id, user_text => text - * - * @param $user User for the spec - * @param $idfield Field name containing the identifier - * @param $utfield Field name containing the user text - * @return array - */ - private function userSpecification( &$user, $idfield, $utfield ) { - return array( $idfield => $user->getId(), $utfield => $user->getName() ); - } - - /** - * Initialise the user object - * - * @param $username Username or IP address - * @return User - */ - private function initialiseUser( $username ) { - if( User::isIP( $username ) ) { - $user = new User(); - $user->setId( 0 ); - $user->setName( $username ); - } else { - $user = User::newFromName( $username ); - } - $user->load(); - return $user; - } - - +} else { + ShowUsage(); } -$maintClass = "ReassignEdits"; -require_once( DO_MAINTENANCE ); +/** Show script usage information */ +function ShowUsage() { + echo( "Reassign edits from one user to another.\n\n" ); + echo( "Usage: php reassignEdits.php [--force|--quiet|--norc|--report] <from> <to>\n\n" ); + echo( " <from> : Name of the user to assign edits from\n" ); + echo( " <to> : Name of the user to assign edits to\n" ); + echo( " --force : Reassign even if the target user doesn't exist\n" ); + echo( " --quiet : Don't print status information (except for errors)\n" ); + echo( " --norc : Don't update the recent changes table\n" ); + echo( " --report : Print out details of what would be changed, but don't update it\n\n" ); +} diff --git a/maintenance/rebuildFileCache.php b/maintenance/rebuildFileCache.php index c24ad612d8..8c01b90fa8 100644 --- a/maintenance/rebuildFileCache.php +++ b/maintenance/rebuildFileCache.php @@ -6,96 +6,87 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +/** */ +require_once( "commandLine.inc" ); +if( !$wgUseFileCache ) { + echo "Nothing to do -- \$wgUseFileCache is disabled.\n"; + exit(0); +} +$wgDisableCounters = false; // no real hits here -class RebuildFileCache extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Build file cache for content pages"; - $this->addArgs( array( 'start', 'overwrite' ) ); - } +$start = isset($args[0]) ? intval($args[0]) : 0; +$overwrite = isset( $args[1] ) && $args[1] === 'overwrite'; +echo "Building content page file cache from page {$start}!\n"; +echo "Format: <start> [overwrite]\n"; - public function execute() { - global $wgUseFileCache, $wgDisableCounters, $wgTitle, $wgArticle, $wgOut; - if( !$wgUseFileCache ) { - $this->error( "Nothing to do -- \$wgUseFileCache is disabled.\n", true ); - } - $wgDisableCounters = false; - $start = intval( $this->getArg( 0, 0 ) ); - $overwrite = $this->hasArg(1) && $this->getArg(1) === 'overwrite'; - $this->output( "Building content page file cache from page {$start}!\n" ); - - $dbr = wfGetDB( DB_SLAVE ); - $start = $start > 0 ? $start : $dbr->selectField( 'page', 'MIN(page_id)', false, __FUNCTION__ ); - $end = $dbr->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ ); - if( !$start ) { - $this->error( "Nothing to do.\n", true ); +$dbr = wfGetDB( DB_SLAVE ); +$start = $start > 0 ? $start : $dbr->selectField( 'page', 'MIN(page_id)', false, __FUNCTION__ ); +$end = $dbr->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ ); +if( !$start ) { + die("Nothing to do.\n"); +} + +$_SERVER['HTTP_ACCEPT_ENCODING'] = 'bgzip'; // hack, no real client +OutputPage::setEncodings(); # Not really used yet + +$BATCH_SIZE = 100; +# Do remaining chunk +$end += $BATCH_SIZE - 1; +$blockStart = $start; +$blockEnd = $start + $BATCH_SIZE - 1; + +$dbw = wfGetDB( DB_MASTER ); +// Go through each page and save the output +while( $blockEnd <= $end ) { + // Get the pages + $res = $dbr->select( 'page', array('page_namespace','page_title','page_id'), + array('page_namespace' => $wgContentNamespaces, + "page_id BETWEEN $blockStart AND $blockEnd" ), + array('ORDER BY' => 'page_id ASC','USE INDEX' => 'PRIMARY') + ); + while( $row = $dbr->fetchObject( $res ) ) { + $rebuilt = false; + $wgTitle = Title::makeTitleSafe( $row->page_namespace, $row->page_title ); + if( null == $wgTitle ) { + echo "Page {$row->page_id} bad title\n"; + continue; // broken title? } - - $_SERVER['HTTP_ACCEPT_ENCODING'] = 'bgzip'; // hack, no real client - OutputPage::setEncodings(); # Not really used yet - - $BATCH_SIZE = 100; - # Do remaining chunk - $end += $BATCH_SIZE - 1; - $blockStart = $start; - $blockEnd = $start + $BATCH_SIZE - 1; - - $dbw = wfGetDB( DB_MASTER ); - // Go through each page and save the output - while( $blockEnd <= $end ) { - // Get the pages - $res = $dbr->select( 'page', array('page_namespace','page_title','page_id'), - array('page_namespace' => $wgContentNamespaces, - "page_id BETWEEN $blockStart AND $blockEnd" ), - array('ORDER BY' => 'page_id ASC','USE INDEX' => 'PRIMARY') - ); - while( $row = $dbr->fetchObject( $res ) ) { - $rebuilt = false; - $wgTitle = Title::makeTitleSafe( $row->page_namespace, $row->page_title ); - if( null == $wgTitle ) { - $this->output( "Page {$row->page_id} bad title\n" ); - continue; // broken title? - } - $wgArticle = new Article( $wgTitle ); - // If the article is cacheable, then load it - if( $wgArticle->isFileCacheable() ) { - $cache = new HTMLFileCache( $wgTitle ); - if( $cache->isFileCacheGood() ) { - if( $overwrite ) { - $rebuilt = true; - } else { - $this->output( "Page {$row->page_id} already cached\n" ); - continue; // done already! - } - } - ob_start( array(&$cache, 'saveToFileCache' ) ); // save on ob_end_clean() - $wgUseFileCache = false; // hack, we don't want $wgArticle fiddling with filecache - $wgArticle->view(); - @$wgOut->output(); // header notices - $wgUseFileCache = true; - ob_end_clean(); // clear buffer - $wgOut = new OutputPage(); // empty out any output page garbage - if( $rebuilt ) - $this->output( "Re-cached page {$row->page_id}\n" ); - else - $this->output( "Cached page {$row->page_id}\n" ); + $wgArticle = new Article( $wgTitle ); + // If the article is cacheable, then load it + if( $wgArticle->isFileCacheable() ) { + $cache = new HTMLFileCache( $wgTitle ); + if( $cache->isFileCacheGood() ) { + if( $overwrite ) { + $rebuilt = true; } else { - $this->output( "Page {$row->page_id} not cacheable\n" ); + echo "Page {$row->page_id} already cached\n"; + continue; // done already! } - $dbw->commit(); // commit any changes } - $blockStart += $BATCH_SIZE; - $blockEnd += $BATCH_SIZE; - wfWaitForSlaves( 5 ); + ob_start( array(&$cache, 'saveToFileCache' ) ); // save on ob_end_clean() + $wgUseFileCache = false; // hack, we don't want $wgArticle fiddling with filecache + $wgArticle->view(); + @$wgOut->output(); // header notices + $wgUseFileCache = true; + ob_end_clean(); // clear buffer + $wgOut = new OutputPage(); // empty out any output page garbage + if( $rebuilt ) + echo "Re-cached page {$row->page_id}\n"; + else + echo "Cached page {$row->page_id}\n"; + } else { + echo "Page {$row->page_id} not cacheable\n"; } - $this->output( "Done!\n" ); - - // Remove these to be safe - if( isset($wgTitle) ) - unset($wgTitle); - if( isset($wgArticle) ) - unset($wgArticle); + $dbw->commit(); // commit any changes } + $blockStart += $BATCH_SIZE; + $blockEnd += $BATCH_SIZE; + wfWaitForSlaves( 5 ); } -require_once( "commandLine.inc" ); +echo "Done!\n"; + +// Remove these to be safe +if( isset($wgTitle) ) + unset($wgTitle); +if( isset($wgArticle) ) + unset($wgArticle); diff --git a/maintenance/refreshImageCount.php b/maintenance/refreshImageCount.php index e0f22b839d..14f842b950 100644 --- a/maintenance/refreshImageCount.php +++ b/maintenance/refreshImageCount.php @@ -7,34 +7,23 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); - -class RefreshImageCount extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Resets ss_image count, forcing slaves to pick it up."; - } - - public function execute() { - $dbw = wfGetDB( DB_MASTER ); - - // Load the current value from the master - $count = $dbw->selectField( 'site_stats', 'ss_images' ); - - $this->output( wfWikiID() . ": forcing ss_images to $count\n" ); - - // First set to NULL so that it changes on the master - $dbw->update( 'site_stats', - array( 'ss_images' => null ), - array( 'ss_row_id' => 1 ) ); - - // Now this update will be forced to go out - $dbw->update( 'site_stats', - array( 'ss_images' => $count ), - array( 'ss_row_id' => 1 ) ); - } -} - -$maintClass = "RefreshImageCount"; -require_once( DO_MAINTENANCE ); +require_once( "commandLine.inc" ); + +$dbw = wfGetDB( DB_MASTER ); + +// Load the current value from the master +$count = $dbw->selectField( 'site_stats', 'ss_images' ); + +echo wfWikiID().": forcing ss_images to $count\n"; + +// First set to NULL so that it changes on the master +$dbw->update( 'site_stats', + array( 'ss_images' => null ), + array( 'ss_row_id' => 1 ) ); + +// Now this update will be forced to go out +$dbw->update( 'site_stats', + array( 'ss_images' => $count ), + array( 'ss_row_id' => 1 ) ); + diff --git a/maintenance/removeUnusedAccounts.php b/maintenance/removeUnusedAccounts.php index bf03154572..5f74b65538 100644 --- a/maintenance/removeUnusedAccounts.php +++ b/maintenance/removeUnusedAccounts.php @@ -8,89 +8,63 @@ * @author Rob Church <robchur@gmail.com> */ -require_once( "Maintenance.php" ); +$options = array( 'help', 'delete' ); +require_once( 'commandLine.inc' ); +require_once( 'removeUnusedAccounts.inc' ); +echo( "Remove Unused Accounts\n\n" ); +$fname = 'removeUnusedAccounts'; -class RemoveUnusedAccounts extends Maintenance { - public function __construct() { - parent::__construct(); - $this->addParam( 'delete', 'Actually delete the account' ); - $this->addParam( 'ignore-groups', 'List of comma-separated groups to exclude', false, true ); - $this->addParam( 'ignore-touched', 'Skip accounts touched in last N days', false, true ); - } - - public function execute() { +if( isset( $options['help'] ) ) { + showHelp(); + exit(1); +} - $this->output( "Remove unused accounts\n\n" ); - - # Do an initial scan for inactive accounts and report the result - $this->output( "Checking for unused user accounts...\n" ); - $del = array(); - $dbr = wfGetDB( DB_SLAVE ); - $res = $dbr->select( 'user', array( 'user_id', 'user_name', 'user_touched' ), '', __METHOD__ ); - if( $this->hasOption('ignore-groups') ) { - $excludedGroups = explode( ',', $this->getOption('ignore-groups') ); - } else { - $excludedGroups = array(); - } - $touched = $this->getOption( 'ignore-touched', "1" ); - if( !ctype_digit( $touched ) ) { - $this->error( "Please put a valid positive integer on the --ignore-touched parameter.\n", true ); - } - $touchedSeconds = 86400 * $touched; - while( $row = $dbr->fetchObject( $res ) ) { - # Check the account, but ignore it if it's within a $excludedGroups group or if it's touched within the $touchedSeconds seconds. - $instance = User::newFromId( $row->user_id ); - if( count( array_intersect( $instance->getEffectiveGroups(), $excludedGroups ) ) == 0 - && $this->isInactiveAccount( $row->user_id, true ) - && wfTimestamp( TS_UNIX, $row->user_touched ) < wfTimestamp( TS_UNIX, time() - $touchedSeconds ) - ) { - # Inactive; print out the name and flag it - $del[] = $row->user_id; - $this->output( $row->user_name . "\n" ); - } +# Do an initial scan for inactive accounts and report the result +echo( "Checking for unused user accounts...\n" ); +$del = array(); +$dbr = wfGetDB( DB_SLAVE ); +$res = $dbr->select( 'user', array( 'user_id', 'user_name', 'user_touched' ), '', $fname ); +if( isset( $options['ignore-groups'] ) ) { + $excludedGroups = explode( ',', $options['ignore-groups'] ); +} else { $excludedGroups = array(); } +$touchedSeconds = 0; +if( isset( $options['ignore-touched'] ) ) { + $touchedParamError = 0; + if( ctype_digit( $options['ignore-touched'] ) ) { + if( $options['ignore-touched'] <= 0 ) { + $touchedParamError = 1; } - $count = count( $del ); - $this->output( "...found {$count}.\n" ); - - # If required, go back and delete each marked account - if( $count > 0 && $this->hasOption('delete') ) { - $this->output( "\nDeleting inactive accounts..." ); - $dbw = wfGetDB( DB_MASTER ); - $dbw->delete( 'user', array( 'user_id' => $del ), __METHOD__ ); - $this->output( "done.\n" ); - # Update the site_stats.ss_users field - $users = $dbw->selectField( 'user', 'COUNT(*)', array(), __METHOD__ ); - $dbw->update( 'site_stats', array( 'ss_users' => $users ), array( 'ss_row_id' => 1 ), __METHOD__ ); - } elseif( $count > 0 ) { - $this->output( "\nRun the script again with --delete to remove them from the database.\n" ); - } - $this->output( "\n" ); - } - - /** - * Could the specified user account be deemed inactive? - * (No edits, no deleted edits, no log entries, no current/old uploads) - * - * @param $id User's ID - * @param $master Perform checking on the master - * @return bool - */ - private function isInactiveAccount( $id, $master = false ) { - $dbo = wfGetDB( $master ? DB_MASTER : DB_SLAVE ); - $checks = array( 'revision' => 'rev', 'archive' => 'ar', 'logging' => 'log', - 'image' => 'img', 'oldimage' => 'oi' ); - $count = 0; - - $dbo->immediateBegin(); - foreach( $checks as $table => $fprefix ) { - $conds = array( $fprefix . '_user' => $id ); - $count += (int)$dbo->selectField( $table, 'COUNT(*)', $conds, __METHOD__ ); - } - $dbo->immediateCommit(); - - return $count == 0; + } else { $touchedParamError = 1; } + if( $touchedParamError == 1 ) { + die( "Please put a valid positive integer on the --ignore-touched parameter.\n" ); + } else { $touchedSeconds = 86400 * $options['ignore-touched']; } +} +while( $row = $dbr->fetchObject( $res ) ) { + # Check the account, but ignore it if it's within a $excludedGroups group or if it's touched within the $touchedSeconds seconds. + $instance = User::newFromId( $row->user_id ); + if( count( array_intersect( $instance->getEffectiveGroups(), $excludedGroups ) ) == 0 + && isInactiveAccount( $row->user_id, true ) + && wfTimestamp( TS_UNIX, $row->user_touched ) < wfTimestamp( TS_UNIX, time() - $touchedSeconds ) + ) { + # Inactive; print out the name and flag it + $del[] = $row->user_id; + echo( $row->user_name . "\n" ); } } +$count = count( $del ); +echo( "...found {$count}.\n" ); -$maintClass = "RemoveUnusedAccounts"; -require_once( DO_MAINTENANCE ); +# If required, go back and delete each marked account +if( $count > 0 && isset( $options['delete'] ) ) { + echo( "\nDeleting inactive accounts..." ); + $dbw = wfGetDB( DB_MASTER ); + $dbw->delete( 'user', array( 'user_id' => $del ), $fname ); + echo( "done.\n" ); + # Update the site_stats.ss_users field + $users = $dbw->selectField( 'user', 'COUNT(*)', array(), $fname ); + $dbw->update( 'site_stats', array( 'ss_users' => $users ), array( 'ss_row_id' => 1 ), $fname ); +} else { + if( $count > 0 ) + echo( "\nRun the script again with --delete to remove them from the database.\n" ); +} +echo( "\n" ); diff --git a/maintenance/renameDbPrefix.php b/maintenance/renameDbPrefix.php index 562f143bcc..277f3b95cb 100644 --- a/maintenance/renameDbPrefix.php +++ b/maintenance/renameDbPrefix.php @@ -6,59 +6,62 @@ * @file * @ingroup Maintenance */ - -require_once( "Maintenance.php" ); +$optionsWithArgs = array( 'old', 'new', 'help' ); -class RenameDbPrefix extends Maintenance { - public function __construct() { - parent::__construct(); - $this->addParam( "old", "Old db prefix [0 for none]", true, true ); - $this->addParam( "new", "New db prefix [0 for none]", true, true ); - } - - public function execute() { - // Allow for no old prefix - if( $this->getOption( 'old', 0 ) === '0' ) { - $old = ''; - } else { - // Use nice safe, sane, prefixes - preg_match( '/^[a-zA-Z]+_$/', $this->getOption('old'), $m ); - $old = isset( $m[0] ) ? $m[0] : false; - } - // Allow for no new prefix - if( $this->getOption( 'new', 0 ) === '0' ) { - $new = ''; - } else { - // Use nice safe, sane, prefixes - preg_match( '/^[a-zA-Z]+_$/', $this->getOption('new'), $m ); - $new = isset( $m[0] ) ? $m[0] : false; - } - - if( $old === false || $new === false ) { - $this->error( "Invalid prefix!\n", true ); - } - if( $old === $new ) { - $this->( "Same prefix. Nothing to rename!\n", true ); - } - - $this->output( "Renaming DB prefix for tables of $wgDBname from '$old' to '$new'\n" ); - $count = 0; - - $dbw = wfGetDB( DB_MASTER ); - $res = $dbw->query( "SHOW TABLES LIKE '".$dbw->escapeLike( $old )."%'" ); - foreach( $res as $row ) { - // XXX: odd syntax. MySQL outputs an oddly cased "Tables of X" - // sort of message. Best not to try $row->x stuff... - $fields = get_object_vars( $row ); - // Silly for loop over one field... - foreach( $fields as $resName => $table ) { - // $old should be regexp safe ([a-zA-Z_]) - $newTable = preg_replace( '/^'.$old.'/', $new, $table ); - $this->output( "Renaming table $table to $newTable\n" ); - $dbw->query( "RENAME TABLE $table TO $newTable" ); - } - $count++; - } - $this->output( "Done! [$count tables]\n" ); +require_once( 'commandLine.inc' ); + +if( @$options['help'] || !isset( $options['old'] ) || !isset( $options['new'] ) ) { + print "usage: renameDbPrefix.php [--help] [--old x] [new y]\n"; + print " --help : this help message\n"; + print " --old x : old db prefix x\n"; + print " --old 0 : EMPTY old db prefix x\n"; + print " --new y : new db prefix y\n"; + print " --new 0 : EMPTY new db prefix\n"; + wfDie(); +} + +// Allow for no old prefix +if( $options['old'] === '0' ) { + $old = ''; +} else { + // Use nice safe, sane, prefixes + preg_match( '/^[a-zA-Z]+_$/', $options['old'], $m ); + $old = isset( $m[0] ) ? $m[0] : false; +} +// Allow for no new prefix +if( $options['new'] === '0' ) { + $new = ''; +} else { + // Use nice safe, sane, prefixes + preg_match( '/^[a-zA-Z]+_$/', $options['new'], $m ); + $new = isset( $m[0] ) ? $m[0] : false; +} + +if( $old === false || $new === false ) { + print "Invalid prefix!\n"; + wfDie(); +} +if( $old === $new ) { + print "Same prefix. Nothing to rename!\n"; + wfDie(); +} + +print "Renaming DB prefix for tables of $wgDBname from '$old' to '$new'\n"; +$count = 0; + +$dbw = wfGetDB( DB_MASTER ); +$res = $dbw->query( "SHOW TABLES LIKE '".$dbw->escapeLike( $old )."%'" ); +foreach( $res as $row ) { + // XXX: odd syntax. MySQL outputs an oddly cased "Tables of X" + // sort of message. Best not to try $row->x stuff... + $fields = get_object_vars( $row ); + // Silly for loop over one field... + foreach( $fields as $resName => $table ) { + // $old should be regexp safe ([a-zA-Z_]) + $newTable = preg_replace( '/^'.$old.'/', $new, $table ); + print "Renaming table $table to $newTable\n"; + $dbw->query( "RENAME TABLE $table TO $newTable" ); } + $count++; } +print "Done! [$count tables]\n"; \ No newline at end of file diff --git a/maintenance/renderDump.php b/maintenance/renderDump.php index fe2d22b6b7..97797792a0 100644 --- a/maintenance/renderDump.php +++ b/maintenance/renderDump.php @@ -27,61 +27,42 @@ * @file * @ingroup Maintenance */ - -require_once( "Maintenance.php" ); -class DumpRenderer extends Maintenance { +$optionsWithArgs = array( 'report' ); - private $count = 0; - private $outputDirectory, $startTime; +require_once( 'commandLine.inc' ); - public function __construct() { - parent::__construct(); - $this->mDescription = "Take page text out of an XML dump file and render basic HTML out to files"; - $this->addParam( 'output-dir', 'The directory to output the HTML files to', true, true ); +class DumpRenderer { + function __construct( $dir ) { + $this->stderr = fopen( "php://stderr", "wt" ); + $this->outputDirectory = $dir; + $this->count = 0; } - public function execute() { - $this->outputDirectory = $this->getOption( 'output-dir' ); - $this->startTime = wfTime(); - - $source = new ImportStreamSource( $this->getStdin() ); - $importer = new WikiImporter( $source ); - - $importer->setRevisionCallback( - array( &$this, 'handleRevision' ) ); - - return $importer->doImport(); - } - - /** - * Callback function for each revision, turn into HTML and save - * @param $rev Revision - */ - private function handleRevision( $rev ) { + function handleRevision( $rev ) { $title = $rev->getTitle(); if (!$title) { - $this->error( "Got bogus revision with null title!" ); + fprintf( $this->stderr, "Got bogus revision with null title!" ); return; } $display = $title->getPrefixedText(); - + $this->count++; - + $sanitized = rawurlencode( $display ); $filename = sprintf( "%s/wiki-%07d-%s.html", $this->outputDirectory, $this->count, $sanitized ); - $this->output( sprintf( $this->stderr, "%s\n", $filename, $display ) ); - - // fixme (what?) + fprintf( $this->stderr, "%s\n", $filename, $display ); + + // fixme $user = new User(); $parser = new Parser(); $options = ParserOptions::newFromUser( $user ); - + $output = $parser->parse( $rev->getText(), $title, $options ); - + file_put_contents( $filename, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" " . "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" . @@ -95,7 +76,27 @@ class DumpRenderer extends Maintenance { "</body>\n" . "</html>" ); } + + function run() { + $this->startTime = wfTime(); + + $file = fopen( 'php://stdin', 'rt' ); + $source = new ImportStreamSource( $file ); + $importer = new WikiImporter( $source ); + + $importer->setRevisionCallback( + array( &$this, 'handleRevision' ) ); + + return $importer->doImport(); + } } -$maintClass = "DumpRenderer"; -require_once( DO_MAINTENANCE ); +if( isset( $options['output-dir'] ) ) { + $dir = $options['output-dir']; +} else { + wfDie( "Must use --output-dir=/some/dir\n" ); +} +$render = new DumpRenderer( $dir ); +$render->run(); + + diff --git a/maintenance/runJobs.php b/maintenance/runJobs.php index 202c1e7f4f..1340a85770 100644 --- a/maintenance/runJobs.php +++ b/maintenance/runJobs.php @@ -10,77 +10,71 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +$optionsWithArgs = array( 'maxjobs', 'type', 'procs' ); +$wgUseNormalUser = true; +require_once( 'commandLine.inc' ); -class RunJobs extends Maintenance { - public function __construct() { - global $wgUseNormalUser; - parent::__construct(); - $this->mDescription = "Run pending jobs"; - $this->addParam( 'maxjobs', 'Maximum number of jobs to run', false, true ); - $this->addParam( 'type', 'Type of job to run', false, true ); - $this->addParam( 'procs', 'Number of processes to use', false, true ); - $wgUseNormalUser = true; +if ( isset( $options['procs'] ) ) { + $procs = intval( $options['procs'] ); + if ( $procs < 1 || $procs > 1000 ) { + echo "Invalid argument to --procs\n"; + exit( 1 ); } + $fc = new ForkController( $procs ); + if ( $fc->start( $procs ) != 'child' ) { + exit( 0 ); + } +} - public function execute() { - global $wgTitle; - if ( $this->hasOption( 'procs' ) ) { - $procs = intval( $this->getOption('procs') ); - if ( $procs < 1 || $procs > 1000 ) { - $this->error( "Invalid argument to --procs\n", true ); - } - $fc = new ForkController( $procs ); - if ( $fc->start( $procs ) != 'child' ) { - exit( 0 ); - } - } - $maxJobs = $this->getOption( 'maxjobs', 10000 ); - $type = $this->getOption( 'type', false ); - $wgTitle = Title::newFromText( 'RunJobs.php' ); - $dbw = wfGetDB( DB_MASTER ); - $n = 0; - $conds = ''; - if ($type !== false) - $conds = "job_cmd = " . $dbw->addQuotes($type); +if ( isset( $options['maxjobs'] ) ) { + $maxJobs = $options['maxjobs']; +} else { + $maxJobs = 10000; +} + +$type = false; +if ( isset( $options['type'] ) ) + $type = $options['type']; + +$wgTitle = Title::newFromText( 'RunJobs.php' ); + +$dbw = wfGetDB( DB_MASTER ); +$n = 0; +$conds = ''; +if ($type !== false) + $conds = "job_cmd = " . $dbw->addQuotes($type); - while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) { - $offset=0; - for (;;) { - $job = ($type == false) ? - Job::pop($offset) - : Job::pop_type($type); - - if ($job == false) - break; - - wfWaitForSlaves( 5 ); - $t = microtime( true ); - $offset=$job->id; - $status = $job->run(); - $t = microtime( true ) - $t; - $timeMs = intval( $t * 1000 ); - if ( !$status ) { - $this->runJobsLog( $job->toString() . " t=$timeMs error={$job->error}" ); - } else { - $this->runJobsLog( $job->toString() . " t=$timeMs good" ); - } - if ( $maxJobs && ++$n > $maxJobs ) { - break 2; - } - } +while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) { + $offset=0; + for (;;) { + $job = ($type == false) ? + Job::pop($offset) + : Job::pop_type($type); + + if ($job == false) + break; + + wfWaitForSlaves( 5 ); + $t = microtime( true ); + $offset=$job->id; + $status = $job->run(); + $t = microtime( true ) - $t; + $timeMs = intval( $t * 1000 ); + if ( !$status ) { + runJobsLog( $job->toString() . " t=$timeMs error={$job->error}" ); + } else { + runJobsLog( $job->toString() . " t=$timeMs good" ); + } + if ( $maxJobs && ++$n > $maxJobs ) { + break 2; } } +} - /** - * Log the job message - * @param $msg String The message to log - */ - private function runJobsLog( $msg ) { - $this->output( wfTimestamp( TS_DB ) . " $msg\n" ); - wfDebugLog( 'runJobs', $msg ); - } + +function runJobsLog( $msg ) { + print wfTimestamp( TS_DB ) . " $msg\n"; + wfDebugLog( 'runJobs', $msg ); } -$maintClass = "RunJobs"; -require_once( DO_MAINTENANCE ); + diff --git a/maintenance/showJobs.php b/maintenance/showJobs.php index 49b825f791..6e38c854c3 100644 --- a/maintenance/showJobs.php +++ b/maintenance/showJobs.php @@ -9,19 +9,10 @@ * @author Tim Starling * @author Ashar Voultoiz */ - -require_once( "Maintenance.php" ); +require_once( 'commandLine.inc' ); + +$dbw = wfGetDB( DB_MASTER ); +$count = $dbw->selectField( 'job', 'count(*)', '', 'runJobs.php' ); +print $count."\n"; -class ShowJobs extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Show number of jobs waiting in master database"; - } - public function execute() { - $dbw = wfGetDB( DB_MASTER ); - $this->output( $dbw->selectField( 'job', 'count(*)', '', 'runJobs.php' ) . "\n" ); - } -} -$maintClass = "ShowJobs"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/showStats.php b/maintenance/showStats.php index fc0a1410c9..ef13f6541a 100644 --- a/maintenance/showStats.php +++ b/maintenance/showStats.php @@ -14,41 +14,35 @@ * @license GNU General Public License 2.0 or later */ -require_once( "Maintenance.php" ); +require_once( 'commandLine.inc' ); -class ShowStats extends Maintenance { - public function __construct() { - $this->mDescription = "Show the cached statistics"; - } - public function execute() { - $fields = array( - 'ss_total_views' => 'Total views', - 'ss_total_edits' => 'Total edits', - 'ss_good_articles' => 'Number of articles', - 'ss_total_pages' => 'Total pages', - 'ss_users' => 'Number of users', - 'ss_admins' => 'Number of admins', - 'ss_images' => 'Number of images', - ); - - // Get cached stats from slave database - $dbr = wfGetDB( DB_SLAVE ); - $stats = $dbr->selectRow( 'site_stats', '*', '', __METHOD__ ); - - // Get maximum size for each column - $max_length_value = $max_length_desc = 0; - foreach( $fields as $field => $desc ) { - $max_length_value = max( $max_length_value, strlen( $stats->$field ) ); - $max_length_desc = max( $max_length_desc , strlen( $desc )) ; - } - - // Show them - foreach( $fields as $field => $desc ) { - $this->output( sprintf( "%-{$max_length_desc}s: %{$max_length_value}d\n", $desc, $stats->$field ) ); - } - } +# +# Configuration +# +$fields = array( + 'ss_total_views' => 'Total views', + 'ss_total_edits' => 'Total edits', + 'ss_good_articles' => 'Number of articles', + 'ss_total_pages' => 'Total pages', + 'ss_users' => 'Number of users', + 'ss_admins' => 'Number of admins', + 'ss_images' => 'Number of images', +); + +// Get cached stats from slave database +$dbr = wfGetDB( DB_SLAVE ); +$fname = 'showStats'; +$stats = $dbr->selectRow( 'site_stats', '*', '' ); + +// Get maximum size for each column +$max_length_value = $max_length_desc = 0; +foreach( $fields as $field => $desc ) { + $max_length_value = max( $max_length_value, strlen( $stats->$field ) ); + $max_length_desc = max( $max_length_desc , strlen( $desc )) ; } -$maintClass = "ShowStats"; -require_once( DO_MAINTENANCE ); +// Show them +foreach( $fields as $field => $desc ) { + printf( "%-{$max_length_desc}s: %{$max_length_value}d\n", $desc, $stats->$field ); +} diff --git a/maintenance/sql.php b/maintenance/sql.php index 1dbbe550ac..ab6546b9e0 100644 --- a/maintenance/sql.php +++ b/maintenance/sql.php @@ -7,56 +7,38 @@ * @ingroup Database Maintenance */ -require_once( "Maintenance.php" ); +require_once( dirname(__FILE__) . '/' . 'commandLine.inc' ); -class MwSql extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Send SQL queries to a MediaWiki database"; - } +if ( isset( $options['help'] ) ) { + echo "Send SQL queries to a MediaWiki database.\nUsage: php sql.php [<file>]\n"; + exit( 1 ); +} - public function execute() { - if ( $this->hasArg() ) { - $fileName = $this->getArg(); - $file = fopen( $fileName, 'r' ); - $promptCallback = false; - } else { - $file = $this->getStdin(); - $promptObject = new SqlPromptPrinter( "> " ); - $promptCallback = $promptObject->cb(); - } - - if ( !$file ) - $this->error( "Unable to open input file\n", true ); +if ( isset( $args[0] ) ) { + $fileName = $args[0]; + $file = fopen( $fileName, 'r' ); + $promptCallback = false; +} else { + $file = STDIN; + $promptObject = new SqlPromptPrinter( "> " ); + $promptCallback = $promptObject->cb(); +} - $dbw = wfGetDB( DB_MASTER ); - $error = $dbw->sourceStream( $file, $promptCallback, array( $this, 'sqlPrintResult' ) ); - if ( $error !== true ) { - $this->error( $error, true ); - } else { - exit( 0 ); - } - } +if ( !$file ) { + echo "Unable to open input file\n"; + exit( 1 ); +} - /** - * Print the results, callback for $db->sourceStream() - * @param $res The results object - * @param $db Database object - */ - public function sqlPrintResult( $res, $db ) { - if ( !$res ) { - // Do nothing - } elseif ( is_object( $res ) && $res->numRows() ) { - while ( $row = $res->fetchObject() ) { - $this->output( print_r( $row, true ) ); - } - } else { - $affected = $db->affectedRows(); - $this->output( "Query OK, $affected row(s) affected\n" ); - } - } +$dbw =& wfGetDB( DB_MASTER ); +$error = $dbw->sourceStream( $file, $promptCallback, 'sqlPrintResult' ); +if ( $error !== true ) { + echo $error; + exit( 1 ); +} else { + exit( 0 ); } +//----------------------------------------------------------------------------- class SqlPromptPrinter { function __construct( $prompt ) { $this->prompt = $prompt; @@ -71,5 +53,17 @@ class SqlPromptPrinter { } } -$maintClass = "MwSql"; -require_once( DO_MAINTENANCE ); +function sqlPrintResult( $res, $db ) { + if ( !$res ) { + // Do nothing + } elseif ( is_object( $res ) && $res->numRows() ) { + while ( $row = $res->fetchObject() ) { + print_r( $row ); + } + } else { + $affected = $db->affectedRows(); + echo "Query OK, $affected row(s) affected\n"; + } +} + + diff --git a/maintenance/stats.php b/maintenance/stats.php index 0e530333c3..00f79ded81 100644 --- a/maintenance/stats.php +++ b/maintenance/stats.php @@ -1,73 +1,58 @@ <?php /** * Show statistics from memcached + * + * @file * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +require_once('commandLine.inc'); -class MemcachedStats extends Maintenance { - - public function __construct() { - $this->mDescription = "Show statistics from memcached"; - } - - public function execute() { - global $wgMemc; - - // Can't do stats if - if( get_class( $wgMemc ) == 'FakeMemCachedClient' ) { - $this->error( "You are running FakeMemCachedClient, I can not provide any statistics.\n", true ); - } - $session = intval($wgMemc->get(wfMemcKey('stats','request_with_session'))); - $noSession = intval($wgMemc->get(wfMemcKey('stats','request_without_session'))); - $total = $session + $noSession; - if ( $total == 0 ) { - $this->error( "You either have no stats or memcached isn't running. Aborting.\n", true ); - } - $this->output( "Requests\n" ); - $this->output( sprintf( "with session: %-10d %6.2f%%\n", $session, $session/$total*100 ); - $this->output( sprintf( "without session: %-10d %6.2f%%\n", $noSession, $noSession/$total*100 ); - $this->output( sprintf( "total: %-10d %6.2f%%\n", $total, 100 ); - - - $this->output( "\nParser cache\n" ); - $hits = intval($wgMemc->get(wfMemcKey('stats','pcache_hit'))); - $invalid = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_invalid'))); - $expired = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_expired'))); - $absent = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_absent'))); - $stub = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_stub'))); - $total = $hits + $invalid + $expired + $absent + $stub; - $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ) ); - $this->output( sprintf( "invalid: %-10d %6.2f%%\n", $invalid, $invalid/$total*100 ) ); - $this->output( sprintf( "expired: %-10d %6.2f%%\n", $expired, $expired/$total*100 ) ); - $this->output( sprintf( "absent: %-10d %6.2f%%\n", $absent, $absent/$total*100 ) ); - $this->output( sprintf( "stub threshold: %-10d %6.2f%%\n", $stub, $stub/$total*100 ) ); - $this->output( sprintf( "total: %-10d %6.2f%%\n", $total, 100 ) ); - - $hits = intval($wgMemc->get(wfMemcKey('stats','image_cache_hit'))); - $misses = intval($wgMemc->get(wfMemcKey('stats','image_cache_miss'))); - $updates = intval($wgMemc->get(wfMemcKey('stats','image_cache_update'))); - $total = $hits + $misses; - $this->output("\nImage cache\n"); - $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ) ); - $this->output( sprintf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 ) ); - $this->output( sprintf( "updates: %-10d\n", $updates ) ); - - $hits = intval($wgMemc->get(wfMemcKey('stats','diff_cache_hit'))); - $misses = intval($wgMemc->get(wfMemcKey('stats','diff_cache_miss'))); - $uncacheable = intval($wgMemc->get(wfMemcKey('stats','diff_uncacheable'))); - $total = $hits + $misses + $uncacheable; - $this->output("\nDiff cache\n"); - $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ); - $this->output( sprintf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 ); - $this->output( sprintf( "uncacheable: %-10d %6.2f%%\n", $uncacheable, $uncacheable/$total*100 ); - } +if( get_class( $wgMemc ) == 'FakeMemCachedClient' ) { + die("You are running FakeMemCachedClient, I can not provide any statistics.\n"); } - -$maintClass = "MemcachedStats"; -require_once( DO_MAINTENANCE ); - - +$session = intval($wgMemc->get(wfMemcKey('stats','request_with_session'))); +$noSession = intval($wgMemc->get(wfMemcKey('stats','request_without_session'))); +$total = $session + $noSession; +if ( $total == 0 ) { + die("You either have no stats or memcached isn't running. Aborting.\n"); +} +print "Requests\n"; +printf( "with session: %-10d %6.2f%%\n", $session, $session/$total*100 ); +printf( "without session: %-10d %6.2f%%\n", $noSession, $noSession/$total*100 ); +printf( "total: %-10d %6.2f%%\n", $total, 100 ); + + +print "\nParser cache\n"; +$hits = intval($wgMemc->get(wfMemcKey('stats','pcache_hit'))); +$invalid = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_invalid'))); +$expired = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_expired'))); +$absent = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_absent'))); +$stub = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_stub'))); +$total = $hits + $invalid + $expired + $absent + $stub; +printf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ); +printf( "invalid: %-10d %6.2f%%\n", $invalid, $invalid/$total*100 ); +printf( "expired: %-10d %6.2f%%\n", $expired, $expired/$total*100 ); +printf( "absent: %-10d %6.2f%%\n", $absent, $absent/$total*100 ); +printf( "stub threshold: %-10d %6.2f%%\n", $stub, $stub/$total*100 ); +printf( "total: %-10d %6.2f%%\n", $total, 100 ); + +$hits = intval($wgMemc->get(wfMemcKey('stats','image_cache_hit'))); +$misses = intval($wgMemc->get(wfMemcKey('stats','image_cache_miss'))); +$updates = intval($wgMemc->get(wfMemcKey('stats','image_cache_update'))); +$total = $hits + $misses; +print("\nImage cache\n"); +printf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ); +printf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 ); +printf( "updates: %-10d\n", $updates ); + +$hits = intval($wgMemc->get(wfMemcKey('stats','diff_cache_hit'))); +$misses = intval($wgMemc->get(wfMemcKey('stats','diff_cache_miss'))); +$uncacheable = intval($wgMemc->get(wfMemcKey('stats','diff_uncacheable'))); +$total = $hits + $misses + $uncacheable; +print("\nDiff cache\n"); +printf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ); +printf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 ); +printf( "uncacheable: %-10d %6.2f%%\n", $uncacheable, $uncacheable/$total*100 ); diff --git a/maintenance/undelete.php b/maintenance/undelete.php index 9328f12db6..b7b7df979e 100644 --- a/maintenance/undelete.php +++ b/maintenance/undelete.php @@ -6,35 +6,34 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); +$usage = <<<EOT +Undelete a page +Usage: php undelete.php [-u <user>] [-r <reason>] <pagename> -class Undelete extends Maintenance { - public function __construct() { - parent::__construct(); - $this->mDescription = "Undelete a page"; - $this->addParam( 'u', 'The user to perform the undeletion', false, true ); - $this->addParam( 'r', 'The reason to undelete', false, true ); - $this->addArgs( array( 'pagename' ) ); - } +EOT; - public function execute() { - global $wgUser; +$optionsWithArgs = array( 'u', 'r' ); +require_once( 'commandLine.inc' ); - $user = $this->getOption( 'u', 'Command line script' ); - $reason = $this->getOption( 'r', '' ); - $pageName = $this->getArg(); +$user = 'Command line script'; +$reason = ''; - $title = Title::newFromText( $pageName ); - if ( !$title ) { - $this->error( "Invalid title", true ); - } - $wgUser = User::newFromName( $user ); - $archive = new PageArchive( $title ); - $this->output( "Undeleting " . $title->getPrefixedDBkey() . '...' ); - $archive->undelete( array(), $reason ); - $this->output( "done\n" ); - } +if ( isset( $options['u'] ) ) { + $user = $options['u']; } +if ( isset( $options['r'] ) ) { + $reason = $options['r']; +} +$pageName = @$args[0]; +$title = Title::newFromText( $pageName ); +if ( !$title ) { + echo $usage; + exit( 1 ); +} +$wgUser = User::newFromName( $user ); +$archive = new PageArchive( $title ); +echo "Undeleting " . $title->getPrefixedDBkey() . '...'; +$archive->undelete( array(), $reason ); +echo "done\n"; + -$maintClass = "Undelete"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/updateArticleCount.php b/maintenance/updateArticleCount.php index 3b704ebf98..15033ad309 100644 --- a/maintenance/updateArticleCount.php +++ b/maintenance/updateArticleCount.php @@ -3,84 +3,38 @@ * Maintenance script to provide a better count of the number of articles * and update the site statistics table, if desired * + * @file * @ingroup Maintenance * @author Rob Church <robchur@gmail.com> */ -require_once( "Maintenance.php" ); +$options = array( 'update', 'help' ); +require_once( 'commandLine.inc' ); +require_once( 'updateArticleCount.inc' ); +echo( "Update Article Count\n\n" ); -class UpdateArticleCount extends Maintenance { - - // Content namespaces - private $namespaces; - - public function __construct() { - global $wgContentNamespaces; - parent::__construct(); - $this->mDescription = "Count of the number of articles and update the site statistics table"; - $this->addParam( 'update', 'Update the site_stats table with the new count' ); - $this->namespaces = $wgContentNamespaces; - } - - public function execute() { - $this->output( "Counting articles..." ); - $result = $this->count(); - - if( $result !== false ) { - $this->output( "found {$result}.\n" ); - if( isset( $options['update'] ) && $options['update'] ) { - $this->output( "Updating site statistics table... " ); - $dbw = wfGetDB( DB_MASTER ); - $dbw->update( 'site_stats', array( 'ss_good_articles' => $result ), array( 'ss_row_id' => 1 ), __METHOD__ ); - $this->output( "done.\n" ); - } else { - $this->output( "To update the site statistics table, run the script with the --update option.\n" ); - } - } else { - $this->output( "failed.\n" ); - } - } - - /** - * Produce a comma-delimited set of namespaces - * Includes paranoia - * - * @return string - */ - private function makeNsSet() { - foreach( $this->namespaces as $namespace ) - $namespaces[] = intval( $namespace ); - return implode( ', ', $namespaces ); - } - - /** - * Produce SQL for the query - * - * @param $dbr Database handle - * @return string - */ - private function makeSql( $dbr ) { - list( $page, $pagelinks ) = $dbr->tableNamesN( 'page', 'pagelinks' ); - $nsset = $this->makeNsSet(); - return "SELECT COUNT(DISTINCT page_namespace, page_title) AS pagecount " . - "FROM $page, $pagelinks " . - "WHERE pl_from=page_id and page_namespace IN ( $nsset ) " . - "AND page_is_redirect = 0 AND page_len > 0"; - } +if( isset( $options['help'] ) && $options['help'] ) { + echo( "Usage: php updateArticleCount.php [--update]\n\n" ); + echo( "--update : Update site statistics table\n" ); + exit( 0 ); +} - /** - * Count the number of valid content pages in the wiki - * - * @return mixed Integer, or false if there's a problem - */ - private function count() { - $dbr = wfGetDB( DB_SLAVE ); - $res = $dbr->query( $this->makeSql( $dbr ), __METHOD__ ); - $row = $dbr->fetchObject( $res ); - $dbr->freeResult( $res ); - return $row->pagecount; +echo( "Counting articles..." ); +$counter = new ArticleCounter(); +$result = $counter->count(); + +if( $result !== false ) { + echo( "found {$result}.\n" ); + if( isset( $options['update'] ) && $options['update'] ) { + echo( "Updating site statistics table... " ); + $dbw = wfGetDB( DB_MASTER ); + $dbw->update( 'site_stats', array( 'ss_good_articles' => $result ), array( 'ss_row_id' => 1 ), __METHOD__ ); + echo( "done.\n" ); + } else { + echo( "To update the site statistics table, run the script with the --update option.\n" ); } +} else { + echo( "failed.\n" ); } +echo( "\n" ); -$maintClass = "UpdateArticleCount"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/updateSearchIndex.php b/maintenance/updateSearchIndex.php index ee1bb2f7ea..5fa24ad691 100644 --- a/maintenance/updateSearchIndex.php +++ b/maintenance/updateSearchIndex.php @@ -5,159 +5,58 @@ * Usage: php updateSearchIndex.php [-s START] [-e END] [-p POSFILE] [-l LOCKTIME] [-q] * Where START is the starting timestamp * END is the ending timestamp - * POSFILE is a file to load timestamps from and save them to, searchUpdate.WIKI_ID.pos by default - * LOCKTIME is how long the searchindex and revision tables will be locked for + * POSFILE is a file to load timestamps from and save them to, searchUpdate.pos by default + * LOCKTIME is how long the searchindex and cur tables will be locked for * -q means quiet * + * @file * @ingroup Maintenance */ - -require_once( "Maintenance.php" ); -class UpdateSearchIndex extends Maintenance { +/** */ +$optionsWithArgs = array( 's', 'e', 'p' ); - public function __construct() { - parent::__construct(); - $this->mDescription = "Script for periodic off-peak updating of the search index"; - $this->addParam( 's', 'starting timestamp', false, true ); - $this->addParam( 'e', 'Ending timestamp', false, true ); - $this->addParam( 'p', 'File for saving/loading timestamps, searchUpdate.WIKI_ID.pos by default', false, true ); - $this->addParam( 'l', 'How long the searchindex and revision tables will be locked for', false, true ); - } - - public function execute() { - $posFile = $this->getOption( 'p', 'searchUpdate.' . wfWikiId() . '.pos' ); - $end = $this->getOption( 'e', wfTimestampNow() ); - if ( $this->hasOption( 's' ) ) { - $start = $this->getOption('s'); - } elseif( is_readable( 'searchUpdate.pos' ) ) { - # B/c to the old position file name which was hardcoded - # We can safely delete the file when we're done though. - $start = file_get_contents( 'searchUpdate.pos' ); - unlink( 'searchUpdate.pos' ); - } else { - $start = @file_get_contents( $posFile ); - if ( !$start ) { - $start = wfTimestamp( TS_MW, time() - 86400 ); - } - } - $lockTime = $this->getOption( 'l', 20 ); - - $this->updateSearchIndex( $start, $end, $lockTime ); - $file = fopen( $posFile, 'w' ); - fwrite( $file, $end ); - fclose( $file ); - } - - private function updateSearchIndex( $start, $end, $maxLockTime ) { - global $wgDisableSearchUpdate; - - $wgDisableSearchUpdate = false; +require_once( 'commandLine.inc' ); +require_once( 'updateSearchIndex.inc' ); - $dbw = wfGetDB( DB_MASTER ); - $recentchanges = $dbw->tableName( 'recentchanges' ); - - $this->output( "Updating searchindex between $start and $end\n" ); - - # Select entries from recentchanges which are on top and between the specified times - $start = $dbw->strencode( $start ); - $end = $dbw->strencode( $end ); +if ( isset( $options['p'] ) ) { + $posFile = $options['p']; +} else { + $posFile = 'searchUpdate.' . wfWikiId() . '.pos'; +} - $page = $dbw->tableName( 'page' ); - $sql = "SELECT rc_cur_id,rc_type,rc_moved_to_ns,rc_moved_to_title FROM $recentchanges - JOIN $page ON rc_cur_id=page_id AND rc_this_oldid=page_latest - WHERE rc_timestamp BETWEEN '$start' AND '$end' - "; - $res = $dbw->query( $sql, __METHOD__ ); +if ( isset( $options['e'] ) ) { + $end = $options['e']; +} else { + $end = wfTimestampNow(); +} +if ( isset( $options['s'] ) ) { + $start = $options['s']; +} elseif( is_readable( 'searchUpdate.pos' ) ) { + # B/c to the old position file name which was hardcoded + # We can safely delete the file when we're done though. + $start = file_get_contents( 'searchUpdate.pos' ); + unlink( 'searchUpdate.pos' ); +} else { + $start = @file_get_contents( $posFile ); + if ( !$start ) { + $start = wfTimestamp( TS_MW, time() - 86400 ); + } +} - # Lock searchindex - if ( $maxLockTime ) { - $this->output( " --- Waiting for lock ---" ); - $this->lockSearchindex( $dbw ); - $lockTime = time(); - $this->output( "\n" ); - } +if ( isset( $options['l'] ) ) { + $lockTime = $options['l']; +} else { + $lockTime = 20; +} - # Loop through the results and do a search update - while ( $row = $dbw->fetchObject( $res ) ) { - # Allow reads to be processed - if ( $maxLockTime && time() > $lockTime + $maxLockTime ) { - $this->output( " --- Relocking ---" ); - $this->relockSearchindex( $dbw ); - $lockTime = time(); - $this->output( "\n" ); - } - if ( $row->rc_type == RC_LOG ) { - continue; - } elseif ( $row->rc_type == RC_MOVE || $row->rc_type == RC_MOVE_OVER_REDIRECT ) { - # Rename searchindex entry - $titleObj = Title::makeTitle( $row->rc_moved_to_ns, $row->rc_moved_to_title ); - $title = $titleObj->getPrefixedDBkey(); - $this->output( "$title..." ); - $u = new SearchUpdate( $row->rc_cur_id, $title, false ); - $this->output( "\n" ); - } else { - // Get current revision - $rev = Revision::loadFromPageId( $dbw, $row->rc_cur_id ); - if( $rev ) { - $titleObj = $rev->getTitle(); - $title = $titleObj->getPrefixedDBkey(); - $this->output( $title ); - # Update searchindex - $u = new SearchUpdate( $row->rc_cur_id, $titleObj->getText(), $rev->getText() ); - $u->doUpdate(); - $this->output( "\n" ); - } - } - } +$quiet = (bool)(@$options['q']); - # Unlock searchindex - if ( $maxLockTime ) { - $this->output( " --- Unlocking --" ); - $this->unlockSearchindex( $dbw ); - $this->output( "\n" ); - } - $this->output( "Done\n" ); - } +updateSearchIndex( $start, $end, $lockTime, $quiet ); - /** - * Lock the search index - * @param &$db Database object - */ - private function lockSearchindex( &$db ) { - $write = array( 'searchindex' ); - $read = array( 'page', 'revision', 'text', 'interwiki' ); - $items = array(); - - foreach( $write as $table ) { - $items[] = $db->tableName( $table ) . ' LOW_PRIORITY WRITE'; - } - foreach( $read as $table ) { - $items[] = $db->tableName( $table ) . ' READ'; - } - $sql = "LOCK TABLES " . implode( ',', $items ); - $db->query( $sql, 'updateSearchIndex.php ' . __METHOD__ ); - } +$file = fopen( $posFile, 'w' ); +fwrite( $file, $end ); +fclose( $file ); - /** - * Unlock the tables - * @param &$db Database object - */ - private function unlockSearchindex( &$db ) { - $db->query( "UNLOCK TABLES", 'updateSearchIndex.php ' . __METHOD__ ); - } - - /** - * Unlock and lock again - * Since the lock is low-priority, queued reads will be able to complete - * @param &$db Database object - */ - private function relockSearchindex( &$db ) { - $this->unlockSearchindex( $db ); - $this->lockSearchindex( $db ); - } -} -$maintClass = "UpdateSearchIndex"; -require_once( DO_MAINTENANCE ); diff --git a/maintenance/updateSpecialPages.php b/maintenance/updateSpecialPages.php index bbe4727518..3eaa62056b 100644 --- a/maintenance/updateSpecialPages.php +++ b/maintenance/updateSpecialPages.php @@ -6,114 +6,114 @@ * @file * @ingroup Maintenance */ - -require_once( "Maintenance.php" ); +$options = array('only','help'); -class UpdateSpecialPages extends Maintenance { - public function __construct() { - parent::__construct(); - $this->addParam( 'list', 'List special page names' ); - $this->addParam( 'only', 'Only update "page". Ex: --only=BrokenRedirects', false, true ); - $this->addParam( 'override', 'Also update pages that have updates disabled' ); +require_once( 'commandLine.inc' ); + +require_once( "$IP/includes/SpecialPage.php" ); +require_once( "$IP/includes/QueryPage.php" ); + +if(@$options['help']) { + print "usage:updateSpecialPages.php [--help] [--only=page]\n"; + print " --help : this help message\n"; + print " --list : list special pages names\n"; + print " --only=page : only update 'page'. Ex: --only=BrokenRedirects\n"; + print " --override : update even pages which have had updates disabled\n"; + wfDie(); +} + +$wgOut->disable(); +$dbw = wfGetDB( DB_MASTER ); + +foreach( $wgSpecialPageCacheUpdates as $special => $call ) { + if( !is_callable($call) ) { + print "Uncallable function $call!\n"; + continue; + } + $t1 = explode( ' ', microtime() ); + call_user_func( $call, $dbw ); + $t2 = explode( ' ', microtime() ); + printf( '%-30s ', $special ); + $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); + $hours = intval( $elapsed / 3600 ); + $minutes = intval( $elapsed % 3600 / 60 ); + $seconds = $elapsed - $hours * 3600 - $minutes * 60; + if ( $hours ) { + print $hours . 'h '; } + if ( $minutes ) { + print $minutes . 'm '; + } + printf( "completed in %.2fs\n", $seconds ); + # Wait for the slave to catch up + wfWaitForSlaves( 5 ); +} - public function execute() { - global $wgOut; - $wgOut->disable(); - $dbw = wfGetDB( DB_MASTER ); +foreach( $wgQueryPages as $page ) { + @list( $class, $special, $limit ) = $page; - foreach( $wgSpecialPageCacheUpdates as $special => $call ) { - if( !is_callable($call) ) { - $this->error( "Uncallable function $call!\n" ); - continue; - } + # --list : just show the name of pages + if( @$options['list'] ) { + print "$special\n"; + continue; + } + + if ( !isset( $options['override'] ) && $wgDisableQueryPageUpdate && in_array( $special, $wgDisableQueryPageUpdate ) ) { + printf("%-30s disabled\n", $special); + continue; + } + + $specialObj = SpecialPage::getPage( $special ); + if ( !$specialObj ) { + print "No such special page: $special\n"; + exit; + } + if ( !class_exists( $class ) ) { + $file = $specialObj->getFile(); + require_once( $file ); + } + $queryPage = new $class; + + if( !isset($options['only']) or $options['only'] == $queryPage->getName() ) { + printf( '%-30s ', $special ); + if ( $queryPage->isExpensive() ) { $t1 = explode( ' ', microtime() ); - call_user_func( $call, $dbw ); + # Do the query + $num = $queryPage->recache( $limit === null ? $wgQueryCacheLimit : $limit ); $t2 = explode( ' ', microtime() ); - $this->output( sprintf( '%-30s ', $special ) ); - $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); - $hours = intval( $elapsed / 3600 ); - $minutes = intval( $elapsed % 3600 / 60 ); - $seconds = $elapsed - $hours * 3600 - $minutes * 60; - if ( $hours ) { - $this->output( $hours . 'h ' ); - } - if ( $minutes ) { - $this->output( $minutes . 'm ' ); - } - $this->output( sprintf( "completed in %.2fs\n", $seconds ) ); - # Wait for the slave to catch up - wfWaitForSlaves( 5 ); - } - - foreach( $wgQueryPages as $page ) { - @list( $class, $special, $limit ) = $page; - - # --list : just show the name of pages - if( $this->hasOption('list') ) { - $this->output( "$special\n" ); - continue; - } - - if ( $this->hasOption('override') && $wgDisableQueryPageUpdate && in_array( $special, $wgDisableQueryPageUpdate ) ) { - $this->output( sprintf( "%-30s disabled\n", $special ) ); - continue; - } - - $specialObj = SpecialPage::getPage( $special ); - if ( !$specialObj ) { - $this->output( "No such special page: $special\n" ); - exit; - } - if ( !class_exists( $class ) ) { - $file = $specialObj->getFile(); - require_once( $file ); - } - $queryPage = new $class; - - if( !$this->hasOption('only') || $this->getOption('only') == $queryPage->getName() ) { - $this->output( sprintf( '%-30s ', $special ) ); - if ( $queryPage->isExpensive() ) { - $t1 = explode( ' ', microtime() ); - # Do the query - $num = $queryPage->recache( $limit === null ? $wgQueryCacheLimit : $limit ); - $t2 = explode( ' ', microtime() ); - if ( $num === false ) { - $this->output( "FAILED: database error\n" ); - } else { - $this->output( "got $num rows in " ); - - $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); - $hours = intval( $elapsed / 3600 ); - $minutes = intval( $elapsed % 3600 / 60 ); - $seconds = $elapsed - $hours * 3600 - $minutes * 60; - if ( $hours ) { - $this->output( $hours . 'h ' ); - } - if ( $minutes ) { - $this->output( $minutes . 'm ' ); - } - $this->output( sprintf( "%.2fs\n", $seconds ) ); - } - # Reopen any connections that have closed - if ( !wfGetLB()->pingAll()) { - $this->output( "\n" ); - do { - $this->error( "Connection failed, reconnecting in 10 seconds...\n" ); - sleep(10); - } while ( !wfGetLB()->pingAll() ); - $this->output( "Reconnected\n\n" ); - } else { - # Commit the results - $dbw->immediateCommit(); + if ( $num === false ) { + print "FAILED: database error\n"; + } else { + print "got $num rows in "; + + $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); + $hours = intval( $elapsed / 3600 ); + $minutes = intval( $elapsed % 3600 / 60 ); + $seconds = $elapsed - $hours * 3600 - $minutes * 60; + if ( $hours ) { + print $hours . 'h '; } - # Wait for the slave to catch up - wfWaitForSlaves( 5 ); - } else { - $this->output( "cheap, skipped\n" ); + if ( $minutes ) { + print $minutes . 'm '; } - } + printf( "%.2fs\n", $seconds ); + } + # Reopen any connections that have closed + if ( !wfGetLB()->pingAll()) { + print "\n"; + do { + print "Connection failed, reconnecting in 10 seconds...\n"; + sleep(10); + } while ( !wfGetLB()->pingAll() ); + print "Reconnected\n\n"; + } else { + # Commit the results + $dbw->immediateCommit(); + } + # Wait for the slave to catch up + wfWaitForSlaves( 5 ); + } else { + print "cheap, skipped\n"; } } } - diff --git a/maintenance/updaters.inc b/maintenance/updaters.inc index 5d3d22ec69..4b77af4723 100644 --- a/maintenance/updaters.inc +++ b/maintenance/updaters.inc @@ -1038,7 +1038,10 @@ function do_stats_init() { wfOut( "ok.\n" ); return; } - SiteStats::init( false ); + + global $IP; + require_once "$IP/maintenance/initStats.inc"; + wfInitStats(); } function do_active_users_init() { diff --git a/maintenance/waitForSlave.php b/maintenance/waitForSlave.php index edeede88e2..309d0e7d36 100644 --- a/maintenance/waitForSlave.php +++ b/maintenance/waitForSlave.php @@ -5,16 +5,11 @@ * @ingroup Maintenance */ -require_once( "Maintenance.php" ); - -class WaitForSlave extends Maintenance { - public function __construct() { - $this->addArgs( array( 'maxlag' ) ); - } - public function execute() { - wfWaitForSlaves( $this->getArg( 0, 10 ) ); - } +require_once( "commandLine.inc" ); +if ( isset( $args[0] ) ) { + wfWaitForSlaves($args[0]); +} else { + wfWaitForSlaves(10); } -$maintClass = "WaitForSlave"; -require_once( DO_MAINTENANCE ); + diff --git a/profileinfo.php b/profileinfo.php index afc05eb5c0..fcce6d71c6 100644 --- a/profileinfo.php +++ b/profileinfo.php @@ -4,6 +4,7 @@ ini_set( 'zlib.output_compression', 'off' ); $wgEnableProfileInfo = $wgProfileToDatabase = false; require_once( './includes/WebStart.php' ); +@include_once( './AdminSettings.php' ); ?> <!-- diff --git a/t/Search.inc b/t/Search.inc index a76acfd08b..252293065a 100644 --- a/t/Search.inc +++ b/t/Search.inc @@ -7,10 +7,11 @@ require 't/Test.php'; require 'includes/Defines.php'; require 'includes/ProfilerStub.php'; require 'LocalSettings.php'; +require 'AdminSettings.php'; require 'includes/Setup.php'; function buildTestDatabase( $tables ) { - global $wgDBprefix, $wgDBserver, $wgDBname, $wgDBtype; + global $wgDBprefix, $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname, $wgDBtype; $oldPrefix = $wgDBprefix; $wgDBprefix = 'parsertest';