X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=maintenance%2FMaintenance.php;h=107e66ab96961861ca1743ec5fa45db7b7e139e7;hb=e07735331b193b040adc53f0dd898ad1c77ffe99;hp=4cc49d68bb6ef22b1bacaf977f186e524c6594c4;hpb=6647e60bff12a1b50959a675d01886751f23b0f1;p=lhc%2Fweb%2Fwiklou.git diff --git a/maintenance/Maintenance.php b/maintenance/Maintenance.php index 4cc49d68bb..107e66ab96 100644 --- a/maintenance/Maintenance.php +++ b/maintenance/Maintenance.php @@ -1,6 +1,7 @@ mParams[ $name ] = array( 'desc' => $description, 'require' => $required, 'withArg' => $withArg ); + $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 ] ); + return isset( $this->mOptions[$name] ); } - + /** * Get an option, or return the default * @param $name String The name of the param @@ -127,7 +128,7 @@ abstract class Maintenance { * @return mixed */ protected function getOption( $name, $default = null ) { - if( $this->hasOption($name) ) { + if( $this->hasOption( $name ) ) { return $this->mOptions[$name]; } else { // Set it so we don't have to provide the default again @@ -135,21 +136,28 @@ abstract class Maintenance { return $this->mOptions[$name]; } } - + /** - * Add some args that are needed. Used in formatting help + * Add some args that are needed + * @param $arg String Name of the arg, like 'start' + * @param $description String Short description of the arg + * @param $required Boolean Is this required? */ - protected function addArgs( $args ) { - $this->mArgList = array_merge( $this->mArgList, $args ); + protected function addArg( $arg, $description, $required = true ) { + $this->mArgList[] = array( + 'name' => $arg, + 'desc' => $description, + 'require' => $required + ); } - + /** * 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 ] ) ; + return isset( $this->mArgs[$argId] ); } /** @@ -159,7 +167,7 @@ abstract class Maintenance { * @return mixed */ protected function getArg( $argId = 0, $default = null ) { - return $this->hasArg($argId) ? $this->mArgs[$argId] : $default; + return $this->hasArg( $argId ) ? $this->mArgs[$argId] : $default; } /** @@ -192,7 +200,7 @@ abstract class Maintenance { if( !$len ) return $f; $input = fgets( $f, $len ); - fclose ( $f ); + fclose( $f ); return rtrim( $input ); } @@ -224,23 +232,23 @@ abstract class Maintenance { } /** - * 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: + * Does the script need different DB access? By default, we give Maintenance + * scripts normal rights to the DB. Sometimes, a script needs admin rights + * access for a reason and sometimes they want no access. Subclasses should + * override and return one of the following values, as needed: * Maintenance::DB_NONE - For no DB access at all - * Maintenance::DB_STD - For normal DB access - * Maintenance::DB_ADMIN - For admin DB access, default + * Maintenance::DB_STD - For normal DB access, default + * Maintenance::DB_ADMIN - For admin DB access * @return int */ protected function getDbType() { - return Maintenance :: DB_ADMIN; + return Maintenance::DB_STD; } /** * Add the default parameters to the scripts */ - private function addDefaultParams() { + protected function addDefaultParams() { $this->addOption( 'help', "Display this help message" ); $this->addOption( 'quiet', "Whether to supress non-error output" ); $this->addOption( 'conf', "Location of LocalSettings.php, if not default", false, true ); @@ -259,17 +267,17 @@ abstract class Maintenance { } /** - * Spawn a child maintenance script. Pass all of the current arguments + * Run 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 ) { + protected function runChild( $maintClass, $classFile = null ) { // If we haven't already specified, kill setup procedures // for child scripts, we've already got a sane environment self::disableSetup(); - + // Make sure the class is loaded first if( !class_exists( $maintClass ) ) { if( $classFile ) { @@ -279,7 +287,7 @@ abstract class Maintenance { $this->error( "Cannot spawn child: $maintClass" ); } } - + $child = new $maintClass(); $child->loadParamsAndArgs( $this->mSelf, $this->mOptions, $this->mArgs ); return $child; @@ -327,21 +335,26 @@ abstract class Maintenance { # Set the memory limit ini_set( 'memory_limit', -1 ); - $wgRequestTime = microtime(true); + # Set max execution time to 0 (no limit). PHP.net says that + # "When running PHP from the command line the default setting is 0." + # But sometimes this doesn't seem to be the case. + ini_set( 'max_execution_time', 0 ); + + $wgRequestTime = microtime( true ); - # Define us as being in Mediawiki + # 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') + $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 ) ) { + if ( !isset( $wgUseNormalUser ) ) { $wgUseNormalUser = false; } @@ -413,7 +426,8 @@ abstract class Maintenance { if ( isset( $this->mParams[$option] ) && $this->mParams[$option]['withArg'] ) { $param = next( $argv ); if ( $param === false ) { - $this->error( "$arg needs a value after it", true ); + $this->error( "\nERROR: $option needs a value after it\n" ); + $this->maybeHelp( true ); } $options[$option] = $param; } else { @@ -433,7 +447,8 @@ abstract class Maintenance { if ( $this->mParams[$option]['withArg'] ) { $param = next( $argv ); if ( $param === false ) { - $this->error( "$arg needs a value after it", true ); + $this->error( "\nERROR: $option needs a value after it\n" ); + $this->maybeHelp( true ); } $options[$option] = $param; } else { @@ -454,24 +469,30 @@ abstract class Maintenance { /** * Run some validation checks on the params, etc */ - private function validateParamsAndArgs() { - # Check to make sure we've got all the required ones + protected function validateParamsAndArgs() { + $die = false; + # Check to make sure we've got all the required options foreach( $this->mParams as $opt => $info ) { - if( $info['require'] && !$this->hasOption($opt) ) { - $this->error( "Param $opt required.", true ); + if( $info['require'] && !$this->hasOption( $opt ) ) { + $this->error( "Param $opt required!" ); + $die = true; } } - - # Also make sure we've got enough arguments - if ( count( $this->mArgs ) < count( $this->mArgList ) ) { - $this->error( "Not enough arguments passed", true ); + # Check arg list too + foreach( $this->mArgList as $k => $info ) { + if( $info['require'] && !$this->hasArg($k) ) { + $this->error( "Argument <" . $info['name'] . "> required!" ); + $die = true; + } } + + if( $die ) $this->maybeHelp( true ); } - + /** * Handle the special variables that are global to all scripts */ - private function loadSpecialVars() { + protected function loadSpecialVars() { if( $this->hasOption( 'dbuser' ) ) $this->mDbUser = $this->getOption( 'dbuser' ); if( $this->hasOption( 'dbpass' ) ) @@ -486,9 +507,9 @@ abstract class Maintenance { * Maybe show the help. * @param $force boolean Whether to force the help to show, default false */ - private function maybeHelp( $force = false ) { + protected function maybeHelp( $force = false ) { ksort( $this->mParams ); - if( $this->hasOption('help') || in_array( 'help', $this->mArgs ) || $force ) { + if( $this->hasOption( 'help' ) || $force ) { $this->mQuiet = false; if( $this->mDescription ) { $this->output( "\n" . $this->mDescription . "\n" ); @@ -498,24 +519,32 @@ abstract class Maintenance { $this->output( " [--" . implode( array_keys( $this->mParams ), "|--" ) . "]" ); } if( $this->mArgList ) { - $this->output( " <" . implode( $this->mArgList, "> <" ) . ">" ); + $this->output( " <" ); + foreach( $this->mArgList as $k => $arg ) { + $this->output( $arg['name'] . ">" ); + if( $k < count( $this->mArgList ) - 1 ) + $this->output( " <" ); + } } $this->output( "\n" ); foreach( $this->mParams as $par => $info ) { $this->output( "\t$par : " . $info['desc'] . "\n" ); } + foreach( $this->mArgList as $info ) { + $this->output( "\t<" . $info['name'] . "> : " . $info['desc'] . "\n" ); + } die( 1 ); } } - + /** * Handle some last-minute setup here. */ - private function finalSetup() { + public 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(); @@ -527,12 +556,12 @@ abstract class Maintenance { if( $this->mDbUser ) $wgDBadminuser = $this->mDbUser; if( $this->mDbPass ) - $wgDBadminpass = $this->mDbPass; + $wgDBadminpassword = $this->mDbPass; if ( empty( $wgUseNormalUser ) && isset( $wgDBadminuser ) ) { $wgDBuser = $wgDBadminuser; $wgDBpassword = $wgDBadminpassword; - + if( $wgDBservers ) { foreach ( $wgDBservers as $i => $server ) { $wgDBservers[$i]['user'] = $wgDBuser; @@ -544,15 +573,15 @@ abstract class Maintenance { $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 } @@ -570,7 +599,7 @@ abstract class Maintenance { * Do setup specific to WMF */ public function loadWikimediaSettings() { - global $IP, $wgNoDBParam, $wgUseNormalUser, $wgConf; + global $IP, $wgNoDBParam, $wgUseNormalUser, $wgConf, $site, $lang; if ( empty( $wgNoDBParam ) ) { # Check if we were passed a db name @@ -580,7 +609,7 @@ abstract class Maintenance { $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 ) { @@ -598,19 +627,19 @@ abstract class Maintenance { $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 ); } @@ -637,17 +666,16 @@ abstract class Maintenance { define( 'MW_DB', $bits[0] ); define( 'MW_PREFIX', $bits[1] ); } - - if ( ! is_readable( $settingsFile ) ) { + + if ( !is_readable( $settingsFile ) ) { $this->error( "A copy of your installation's LocalSettings.php\n" . "must exist and be readable in the source directory.", 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 @@ -665,7 +693,7 @@ abstract class Maintenance { # 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 ) ) { + foreach( $res as $row ) { $cur[] = $row->rev_text_id; } $this->output( "done.\n" ); @@ -673,7 +701,7 @@ abstract class Maintenance { # 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 ) ) { + foreach( $res as $row ) { $cur[] = $row->ar_text_id; } $this->output( "done.\n" ); @@ -683,7 +711,7 @@ abstract class Maintenance { $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 ) ) { + foreach( $res as $row ) { $old[] = $row->old_id; } $this->output( "done.\n" ); @@ -703,7 +731,7 @@ abstract class Maintenance { # Done $dbw->commit(); } - + /** * Get the maintenance directory. */ @@ -721,15 +749,12 @@ abstract class Maintenance { global $wgMaintenanceScripts; return $wgMaintenanceScripts + self::getCoreScripts(); } - + /** * Return all of the core maintenance scripts - * @todo Finish porting all scripts so this doesn't blow up * @return array */ - private static function getCoreScripts() { - return array(); - /** + protected static function getCoreScripts() { if( !self::$mCoreScripts ) { self::disableSetup(); $paths = array( @@ -742,8 +767,11 @@ abstract class Maintenance { foreach( $paths as $p ) { $handle = opendir( $p ); while( ( $file = readdir( $handle ) ) !== false ) { + if( $file == 'Maintenance.php' ) + continue; $file = $p . '/' . $file; - if( is_dir( $file ) || !strpos( $file, '.php' ) ) { + if( is_dir( $file ) || !strpos( $file, '.php' ) || + ( strpos( file_get_contents( $file ), '$maintClass' ) === false ) ) { continue; } require( $file ); @@ -756,6 +784,5 @@ abstract class Maintenance { } } return self::$mCoreScripts; - */ } }