MediaWiki  master
userOptions.php
Go to the documentation of this file.
1 <?php
27 require_once __DIR__ . '/Maintenance.php';
28 
33 
34  public function __construct() {
35  parent::__construct();
36 
37  $this->addDescription( 'Pass through all users and change one of their options.
38 The new option is NOT validated.' );
39 
40  $this->addOption( 'list', 'List available user options and their default value' );
41  $this->addOption( 'usage', 'Report all options statistics or just one if you specify it' );
42  $this->addOption( 'old', 'The value to look for', false, true );
43  $this->addOption( 'new', 'Rew value to update users with', false, true );
44  $this->addOption( 'nowarn', 'Hides the 5 seconds warning' );
45  $this->addOption( 'dry', 'Do not save user settings back to database' );
46  $this->addArg( 'option name', 'Name of the option to change or provide statistics about', false );
47  }
48 
52  public function execute() {
53  if ( $this->hasOption( 'list' ) ) {
54  $this->listAvailableOptions();
55  } elseif ( $this->hasOption( 'usage' ) ) {
56  $this->showUsageStats();
57  } elseif ( $this->hasOption( 'old' )
58  && $this->hasOption( 'new' )
59  && $this->hasArg( 0 )
60  ) {
61  $this->updateOptions();
62  } else {
63  $this->maybeHelp( /* force = */ true );
64  }
65  }
66 
70  private function listAvailableOptions() {
71  $def = User::getDefaultOptions();
72  ksort( $def );
73  $maxOpt = 0;
74  foreach ( $def as $opt => $value ) {
75  $maxOpt = max( $maxOpt, strlen( $opt ) );
76  }
77  foreach ( $def as $opt => $value ) {
78  $this->output( sprintf( "%-{$maxOpt}s: %s\n", $opt, $value ) );
79  }
80  }
81 
85  private function showUsageStats() {
86  $option = $this->getArg( 0 );
87 
88  $ret = [];
89  $defaultOptions = User::getDefaultOptions();
90 
91  // We list user by user_id from one of the replica DBs
92  $dbr = wfGetDB( DB_REPLICA );
93  $result = $dbr->select( 'user',
94  [ 'user_id' ],
95  [],
96  __METHOD__
97  );
98 
99  foreach ( $result as $id ) {
100  $user = User::newFromId( $id->user_id );
101 
102  // Get the options and update stats
103  if ( $option ) {
104  if ( !array_key_exists( $option, $defaultOptions ) ) {
105  $this->fatalError( "Invalid user option. Use --list to see valid choices\n" );
106  }
107 
108  $userValue = $user->getOption( $option );
109  if ( $userValue <> $defaultOptions[$option] ) {
110  $ret[$option][$userValue] = ( $ret[$option][$userValue] ?? 0 ) + 1;
111  }
112  } else {
113  foreach ( $defaultOptions as $name => $defaultValue ) {
114  $userValue = $user->getOption( $name );
115  if ( $userValue != $defaultValue ) {
116  $ret[$name][$userValue] = ( $ret[$name][$userValue] ?? 0 ) + 1;
117  }
118  }
119  }
120  }
121 
122  foreach ( $ret as $optionName => $usageStats ) {
123  $this->output( "Usage for <$optionName> (default: '{$defaultOptions[$optionName]}'):\n" );
124  foreach ( $usageStats as $value => $count ) {
125  $this->output( " $count user(s): '$value'\n" );
126  }
127  print "\n";
128  }
129  }
130 
134  private function updateOptions() {
135  $dryRun = $this->hasOption( 'dry' );
136  $option = $this->getArg( 0 );
137  $from = $this->getOption( 'old' );
138  $to = $this->getOption( 'new' );
139 
140  if ( !$dryRun ) {
141  $this->warn( $option, $from, $to );
142  }
143 
144  // We list user by user_id from one of the replica DBs
145  // @todo: getting all users in one query does not scale
146  $dbr = wfGetDB( DB_REPLICA );
147  $result = $dbr->select( 'user',
148  [ 'user_id' ],
149  [],
150  __METHOD__
151  );
152 
153  foreach ( $result as $id ) {
154  $user = User::newFromId( $id->user_id );
155 
156  $curValue = $user->getOption( $option );
157  $username = $user->getName();
158 
159  if ( $curValue == $from ) {
160  $this->output( "Setting {$option} for $username from '{$from}' to '{$to}'): " );
161 
162  // Change value
163  $user->setOption( $option, $to );
164 
165  // Will not save the settings if run with --dry
166  if ( !$dryRun ) {
167  $user->saveSettings();
168  }
169  $this->output( " OK\n" );
170  } else {
171  $this->output( "Not changing '$username' using <{$option}> = '$curValue'\n" );
172  }
173  }
174  }
175 
183  private function warn( $option, $from, $to ) {
184  if ( $this->hasOption( 'nowarn' ) ) {
185  return;
186  }
187 
188  $this->output( <<<WARN
189 The script is about to change the options for ALL USERS in the database.
190 Users with option <$option> = '$from' will be made to use '$to'.
191 
192 Abort with control-c in the next five seconds....
193 WARN
194  );
195  $this->countDown( 5 );
196  }
197 }
198 
199 $maintClass = UserOptionsMaintenance::class;
getArg( $argId=0, $default=null)
Get an argument.
const RUN_MAINTENANCE_IF_MAIN
Definition: Maintenance.php:39
showUsageStats()
List options usage.
Definition: userOptions.php:85
maybeHelp( $force=false)
Maybe show the help.
execute()
Do the actual work.
Definition: userOptions.php:52
getOption( $name, $default=null)
Get an option, or return the default.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: Maintenance.php:86
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
warn( $option, $from, $to)
The warning message and countdown.
hasOption( $name)
Checks to see if a particular option exists.
$maintClass
hasArg( $argId=0)
Does a given argument exist?
updateOptions()
Change our users options.
addDescription( $text)
Set the description text.
addArg( $arg, $description, $required=true)
Add some args that are needed.
output( $out, $channel=null)
Throw some output to the user.
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:539
countDown( $seconds)
Count down from $seconds to zero on the terminal, with a one-second pause between showing each number...
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
const DB_REPLICA
Definition: defines.php:25
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
static getDefaultOptions()
Combine the language default options with any site-specific options and add the default language vari...
Definition: User.php:1648
listAvailableOptions()
List default options and their value.
Definition: userOptions.php:70