MaxSem has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/388935 )
Change subject: Rewrite userOptions.php ...................................................................... Rewrite userOptions.php * Convert to use Maintenance * Clean up * I want to use the class name UserOptions for something else so rename it. Change-Id: Ic441087702376b1ca0e70554c71cdf7ecad908af --- D maintenance/userOptions.inc M maintenance/userOptions.php 2 files changed, 176 insertions(+), 298 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/35/388935/1 diff --git a/maintenance/userOptions.inc b/maintenance/userOptions.inc deleted file mode 100644 index 8ac7f91..0000000 --- a/maintenance/userOptions.inc +++ /dev/null @@ -1,292 +0,0 @@ -<?php -/** - * Helper class for userOptions.php script. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * http://www.gnu.org/copyleft/gpl.html - * - * @file - * @ingroup Maintenance - */ - -// Options we will use -$options = [ 'list', 'nowarn', 'quiet', 'usage', 'dry' ]; -$optionsWithArgs = [ 'old', 'new' ]; - -require_once __DIR__ . '/commandLine.inc'; - -/** - * @ingroup Maintenance - */ -class UserOptions { - public $mQuick; - public $mQuiet; - public $mDry; - public $mAnOption; - public $mOldValue; - public $mNewValue; - - private $mMode, $mReady; - - /** - * Constructor. Will show usage and exit if script options are not correct - * @param array $opts - * @param array $args - */ - function __construct( $opts, $args ) { - if ( !$this->checkOpts( $opts, $args ) ) { - self::showUsageAndExit(); - } else { - $this->mReady = $this->initializeOpts( $opts, $args ); - } - } - - /** - * This is used to check options. Only needed on construction - * - * @param array $opts - * @param array $args - * - * @return bool - */ - private function checkOpts( $opts, $args ) { - // The three possible ways to run the script: - $list = isset( $opts['list'] ); - $usage = isset( $opts['usage'] ) && ( count( $args ) <= 1 ); - $change = isset( $opts['old'] ) && isset( $opts['new'] ) && ( count( $args ) <= 1 ); - - // We want only one of them - $isValid = ( ( $list + $usage + $change ) == 1 ); - - return $isValid; - } - - /** - * load script options in the object - * - * @param array $opts - * @param array $args - * - * @return bool - */ - private function initializeOpts( $opts, $args ) { - $this->mQuick = isset( $opts['nowarn'] ); - $this->mQuiet = isset( $opts['quiet'] ); - $this->mDry = isset( $opts['dry'] ); - - // Set object properties, specially 'mMode' used by run() - if ( isset( $opts['list'] ) ) { - $this->mMode = 'LISTER'; - } elseif ( isset( $opts['usage'] ) ) { - $this->mMode = 'USAGER'; - $this->mAnOption = isset( $args[0] ) ? $args[0] : false; - } elseif ( isset( $opts['old'] ) && isset( $opts['new'] ) ) { - $this->mMode = 'CHANGER'; - $this->mOldValue = $opts['old']; - $this->mNewValue = $opts['new']; - $this->mAnOption = $args[0]; - } else { - die( "There is a bug in the software, this should never happen\n" ); - } - - return true; - } - - /** - * Dumb stuff to run a mode. - * @return bool - */ - public function run() { - if ( !$this->mReady ) { - return false; - } - - $this->{$this->mMode}(); - - return true; - } - - /** - * List default options and their value - */ - private function LISTER() { - $def = User::getDefaultOptions(); - ksort( $def ); - $maxOpt = 0; - foreach ( $def as $opt => $value ) { - $maxOpt = max( $maxOpt, strlen( $opt ) ); - } - foreach ( $def as $opt => $value ) { - printf( "%-{$maxOpt}s: %s\n", $opt, $value ); - } - } - - /** - * List options usage - */ - private function USAGER() { - $ret = []; - $defaultOptions = User::getDefaultOptions(); - - // We list user by user_id from one of the replica DBs - $dbr = wfGetDB( DB_REPLICA ); - $result = $dbr->select( 'user', - [ 'user_id' ], - [], - __METHOD__ - ); - - foreach ( $result as $id ) { - $user = User::newFromId( $id->user_id ); - - // Get the options and update stats - if ( $this->mAnOption ) { - if ( !array_key_exists( $this->mAnOption, $defaultOptions ) ) { - print "Invalid user option. Use --list to see valid choices\n"; - exit; - } - - $userValue = $user->getOption( $this->mAnOption ); - if ( $userValue <> $defaultOptions[$this->mAnOption] ) { - // @codingStandardsIgnoreStart Ignore silencing errors is discouraged warning - @$ret[$this->mAnOption][$userValue]++; - // @codingStandardsIgnoreEnd - } - } else { - - foreach ( $defaultOptions as $name => $defaultValue ) { - $userValue = $user->getOption( $name ); - if ( $userValue <> $defaultValue ) { - // @codingStandardsIgnoreStart Ignore silencing errors is discouraged warning - @$ret[$name][$userValue]++; - // @codingStandardsIgnoreEnd - } - } - } - } - - foreach ( $ret as $optionName => $usageStats ) { - print "Usage for <$optionName> (default: '{$defaultOptions[$optionName]}'):\n"; - foreach ( $usageStats as $value => $count ) { - print " $count user(s): '$value'\n"; - } - print "\n"; - } - } - - /** - * Change our users options - */ - private function CHANGER() { - $this->warn(); - - // We list user by user_id from one of the replica DBs - $dbr = wfGetDB( DB_REPLICA ); - $result = $dbr->select( 'user', - [ 'user_id' ], - [], - __METHOD__ - ); - - foreach ( $result as $id ) { - $user = User::newFromId( $id->user_id ); - - $curValue = $user->getOption( $this->mAnOption ); - $username = $user->getName(); - - if ( $curValue == $this->mOldValue ) { - if ( !$this->mQuiet ) { - print "Setting {$this->mAnOption} for $username from '{$this->mOldValue}' " . - "to '{$this->mNewValue}'): "; - } - - // Change value - $user->setOption( $this->mAnOption, $this->mNewValue ); - - // Will not save the settings if run with --dry - if ( !$this->mDry ) { - $user->saveSettings(); - } - if ( !$this->mQuiet ) { - print " OK\n"; - } - } elseif ( !$this->mQuiet ) { - print "Not changing '$username' using <{$this->mAnOption}> = '$curValue'\n"; - } - } - } - - /** - * Return an array of option names - * @return array - */ - public static function getDefaultOptionsNames() { - $def = User::getDefaultOptions(); - $ret = []; - foreach ( $def as $optname => $defaultValue ) { - array_push( $ret, $optname ); - } - - return $ret; - } - - public static function showUsageAndExit() { - print <<<USAGE - -This script pass through all users and change one of their options. -The new option is NOT validated. - -Usage: - php userOptions.php --list - php userOptions.php [user option] --usage - php userOptions.php [options] <user option> --old <old value> --new <new value> - -Switchs: - --list : list available user options and their default value - - --usage : report all options statistics or just one if you specify it. - - --old <old value> : the value to look for - --new <new value> : new value to update users with - -Options: - --nowarn: hides the 5 seconds warning - --quiet : do not print what is happening - --dry : do not save user settings back to database - -USAGE; - exit( 0 ); - } - - /** - * The warning message and countdown - * @return bool - */ - public function warn() { - if ( $this->mQuick ) { - return true; - } - - print <<<WARN -The script is about to change the skin for ALL USERS in the database. -Users with option <$this->mAnOption> = '$this->mOldValue' will be made to use '$this->mNewValue'. - -Abort with control-c in the next five seconds.... -WARN; - wfCountDown( 5 ); - - return true; - } -} diff --git a/maintenance/userOptions.php b/maintenance/userOptions.php index 53db48c..fabcbdc 100644 --- a/maintenance/userOptions.php +++ b/maintenance/userOptions.php @@ -24,12 +24,182 @@ * @author Antoine Musso <hashar at free dot fr> */ -// This is a command line script, load tools and parse args -require_once 'userOptions.inc'; +require_once __DIR__ . '/Maintenance.php'; -// Load up our tool system, exit with usage() if options are not fine -$uo = new UserOptions( $options, $args ); +/** + * @ingroup Maintenance + */ +class UserOptionsMaintenance extends Maintenance { -$uo->run(); + function __construct() { + parent::__construct(); -print "Done.\n"; + $this->addDescription( 'This script pass through all users and change one of their options. +The new option is NOT validated.' ); + + $this->addOption( 'list', 'List available user options and their default value' ); + $this->addOption( 'usage', 'Report all options statistics or just one if you specify it' ); + $this->addOption( 'old', 'The value to look for', false, true ); + $this->addOption( 'new', 'Rew value to update users with', false, true ); + $this->addOption( 'nowarn', 'Hides the 5 seconds warning' ); + $this->addOption( 'dry', 'Do not save user settings back to database' ); + $this->addArg( 'option name', 'Name of the option to change or provide statistics about', false ); + } + + /** + * Do the actual work + */ + public function execute() { + if ( $this->hasOption( 'list' ) ) { + $this->listAvailableOptions(); + } elseif ( $this->hasOption( 'usage' ) ) { + $this->showUsageStats(); + } elseif ( $this->hasOption( 'old' ) + && $this->hasOption( 'new' ) + && $this->hasArg( 0 ) + ) { + $this->updateOptions(); + } else { + $this->maybeHelp( /* force = */ true ); + } + } + + /** + * List default options and their value + */ + private function listAvailableOptions() { + $def = User::getDefaultOptions(); + ksort( $def ); + $maxOpt = 0; + foreach ( $def as $opt => $value ) { + $maxOpt = max( $maxOpt, strlen( $opt ) ); + } + foreach ( $def as $opt => $value ) { + $this->output( sprintf( "%-{$maxOpt}s: %s\n", $opt, $value ) ); + } + } + + /** + * List options usage + */ + private function showUsageStats() { + $option = $this->getArg( 0 ); + + $ret = []; + $defaultOptions = User::getDefaultOptions(); + + // We list user by user_id from one of the replica DBs + $dbr = wfGetDB( DB_REPLICA ); + $result = $dbr->select( 'user', + [ 'user_id' ], + [], + __METHOD__ + ); + + foreach ( $result as $id ) { + $user = User::newFromId( $id->user_id ); + + // Get the options and update stats + if ( $option ) { + if ( !array_key_exists( $option, $defaultOptions ) ) { + $this->error( "Invalid user option. Use --list to see valid choices\n", 1 ); + } + + $userValue = $user->getOption( $option ); + if ( $userValue <> $defaultOptions[$option] ) { + // @codingStandardsIgnoreStart Ignore silencing errors is discouraged warning + @$ret[$option][$userValue]++; + // @codingStandardsIgnoreEnd + } + } else { + + foreach ( $defaultOptions as $name => $defaultValue ) { + $userValue = $user->getOption( $name ); + if ( $userValue <> $defaultValue ) { + // @codingStandardsIgnoreStart Ignore silencing errors is discouraged warning + @$ret[$name][$userValue]++; + // @codingStandardsIgnoreEnd + } + } + } + } + + foreach ( $ret as $optionName => $usageStats ) { + $this->output( "Usage for <$optionName> (default: '{$defaultOptions[$optionName]}'):\n" ); + foreach ( $usageStats as $value => $count ) { + $this->output( " $count user(s): '$value'\n" ); + } + print "\n"; + } + } + + /** + * Change our users options + */ + private function updateOptions() { + $dryRun = $this->hasOption( 'dry' ); + $option = $this->getArg( 0 ); + $from = $this->getOption( 'old' ); + $to = $this->getOption( 'new' ); + + if ( !$dryRun ) { + $this->warn( $option, $from, $to ); + } + + // We list user by user_id from one of the replica DBs + // @todo: getting all users in one query does not scale + $dbr = wfGetDB( DB_REPLICA ); + $result = $dbr->select( 'user', + [ 'user_id' ], + [], + __METHOD__ + ); + + foreach ( $result as $id ) { + $user = User::newFromId( $id->user_id ); + + $curValue = $user->getOption( $option ); + $username = $user->getName(); + + if ( $curValue == $from ) { + $this->output( "Setting {$option} for $username from '{$from}' to '{$to}'): " ); + + // Change value + $user->setOption( $option, $to ); + + // Will not save the settings if run with --dry + if ( !$dryRun ) { + $user->saveSettings(); + } + $this->output( " OK\n" ); + } else { + $this->output( "Not changing '$username' using <{$option}> = '$curValue'\n" ); + } + } + } + + /** + * The warning message and countdown + * + * @param string $option + * @param string $from + * @param string $to + */ + private function warn( $option, $from, $to ) { + if ( $this->hasOption( 'nowarn' ) ) { + return; + } + + $this->output( <<<WARN +The script is about to change the skin for ALL USERS in the database. +Users with option <$option> = '$from' will be made to use '$to'. + +Abort with control-c in the next five seconds.... +WARN + ); + $this->countDown( 5 ); + } +} + +$maintClass = 'UserOptionsMaintenance'; +require RUN_MAINTENANCE_IF_MAIN; -- To view, visit https://gerrit.wikimedia.org/r/388935 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ic441087702376b1ca0e70554c71cdf7ecad908af Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: MaxSem <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
