39 parent::__construct();
41 $this->
addDescription(
'Pass through all users and change one of their options.
42The new option is NOT validated.' );
44 $this->
addOption(
'list',
'List available user options and their default value' );
45 $this->
addOption(
'usage',
'Report all options statistics or just one if you specify it' );
46 $this->
addOption(
'old',
'The value to look for',
false,
true );
47 $this->
addOption(
'new',
'New value to update users with',
false,
true );
48 $this->
addOption(
'fromuserid',
'Start from this user ID when changing options',
50 $this->
addOption(
'touserid',
'Do not go beyond this user ID when changing options',
52 $this->
addOption(
'nowarn',
'Hides the 5 seconds warning' );
53 $this->
addOption(
'dry',
'Do not save user settings back to database' );
54 $this->
addArg(
'option name',
'Name of the option to change or provide statistics about',
false );
63 $this->listAvailableOptions();
64 } elseif ( $this->
hasOption(
'usage' ) ) {
65 $this->showUsageStats();
70 $this->updateOptions();
79 private function listAvailableOptions() {
80 $userOptionsLookup = MediaWikiServices::getInstance()->getUserOptionsLookup();
81 $def = $userOptionsLookup->getDefaultOptions();
84 foreach ( $def as $opt => $value ) {
85 $maxOpt = max( $maxOpt, strlen( $opt ) );
87 foreach ( $def as $opt => $value ) {
88 $this->
output( sprintf(
"%-{$maxOpt}s: %s\n", $opt, $value ) );
95 private function showUsageStats() {
96 $option = $this->
getArg( 0 );
99 $userOptionsLookup = MediaWikiServices::getInstance()->getUserOptionsLookup();
100 $defaultOptions = $userOptionsLookup->getDefaultOptions();
104 $result =
$dbr->select(
'user',
110 foreach ( $result as $id ) {
115 if ( !array_key_exists( $option, $defaultOptions ) ) {
116 $this->
fatalError(
"Invalid user option. Use --list to see valid choices\n" );
119 $userValue = $userOptionsLookup->getOption( $user, $option );
120 if ( $userValue <> $defaultOptions[$option] ) {
121 $ret[$option][$userValue] = ( $ret[$option][$userValue] ?? 0 ) + 1;
124 foreach ( $defaultOptions as $name => $defaultValue ) {
125 $userValue = $userOptionsLookup->getOption( $user, $name );
126 if ( $userValue != $defaultValue ) {
127 $ret[$name][$userValue] = ( $ret[$name][$userValue] ?? 0 ) + 1;
133 foreach ( $ret as $optionName => $usageStats ) {
134 $this->
output(
"Usage for <$optionName> (default: '{$defaultOptions[$optionName]}'):\n" );
135 foreach ( $usageStats as $value => $count ) {
136 $this->
output(
" $count user(s): '$value'\n" );
145 private function updateOptions() {
147 $settingWord = $dryRun ?
'Would set' :
'Setting';
148 $option = $this->
getArg( 0 );
153 $this->warn( $option, $from, $to );
156 $userOptionsManager = MediaWikiServices::getInstance()->getUserOptionsManager();
160 $fromUserId = (int)$this->
getOption(
'fromuserid', 1 ) - 1;
161 $toUserId = (int)$this->
getOption(
'touserid', 0 ) ?:
null;
163 $queryBuilderTemplate
165 ->join(
'user_properties',
null, [
167 'up_property' => $option,
169 ->fields( [
'user_id',
'user_name' ] )
171 ->where( [
'up_value' => $from ] )
174 ->orderBy(
'user_id', SelectQueryBuilder::SORT_ASC )
176 ->caller( __METHOD__ );
178 $queryBuilderTemplate->andWhere(
"user_id <= $toUserId " );
182 $queryBuilder = clone $queryBuilderTemplate;
183 $queryBuilder->andWhere(
"user_id > $fromUserId" );
184 $result = $queryBuilder->fetchResultSet();
185 foreach ( $result as $row ) {
186 $this->
output(
"$settingWord {$option} for {$row->user_name} from '{$from}' to '{$to}'\n" );
187 $user = UserIdentityValue::newRegistered( $row->user_id, $row->user_name );
189 $userOptionsManager->setOption( $user, $option, $to );
190 $userOptionsManager->saveOptions( $user );
192 $fromUserId = (int)$row->user_id;
195 }
while ( $result->numRows() );
205 private function warn( $option, $from, $to ) {
211The script is about to change the options
for ALL USERS in the database.
212Users with option <$option> =
'$from' will be made to use
'$to'.
214Abort with control-c in the next five seconds....
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
addArg( $arg, $description, $required=true)
Add some args that are needed.
output( $out, $channel=null)
Throw some output to the user.
hasArg( $argId=0)
Does a given argument exist?
waitForReplication()
Wait for replica DBs to catch up.
hasOption( $name)
Checks to see if a particular option was set.
countDown( $seconds)
Count down from $seconds to zero on the terminal, with a one-second pause between showing each number...
getArg( $argId=0, $default=null)
Get an argument.
addDescription( $text)
Set the description text.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
getOption( $name, $default=null)
Get an option, or return the default.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.