Index: trunk/phase3/maintenance/doMaintenance.php |
— | — | @@ -1,60 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * We want to make this whole thing as seamless as possible to the |
5 | | - * end-user. Unfortunately, we can't do _all_ of the work in the class |
6 | | - * because A) included files are not in global scope, but in the scope |
7 | | - * of their caller, and B) MediaWiki has way too many globals. So instead |
8 | | - * we'll kinda fake it, and do the requires() inline. <3 PHP |
9 | | - */ |
10 | | - |
11 | | -if( !isset( $maintClass ) || !class_exists( $maintClass ) ) { |
12 | | - echo "\$maintClass is not set or is set to a non-existent class."; |
13 | | - die(); |
14 | | -} |
15 | | - |
16 | | -if( defined( 'MW_NO_SETUP' ) ) { |
17 | | - return; |
18 | | -} |
19 | | - |
20 | | -// Get an object to start us off |
21 | | -$maintenance = new $maintClass(); |
22 | | - |
23 | | -// Basic sanity checks and such |
24 | | -$maintenance->setup(); |
25 | | - |
26 | | -# Setup the profiler |
27 | | -if ( file_exists( "$IP/StartProfiler.php" ) ) { |
28 | | - require_once( "$IP/StartProfiler.php" ); |
29 | | -} else { |
30 | | - require_once( "$IP/includes/ProfilerStub.php" ); |
31 | | -} |
32 | | - |
33 | | -// Load settings, using wikimedia-mode if needed |
34 | | -if( file_exists( dirname(__FILE__).'/wikimedia-mode' ) ) { |
35 | | - # TODO FIXME! Wikimedia-specific stuff needs to go away to an ext |
36 | | - # Maybe a hook? |
37 | | - global $cluster; |
38 | | - $wgWikiFarm = true; |
39 | | - $cluster = 'pmtma'; |
40 | | - require_once( "$IP/includes/AutoLoader.php" ); |
41 | | - require_once( "$IP/includes/SiteConfiguration.php" ); |
42 | | - require( "$IP/wgConf.php" ); |
43 | | - $maintenance->loadWikimediaSettings(); |
44 | | - require( $IP.'/includes/Defines.php' ); |
45 | | - require( $IP.'/CommonSettings.php' ); |
46 | | -} else { |
47 | | - require_once( "$IP/includes/AutoLoader.php" ); |
48 | | - require_once( "$IP/includes/Defines.php" ); |
49 | | - require_once( $maintenance->loadSettings() ); |
50 | | -} |
51 | | -// Some last includes |
52 | | -require_once( "$IP/includes/Setup.php" ); |
53 | | -require_once( "$IP/install-utils.inc" ); |
54 | | - |
55 | | -$wgTitle = null; # Much much faster startup than creating a title object |
56 | | - |
57 | | -try { |
58 | | - $maintenance->execute(); |
59 | | -} catch( MWException $mwe ) { |
60 | | - echo( $mwe->getText() ); |
61 | | -} |
\ No newline at end of file |
Index: trunk/phase3/maintenance/Maintenance.php |
— | — | @@ -1,639 +0,0 @@ |
2 | | -<?php |
3 | | -// Define this so scripts can easily find doMaintenance.php |
4 | | -define( 'DO_MAINTENANCE', dirname(__FILE__) . '/doMaintenance.php' ); |
5 | | - |
6 | | -/** |
7 | | - * Abstract maintenance class for quickly writing and churning out |
8 | | - * maintenance scripts with minimal effort. All that _must_ be defined |
9 | | - * is the execute() method. See docs/maintenance.txt for more info |
10 | | - * and a quick demo of how to use it. |
11 | | - * |
12 | | - * @author Chad Horohoe <chad@anyonecanedit.org> |
13 | | - * @since 1.16 |
14 | | - * @ingroup Maintenance |
15 | | - */ |
16 | | -abstract class Maintenance { |
17 | | - |
18 | | - /** |
19 | | - * Constants for DB access type |
20 | | - * @see Maintenance::getDbType() |
21 | | - */ |
22 | | - const NO_DB = 0; |
23 | | - const NORMAL_DB = 1; |
24 | | - const ADMIN_DB = 2; |
25 | | - |
26 | | - // This is the desired params |
27 | | - private $mParams = array(); |
28 | | - |
29 | | - // Array of desired args |
30 | | - private $mArgList = array(); |
31 | | - |
32 | | - // This is the list of options that were actually passed |
33 | | - private $mOptions = array(); |
34 | | - |
35 | | - // This is the list of arguments that were actually passed |
36 | | - protected $mArgs = array(); |
37 | | - |
38 | | - // Name of the script currently running |
39 | | - protected $mSelf; |
40 | | - |
41 | | - // Special vars for params that are always used |
42 | | - private $mQuiet = false; |
43 | | - private $mDbUser, $mDbPass; |
44 | | - |
45 | | - // A description of the script, children should change this |
46 | | - protected $mDescription = ''; |
47 | | - |
48 | | - // Have we already loaded our user input? |
49 | | - private $inputLoaded = false; |
50 | | - |
51 | | - // Batch size |
52 | | - protected $mBatchSize = 100; |
53 | | - |
54 | | - /** |
55 | | - * Default constructor. Children should call this if implementing |
56 | | - * their own constructors |
57 | | - */ |
58 | | - public function __construct() { |
59 | | - $this->addDefaultParams(); |
60 | | - } |
61 | | - |
62 | | - /** |
63 | | - * Do the actual work. All child classes will need to implement this |
64 | | - */ |
65 | | - abstract public function execute(); |
66 | | - |
67 | | - /** |
68 | | - * Add a parameter to the script. Will be displayed on --help |
69 | | - * with the associated description |
70 | | - * |
71 | | - * @param $name String The name of the param (help, version, etc) |
72 | | - * @param $description String The description of the param to show on --help |
73 | | - * @param $required boolean Is the param required? |
74 | | - * @param $withArg Boolean Is an argument required with this option? |
75 | | - */ |
76 | | - protected function addParam( $name, $description, $required = false, $withArg = false ) { |
77 | | - $this->mParams[ $name ] = array( 'desc' => $description, 'require' => $required, 'withArg' => $withArg ); |
78 | | - } |
79 | | - |
80 | | - /** |
81 | | - * Checks to see if a particular param exists. |
82 | | - * @param $name String The name of the param |
83 | | - * @return boolean |
84 | | - */ |
85 | | - protected function hasOption( $name ) { |
86 | | - return isset( $this->mOptions[ $name ] ); |
87 | | - } |
88 | | - |
89 | | - /** |
90 | | - * Get an option, or return the default |
91 | | - * @param $name String The name of the param |
92 | | - * @param $default mixed Anything you want, default null |
93 | | - * @return mixed |
94 | | - */ |
95 | | - protected function getOption( $name, $default = null ) { |
96 | | - if( $this->hasOption($name) ) { |
97 | | - return $this->mOptions[$name]; |
98 | | - } else { |
99 | | - // Set it so we don't have to provide the default again |
100 | | - $this->mOptions[$name] = $default; |
101 | | - return $this->mOptions[$name]; |
102 | | - } |
103 | | - } |
104 | | - |
105 | | - /** |
106 | | - * Add some args that are needed. Used in formatting help |
107 | | - */ |
108 | | - protected function addArgs( $args ) { |
109 | | - $this->mArgList = array_merge( $this->mArgList, $args ); |
110 | | - } |
111 | | - |
112 | | - /** |
113 | | - * Does a given argument exist? |
114 | | - * @param $argId int The integer value (from zero) for the arg |
115 | | - * @return boolean |
116 | | - */ |
117 | | - protected function hasArg( $argId = 0 ) { |
118 | | - return isset( $this->mArgs[ $argId ] ) ; |
119 | | - } |
120 | | - |
121 | | - /** |
122 | | - * Get an argument. |
123 | | - * @param $argId int The integer value (from zero) for the arg |
124 | | - * @param $default mixed The default if it doesn't exist |
125 | | - * @return mixed |
126 | | - */ |
127 | | - protected function getArg( $argId = 0, $default = null ) { |
128 | | - return $this->hasArg($name) ? $this->mArgs[$name] : $default; |
129 | | - } |
130 | | - |
131 | | - /** |
132 | | - * Set the batch size. |
133 | | - * @param $s int The number of operations to do in a batch |
134 | | - */ |
135 | | - protected function setBatchSize( $s = 0 ) { |
136 | | - $this->mBatchSize = $s; |
137 | | - } |
138 | | - |
139 | | - /** |
140 | | - * Return input from stdin. |
141 | | - * @param $length int The number of bytes to read. If null, |
142 | | - * just return the handle |
143 | | - * @return mixed |
144 | | - */ |
145 | | - protected function getStdin( $len = null ) { |
146 | | - $f = fopen( 'php://stdin', 'rt' ); |
147 | | - if( !$len ) { |
148 | | - return $f; |
149 | | - } |
150 | | - $input = fgets( $f, $len ); |
151 | | - fclose ( $f ); |
152 | | - return rtrim( $input ); |
153 | | - } |
154 | | - |
155 | | - /** |
156 | | - * Throw some output to the user. Scripts can call this with no fears, |
157 | | - * as we handle all --quiet stuff here |
158 | | - * @param $out String The text to show to the user |
159 | | - */ |
160 | | - protected function output( $out ) { |
161 | | - if( $this->mQuiet ) { |
162 | | - return; |
163 | | - } |
164 | | - $f = fopen( 'php://stdout', 'w' ); |
165 | | - fwrite( $f, $out ); |
166 | | - fclose( $f ); |
167 | | - } |
168 | | - |
169 | | - /** |
170 | | - * Throw an error to the user. Doesn't respect --quiet, so don't use |
171 | | - * this for non-error output |
172 | | - * @param $err String The error to display |
173 | | - * @param $die boolean If true, go ahead and die out. |
174 | | - */ |
175 | | - protected function error( $err, $die = false ) { |
176 | | - $f = fopen( 'php://stderr', 'w' ); |
177 | | - fwrite( $f, $err ); |
178 | | - fclose( $f ); |
179 | | - if( $die ) die(); |
180 | | - } |
181 | | - |
182 | | - /** |
183 | | - * Does the script need normal DB access? By default, we give Maintenance |
184 | | - * scripts admin rights to the DB (when available). Sometimes, a script needs |
185 | | - * normal access for a reason and sometimes they want no access. Subclasses |
186 | | - * should override and return one of the following values, as needed: |
187 | | - * Maintenance::NO_DB - For no DB access at all |
188 | | - * Maintenance::NORMAL_DB - For normal DB access |
189 | | - * Maintenance::ADMIN_DB - For admin DB access, default |
190 | | - * @return int |
191 | | - */ |
192 | | - protected function getDbType() { |
193 | | - return Maintenance :: ADMIN_DB; |
194 | | - } |
195 | | - |
196 | | - /** |
197 | | - * Add the default parameters to the scripts |
198 | | - */ |
199 | | - private function addDefaultParams() { |
200 | | - $this->addParam( 'help', "Display this help message" ); |
201 | | - $this->addParam( 'quiet', "Whether to supress non-error output" ); |
202 | | - $this->addParam( 'conf', "Location of LocalSettings.php, if not default", false, true ); |
203 | | - $this->addParam( 'wiki', "For specifying the wiki ID", false, true ); |
204 | | - if( $this->getDbType() > 0 ) { |
205 | | - $this->addParam( 'dbuser', "The DB user to use for this script", false, true ); |
206 | | - $this->addParam( 'dbpass', "The password to use for this script", false, true ); |
207 | | - } |
208 | | - } |
209 | | - |
210 | | - /** |
211 | | - * Spawn a child maintenance script. Pass all of the current arguments |
212 | | - * to it. |
213 | | - * @param $maintClass String A name of a child maintenance class |
214 | | - * @param $classFile String Full path of where the child is |
215 | | - * @return Maintenance child |
216 | | - */ |
217 | | - protected function spawnChild( $maintClass, $classFile = null ) { |
218 | | - // If we haven't already specified, kill setup procedures |
219 | | - // for child scripts, we've already got a sane environment |
220 | | - if( !defined( 'MW_NO_SETUP' ) ) { |
221 | | - define( 'MW_NO_SETUP', true ); |
222 | | - } |
223 | | - |
224 | | - // Make sure the class is loaded first |
225 | | - if( !class_exists( $maintClass ) ) { |
226 | | - if( $classFile ) { |
227 | | - require_once( $classFile ); |
228 | | - } |
229 | | - if( !class_exists( $maintClass ) ) { |
230 | | - $this->error( "Cannot spawn child: $maintClass\n" ); |
231 | | - } |
232 | | - } |
233 | | - |
234 | | - $child = new $maintClass(); |
235 | | - $child->loadParamsAndArgs( $this->mSelf, $this->mOptions, $this->mArgs ); |
236 | | - return $child; |
237 | | - } |
238 | | - |
239 | | - /** |
240 | | - * Do some sanity checking and basic setup |
241 | | - */ |
242 | | - public function setup() { |
243 | | - global $IP, $wgCommandLineMode, $wgUseNormalUser, $wgRequestTime; |
244 | | - |
245 | | - # Abort if called from a web server |
246 | | - if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) { |
247 | | - $this->error( "This script must be run from the command line\n", true ); |
248 | | - } |
249 | | - |
250 | | - # Make sure we can handle script parameters |
251 | | - if( !ini_get( 'register_argc_argv' ) ) { |
252 | | - $this->error( "Cannot get command line arguments, register_argc_argv is set to false", true ); |
253 | | - } |
254 | | - |
255 | | - # Make sure we're on PHP5 or better |
256 | | - if( version_compare( PHP_VERSION, '5.0.0' ) < 0 ) { |
257 | | - $this->error( "Sorry! This version of MediaWiki requires PHP 5; you are running " . |
258 | | - PHP_VERSION . ".\n\n" . |
259 | | - "If you are sure you already have PHP 5 installed, it may be installed\n" . |
260 | | - "in a different path from PHP 4. Check with your system administrator.\n", true ); |
261 | | - } |
262 | | - |
263 | | - if( version_compare( phpversion(), '5.2.4' ) >= 0 ) { |
264 | | - // Send PHP warnings and errors to stderr instead of stdout. |
265 | | - // This aids in diagnosing problems, while keeping messages |
266 | | - // out of redirected output. |
267 | | - if( ini_get( 'display_errors' ) ) { |
268 | | - ini_set( 'display_errors', 'stderr' ); |
269 | | - } |
270 | | - |
271 | | - // Don't touch the setting on earlier versions of PHP, |
272 | | - // as setting it would disable output if you'd wanted it. |
273 | | - |
274 | | - // Note that exceptions are also sent to stderr when |
275 | | - // command-line mode is on, regardless of PHP version. |
276 | | - } |
277 | | - |
278 | | - # Set the memory limit |
279 | | - ini_set( 'memory_limit', -1 ); |
280 | | - |
281 | | - $wgRequestTime = microtime(true); |
282 | | - |
283 | | - # Define us as being in Mediawiki |
284 | | - define( 'MEDIAWIKI', true ); |
285 | | - |
286 | | - # Setup $IP, using MW_INSTALL_PATH if it exists |
287 | | - $IP = strval( getenv('MW_INSTALL_PATH') ) !== '' |
288 | | - ? getenv('MW_INSTALL_PATH') |
289 | | - : realpath( dirname( __FILE__ ) . '/..' ); |
290 | | - |
291 | | - $wgCommandLineMode = true; |
292 | | - # Turn off output buffering if it's on |
293 | | - @ob_end_flush(); |
294 | | - |
295 | | - if (!isset( $wgUseNormalUser ) ) { |
296 | | - $wgUseNormalUser = false; |
297 | | - } |
298 | | - |
299 | | - $this->loadParamsAndArgs(); |
300 | | - $this->maybeHelp(); |
301 | | - } |
302 | | - |
303 | | - /** |
304 | | - * Clear all params and arguments. |
305 | | - */ |
306 | | - public function clearParamsAndArgs() { |
307 | | - $this->mOptions = array(); |
308 | | - $this->mArgs = array(); |
309 | | - $this->inputLoaded = false; |
310 | | - } |
311 | | - |
312 | | - /** |
313 | | - * Process command line arguments |
314 | | - * $mOptions becomes an array with keys set to the option names |
315 | | - * $mArgs becomes a zero-based array containing the non-option arguments |
316 | | - * |
317 | | - * @param $self String The name of the script, if any |
318 | | - * @param $opts Array An array of options, in form of key=>value |
319 | | - * @param $args Array An array of command line arguments |
320 | | - */ |
321 | | - public function loadParamsAndArgs( $self = null, $opts = null, $args = null ) { |
322 | | - # If we were given opts or args, set those and return early |
323 | | - if( $self ) { |
324 | | - $this->mSelf = $self; |
325 | | - $this->inputLoaded = true; |
326 | | - } |
327 | | - if( $opts ) { |
328 | | - $this->mOptions = $opts; |
329 | | - $this->inputLoaded = true; |
330 | | - } |
331 | | - if( $args ) { |
332 | | - $this->mArgs = $args; |
333 | | - $this->inputLoaded = true; |
334 | | - } |
335 | | - |
336 | | - # If we've already loaded input (either by user values or from $argv) |
337 | | - # skip on loading it again. The array_shift() will corrupt values if |
338 | | - # it's run again and again |
339 | | - if( $this->inputLoaded ) { |
340 | | - $this->loadSpecialVars(); |
341 | | - return; |
342 | | - } |
343 | | - |
344 | | - global $argv; |
345 | | - $this->mSelf = array_shift( $argv ); |
346 | | - |
347 | | - $options = array(); |
348 | | - $args = array(); |
349 | | - |
350 | | - # Parse arguments |
351 | | - for( $arg = reset( $argv ); $arg !== false; $arg = next( $argv ) ) { |
352 | | - if ( $arg == '--' ) { |
353 | | - # End of options, remainder should be considered arguments |
354 | | - $arg = next( $argv ); |
355 | | - while( $arg !== false ) { |
356 | | - $args[] = $arg; |
357 | | - $arg = next( $argv ); |
358 | | - } |
359 | | - break; |
360 | | - } elseif ( substr( $arg, 0, 2 ) == '--' ) { |
361 | | - # Long options |
362 | | - $option = substr( $arg, 2 ); |
363 | | - if ( isset( $this->mParams[$option] ) && $this->mParams[$option]['withArg'] ) { |
364 | | - $param = next( $argv ); |
365 | | - if ( $param === false ) { |
366 | | - $this->error( "$arg needs a value after it\n", true ); |
367 | | - } |
368 | | - $options[$option] = $param; |
369 | | - } else { |
370 | | - $bits = explode( '=', $option, 2 ); |
371 | | - if( count( $bits ) > 1 ) { |
372 | | - $option = $bits[0]; |
373 | | - $param = $bits[1]; |
374 | | - } else { |
375 | | - $param = 1; |
376 | | - } |
377 | | - $options[$option] = $param; |
378 | | - } |
379 | | - } elseif ( substr( $arg, 0, 1 ) == '-' ) { |
380 | | - # Short options |
381 | | - for ( $p=1; $p<strlen( $arg ); $p++ ) { |
382 | | - $option = $arg{$p}; |
383 | | - if ( isset( $this->mParams[$option]['withArg'] ) ) { |
384 | | - $param = next( $argv ); |
385 | | - if ( $param === false ) { |
386 | | - $this->error( "$arg needs a value after it\n", true ); |
387 | | - } |
388 | | - $options[$option] = $param; |
389 | | - } else { |
390 | | - $options[$option] = 1; |
391 | | - } |
392 | | - } |
393 | | - } else { |
394 | | - $args[] = $arg; |
395 | | - } |
396 | | - } |
397 | | - |
398 | | - # Check to make sure we've got all the required ones |
399 | | - foreach( $this->mParams as $opt => $info ) { |
400 | | - if( $info['require'] && !$this->hasOption($opt) ) { |
401 | | - $this->error( "Param $opt required.\n", true ); |
402 | | - } |
403 | | - } |
404 | | - |
405 | | - # Also make sure we've got enough arguments |
406 | | - if ( count( $args ) < count( $this->mArgList ) ) { |
407 | | - $this->error( "Not enough arguments passed", true ); |
408 | | - } |
409 | | - |
410 | | - $this->mOptions = $options; |
411 | | - $this->mArgs = $args; |
412 | | - $this->loadSpecialVars(); |
413 | | - $this->inputLoaded = true; |
414 | | - } |
415 | | - |
416 | | - /** |
417 | | - * Handle the special variables that are global to all scripts |
418 | | - */ |
419 | | - private function loadSpecialVars() { |
420 | | - if( $this->hasOption( 'dbuser' ) ) |
421 | | - $this->mDbUser = $this->getOption( 'dbuser' ); |
422 | | - if( $this->hasOption( 'dbpass' ) ) |
423 | | - $this->mDbPass = $this->getOption( 'dbpass' ); |
424 | | - if( $this->hasOption( 'quiet' ) ) |
425 | | - $this->mQuiet = true; |
426 | | - } |
427 | | - |
428 | | - /** |
429 | | - * Maybe show the help. |
430 | | - * @param $force boolean Whether to force the help to show, default false |
431 | | - */ |
432 | | - private function maybeHelp( $force = false ) { |
433 | | - if( $this->hasOption('help') || in_array( 'help', $this->mArgs ) || $force ) { |
434 | | - $this->mQuiet = false; |
435 | | - if( $this->mDescription ) { |
436 | | - $this->output( $this->mDescription . "\n" ); |
437 | | - } |
438 | | - $this->output( "\nUsage: php " . $this->mSelf ); |
439 | | - if( $this->mParams ) { |
440 | | - $this->output( " [--" . implode( array_keys( $this->mParams ), "|--" ) . "]" ); |
441 | | - } |
442 | | - if( $this->mArgList ) { |
443 | | - $this->output( " <" . implode( $this->mArgList, "> <" ) . ">" ); |
444 | | - } |
445 | | - $this->output( "\n" ); |
446 | | - foreach( $this->mParams as $par => $info ) { |
447 | | - $this->output( "\t$par : " . $info['desc'] . "\n" ); |
448 | | - } |
449 | | - die( 1 ); |
450 | | - } |
451 | | - } |
452 | | - |
453 | | - /** |
454 | | - * Handle some last-minute setup here. |
455 | | - */ |
456 | | - private function finalSetup() { |
457 | | - global $wgCommandLineMode, $wgUseNormalUser, $wgShowSQLErrors; |
458 | | - global $wgTitle, $wgProfiling, $IP, $wgDBadminuser, $wgDBadminpassword; |
459 | | - global $wgDBuser, $wgDBpassword, $wgDBservers, $wgLBFactoryConf; |
460 | | - |
461 | | - # Turn off output buffering again, it might have been turned on in the settings files |
462 | | - if( ob_get_level() ) { |
463 | | - ob_end_flush(); |
464 | | - } |
465 | | - # Same with these |
466 | | - $wgCommandLineMode = true; |
467 | | - |
468 | | - # If these were passed, use them |
469 | | - if( $this->mDbUser ) |
470 | | - $wgDBadminuser = $this->mDbUser; |
471 | | - if( $this->mDbPass ) |
472 | | - $wgDBadminpass = $this->mDbPass; |
473 | | - |
474 | | - if ( empty( $wgUseNormalUser ) && isset( $wgDBadminuser ) ) { |
475 | | - $wgDBuser = $wgDBadminuser; |
476 | | - $wgDBpassword = $wgDBadminpassword; |
477 | | - |
478 | | - if( $wgDBservers ) { |
479 | | - foreach ( $wgDBservers as $i => $server ) { |
480 | | - $wgDBservers[$i]['user'] = $wgDBuser; |
481 | | - $wgDBservers[$i]['password'] = $wgDBpassword; |
482 | | - } |
483 | | - } |
484 | | - if( isset( $wgLBFactoryConf['serverTemplate'] ) ) { |
485 | | - $wgLBFactoryConf['serverTemplate']['user'] = $wgDBuser; |
486 | | - $wgLBFactoryConf['serverTemplate']['password'] = $wgDBpassword; |
487 | | - } |
488 | | - } |
489 | | - |
490 | | - if ( defined( 'MW_CMDLINE_CALLBACK' ) ) { |
491 | | - $fn = MW_CMDLINE_CALLBACK; |
492 | | - $fn(); |
493 | | - } |
494 | | - |
495 | | - $wgShowSQLErrors = true; |
496 | | - @set_time_limit( 0 ); |
497 | | - |
498 | | - $wgProfiling = false; // only for Profiler.php mode; avoids OOM errors |
499 | | - } |
500 | | - |
501 | | - /** |
502 | | - * Do setup specific to WMF |
503 | | - */ |
504 | | - public function loadWikimediaSettings() { |
505 | | - global $IP, $wgNoDBParam, $wgUseNormalUser, $wgConf; |
506 | | - |
507 | | - if ( empty( $wgNoDBParam ) ) { |
508 | | - # Check if we were passed a db name |
509 | | - if ( isset( $this->mOptions['wiki'] ) ) { |
510 | | - $db = $this->mOptions['wiki']; |
511 | | - } else { |
512 | | - $db = array_shift( $this->mArgs ); |
513 | | - } |
514 | | - list( $site, $lang ) = $wgConf->siteFromDB( $db ); |
515 | | - |
516 | | - # If not, work out the language and site the old way |
517 | | - if ( is_null( $site ) || is_null( $lang ) ) { |
518 | | - if ( !$db ) { |
519 | | - $lang = 'aa'; |
520 | | - } else { |
521 | | - $lang = $db; |
522 | | - } |
523 | | - if ( isset( $this->mArgs[0] ) ) { |
524 | | - $site = array_shift( $this->mArgs ); |
525 | | - } else { |
526 | | - $site = 'wikipedia'; |
527 | | - } |
528 | | - } |
529 | | - } else { |
530 | | - $lang = 'aa'; |
531 | | - $site = 'wikipedia'; |
532 | | - } |
533 | | - |
534 | | - # This is for the IRC scripts, which now run as the apache user |
535 | | - # The apache user doesn't have access to the wikiadmin_pass command |
536 | | - if ( $_ENV['USER'] == 'apache' ) { |
537 | | - #if ( posix_geteuid() == 48 ) { |
538 | | - $wgUseNormalUser = true; |
539 | | - } |
540 | | - |
541 | | - putenv( 'wikilang=' . $lang ); |
542 | | - |
543 | | - $DP = $IP; |
544 | | - ini_set( 'include_path', ".:$IP:$IP/includes:$IP/languages:$IP/maintenance" ); |
545 | | - |
546 | | - if ( $lang == 'test' && $site == 'wikipedia' ) { |
547 | | - define( 'TESTWIKI', 1 ); |
548 | | - } |
549 | | - } |
550 | | - |
551 | | - /** |
552 | | - * Generic setup for most installs. Returns the location of LocalSettings |
553 | | - * @return String |
554 | | - */ |
555 | | - public function loadSettings() { |
556 | | - global $wgWikiFarm, $wgCommandLineMode, $IP, $DP; |
557 | | - |
558 | | - $wgWikiFarm = false; |
559 | | - if ( isset( $this->mOptions['conf'] ) ) { |
560 | | - $settingsFile = $this->mOptions['conf']; |
561 | | - } else { |
562 | | - $settingsFile = "$IP/LocalSettings.php"; |
563 | | - } |
564 | | - if ( isset( $this->mOptions['wiki'] ) ) { |
565 | | - $bits = explode( '-', $this->mOptions['wiki'] ); |
566 | | - if ( count( $bits ) == 1 ) { |
567 | | - $bits[] = ''; |
568 | | - } |
569 | | - define( 'MW_DB', $bits[0] ); |
570 | | - define( 'MW_PREFIX', $bits[1] ); |
571 | | - } |
572 | | - |
573 | | - if ( ! is_readable( $settingsFile ) ) { |
574 | | - $this->error( "A copy of your installation's LocalSettings.php\n" . |
575 | | - "must exist and be readable in the source directory.\n", true ); |
576 | | - } |
577 | | - $wgCommandLineMode = true; |
578 | | - $DP = $IP; |
579 | | - $this->finalSetup(); |
580 | | - return $settingsFile; |
581 | | - } |
582 | | - |
583 | | - /** |
584 | | - * Support function for cleaning up redundant text records |
585 | | - * @param $delete boolean Whether or not to actually delete the records |
586 | | - * @author Rob Church <robchur@gmail.com> |
587 | | - */ |
588 | | - protected function purgeRedundantText( $delete = true ) { |
589 | | - # Data should come off the master, wrapped in a transaction |
590 | | - $dbw = wfGetDB( DB_MASTER ); |
591 | | - $dbw->begin(); |
592 | | - |
593 | | - $tbl_arc = $dbw->tableName( 'archive' ); |
594 | | - $tbl_rev = $dbw->tableName( 'revision' ); |
595 | | - $tbl_txt = $dbw->tableName( 'text' ); |
596 | | - |
597 | | - # Get "active" text records from the revisions table |
598 | | - $this->output( "Searching for active text records in revisions table..." ); |
599 | | - $res = $dbw->query( "SELECT DISTINCT rev_text_id FROM $tbl_rev" ); |
600 | | - while( $row = $dbw->fetchObject( $res ) ) { |
601 | | - $cur[] = $row->rev_text_id; |
602 | | - } |
603 | | - $this->output( "done.\n" ); |
604 | | - |
605 | | - # Get "active" text records from the archive table |
606 | | - $this->output( "Searching for active text records in archive table..." ); |
607 | | - $res = $dbw->query( "SELECT DISTINCT ar_text_id FROM $tbl_arc" ); |
608 | | - while( $row = $dbw->fetchObject( $res ) ) { |
609 | | - $cur[] = $row->ar_text_id; |
610 | | - } |
611 | | - $this->output( "done.\n" ); |
612 | | - |
613 | | - # Get the IDs of all text records not in these sets |
614 | | - $this->output( "Searching for inactive text records..." ); |
615 | | - $set = implode( ', ', $cur ); |
616 | | - $res = $dbw->query( "SELECT old_id FROM $tbl_txt WHERE old_id NOT IN ( $set )" ); |
617 | | - $old = array(); |
618 | | - while( $row = $dbw->fetchObject( $res ) ) { |
619 | | - $old[] = $row->old_id; |
620 | | - } |
621 | | - $this->output( "done.\n" ); |
622 | | - |
623 | | - # Inform the user of what we're going to do |
624 | | - $count = count( $old ); |
625 | | - $this->output( "$count inactive items found.\n" ); |
626 | | - |
627 | | - # Delete as appropriate |
628 | | - if( $delete && $count ) { |
629 | | - $this->output( "Deleting..." ); |
630 | | - $set = implode( ', ', $old ); |
631 | | - $dbw->query( "DELETE FROM $tbl_txt WHERE old_id IN ( $set )" ); |
632 | | - $this->output( "done.\n" ); |
633 | | - } |
634 | | - |
635 | | - # Done |
636 | | - $dbw->commit(); |
637 | | - |
638 | | - } |
639 | | -} |
640 | | - |
Index: trunk/phase3/maintenance/stats.php |
— | — | @@ -1,73 +1,58 @@ |
2 | 2 | <?php |
3 | 3 | /** |
4 | 4 | * Show statistics from memcached |
| 5 | + * |
| 6 | + * @file |
5 | 7 | * @ingroup Maintenance |
6 | 8 | */ |
7 | 9 | |
8 | | -require_once( "Maintenance.php" ); |
| 10 | +require_once('commandLine.inc'); |
9 | 11 | |
10 | | -class MemcachedStats extends Maintenance { |
11 | | - |
12 | | - public function __construct() { |
13 | | - $this->mDescription = "Show statistics from memcached"; |
14 | | - } |
15 | | - |
16 | | - public function execute() { |
17 | | - global $wgMemc; |
18 | | - |
19 | | - // Can't do stats if |
20 | | - if( get_class( $wgMemc ) == 'FakeMemCachedClient' ) { |
21 | | - $this->error( "You are running FakeMemCachedClient, I can not provide any statistics.\n", true ); |
22 | | - } |
23 | | - $session = intval($wgMemc->get(wfMemcKey('stats','request_with_session'))); |
24 | | - $noSession = intval($wgMemc->get(wfMemcKey('stats','request_without_session'))); |
25 | | - $total = $session + $noSession; |
26 | | - if ( $total == 0 ) { |
27 | | - $this->error( "You either have no stats or memcached isn't running. Aborting.\n", true ); |
28 | | - } |
29 | | - $this->output( "Requests\n" ); |
30 | | - $this->output( sprintf( "with session: %-10d %6.2f%%\n", $session, $session/$total*100 ); |
31 | | - $this->output( sprintf( "without session: %-10d %6.2f%%\n", $noSession, $noSession/$total*100 ); |
32 | | - $this->output( sprintf( "total: %-10d %6.2f%%\n", $total, 100 ); |
33 | | - |
34 | | - |
35 | | - $this->output( "\nParser cache\n" ); |
36 | | - $hits = intval($wgMemc->get(wfMemcKey('stats','pcache_hit'))); |
37 | | - $invalid = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_invalid'))); |
38 | | - $expired = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_expired'))); |
39 | | - $absent = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_absent'))); |
40 | | - $stub = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_stub'))); |
41 | | - $total = $hits + $invalid + $expired + $absent + $stub; |
42 | | - $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ) ); |
43 | | - $this->output( sprintf( "invalid: %-10d %6.2f%%\n", $invalid, $invalid/$total*100 ) ); |
44 | | - $this->output( sprintf( "expired: %-10d %6.2f%%\n", $expired, $expired/$total*100 ) ); |
45 | | - $this->output( sprintf( "absent: %-10d %6.2f%%\n", $absent, $absent/$total*100 ) ); |
46 | | - $this->output( sprintf( "stub threshold: %-10d %6.2f%%\n", $stub, $stub/$total*100 ) ); |
47 | | - $this->output( sprintf( "total: %-10d %6.2f%%\n", $total, 100 ) ); |
48 | | - |
49 | | - $hits = intval($wgMemc->get(wfMemcKey('stats','image_cache_hit'))); |
50 | | - $misses = intval($wgMemc->get(wfMemcKey('stats','image_cache_miss'))); |
51 | | - $updates = intval($wgMemc->get(wfMemcKey('stats','image_cache_update'))); |
52 | | - $total = $hits + $misses; |
53 | | - $this->output("\nImage cache\n"); |
54 | | - $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ) ); |
55 | | - $this->output( sprintf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 ) ); |
56 | | - $this->output( sprintf( "updates: %-10d\n", $updates ) ); |
57 | | - |
58 | | - $hits = intval($wgMemc->get(wfMemcKey('stats','diff_cache_hit'))); |
59 | | - $misses = intval($wgMemc->get(wfMemcKey('stats','diff_cache_miss'))); |
60 | | - $uncacheable = intval($wgMemc->get(wfMemcKey('stats','diff_uncacheable'))); |
61 | | - $total = $hits + $misses + $uncacheable; |
62 | | - $this->output("\nDiff cache\n"); |
63 | | - $this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ); |
64 | | - $this->output( sprintf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 ); |
65 | | - $this->output( sprintf( "uncacheable: %-10d %6.2f%%\n", $uncacheable, $uncacheable/$total*100 ); |
66 | | - } |
| 12 | +if( get_class( $wgMemc ) == 'FakeMemCachedClient' ) { |
| 13 | + die("You are running FakeMemCachedClient, I can not provide any statistics.\n"); |
67 | 14 | } |
| 15 | +$session = intval($wgMemc->get(wfMemcKey('stats','request_with_session'))); |
| 16 | +$noSession = intval($wgMemc->get(wfMemcKey('stats','request_without_session'))); |
| 17 | +$total = $session + $noSession; |
| 18 | +if ( $total == 0 ) { |
| 19 | + die("You either have no stats or memcached isn't running. Aborting.\n"); |
| 20 | +} |
| 21 | +print "Requests\n"; |
| 22 | +printf( "with session: %-10d %6.2f%%\n", $session, $session/$total*100 ); |
| 23 | +printf( "without session: %-10d %6.2f%%\n", $noSession, $noSession/$total*100 ); |
| 24 | +printf( "total: %-10d %6.2f%%\n", $total, 100 ); |
68 | 25 | |
69 | | -$maintClass = "MemcachedStats"; |
70 | | -require_once( DO_MAINTENANCE ); |
71 | 26 | |
| 27 | +print "\nParser cache\n"; |
| 28 | +$hits = intval($wgMemc->get(wfMemcKey('stats','pcache_hit'))); |
| 29 | +$invalid = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_invalid'))); |
| 30 | +$expired = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_expired'))); |
| 31 | +$absent = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_absent'))); |
| 32 | +$stub = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_stub'))); |
| 33 | +$total = $hits + $invalid + $expired + $absent + $stub; |
| 34 | +printf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ); |
| 35 | +printf( "invalid: %-10d %6.2f%%\n", $invalid, $invalid/$total*100 ); |
| 36 | +printf( "expired: %-10d %6.2f%%\n", $expired, $expired/$total*100 ); |
| 37 | +printf( "absent: %-10d %6.2f%%\n", $absent, $absent/$total*100 ); |
| 38 | +printf( "stub threshold: %-10d %6.2f%%\n", $stub, $stub/$total*100 ); |
| 39 | +printf( "total: %-10d %6.2f%%\n", $total, 100 ); |
72 | 40 | |
| 41 | +$hits = intval($wgMemc->get(wfMemcKey('stats','image_cache_hit'))); |
| 42 | +$misses = intval($wgMemc->get(wfMemcKey('stats','image_cache_miss'))); |
| 43 | +$updates = intval($wgMemc->get(wfMemcKey('stats','image_cache_update'))); |
| 44 | +$total = $hits + $misses; |
| 45 | +print("\nImage cache\n"); |
| 46 | +printf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ); |
| 47 | +printf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 ); |
| 48 | +printf( "updates: %-10d\n", $updates ); |
73 | 49 | |
| 50 | +$hits = intval($wgMemc->get(wfMemcKey('stats','diff_cache_hit'))); |
| 51 | +$misses = intval($wgMemc->get(wfMemcKey('stats','diff_cache_miss'))); |
| 52 | +$uncacheable = intval($wgMemc->get(wfMemcKey('stats','diff_uncacheable'))); |
| 53 | +$total = $hits + $misses + $uncacheable; |
| 54 | +print("\nDiff cache\n"); |
| 55 | +printf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ); |
| 56 | +printf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 ); |
| 57 | +printf( "uncacheable: %-10d %6.2f%%\n", $uncacheable, $uncacheable/$total*100 ); |
74 | 58 | |
| 59 | + |
Index: trunk/phase3/maintenance/deleteBatch.php |
— | — | @@ -1,4 +1,5 @@ |
2 | 2 | <?php |
| 3 | + |
3 | 4 | /** |
4 | 5 | * Deletes a batch of pages |
5 | 6 | * Usage: php deleteBatch.php [-u <user>] [-r <reason>] [-i <interval>] [listfile] |
— | — | @@ -12,87 +13,86 @@ |
13 | 14 | * @file |
14 | 15 | * @ingroup Maintenance |
15 | 16 | */ |
16 | | - |
17 | | -require_once( "Maintenance.php" ); |
18 | 17 | |
19 | | -class DeleteBatch extends Maintenance { |
20 | | - |
21 | | - public function __construct() { |
22 | | - parent::__construct(); |
23 | | - $this->mDescription = "Deletes a batch of pages"; |
24 | | - $this->addParam( 'u', "User to perform deletion", false, true ); |
25 | | - $this->addParam( 'r', "Reason to delete page", false, true ); |
26 | | - $this->addParam( 'i', "Interval to sleep between deletions" ); |
27 | | - $this->addArgs( array( 'listfile' ) ); |
| 18 | +$oldCwd = getcwd(); |
| 19 | +$optionsWithArgs = array( 'u', 'r', 'i' ); |
| 20 | +require_once( 'commandLine.inc' ); |
| 21 | + |
| 22 | +chdir( $oldCwd ); |
| 23 | + |
| 24 | +# Options processing |
| 25 | + |
| 26 | +$filename = 'php://stdin'; |
| 27 | +$user = 'Delete page script'; |
| 28 | +$reason = ''; |
| 29 | +$interval = 0; |
| 30 | + |
| 31 | +if ( isset( $args[0] ) ) { |
| 32 | + $filename = $args[0]; |
| 33 | +} |
| 34 | +if ( isset( $options['u'] ) ) { |
| 35 | + $user = $options['u']; |
| 36 | +} |
| 37 | +if ( isset( $options['r'] ) ) { |
| 38 | + $reason = $options['r']; |
| 39 | +} |
| 40 | +if ( isset( $options['i'] ) ) { |
| 41 | + $interval = $options['i']; |
| 42 | +} |
| 43 | + |
| 44 | +$wgUser = User::newFromName( $user ); |
| 45 | + |
| 46 | + |
| 47 | +# Setup complete, now start |
| 48 | + |
| 49 | +$file = fopen( $filename, 'r' ); |
| 50 | +if ( !$file ) { |
| 51 | + print "Unable to read file, exiting\n"; |
| 52 | + exit; |
| 53 | +} |
| 54 | + |
| 55 | +$dbw = wfGetDB( DB_MASTER ); |
| 56 | + |
| 57 | +for ( $linenum = 1; !feof( $file ); $linenum++ ) { |
| 58 | + $line = trim( fgets( $file ) ); |
| 59 | + if ( $line == '' ) { |
| 60 | + continue; |
28 | 61 | } |
29 | | - |
30 | | - public function execute() { |
31 | | - global $wgUser; |
| 62 | + $page = Title::newFromText( $line ); |
| 63 | + if ( is_null( $page ) ) { |
| 64 | + print "Invalid title '$line' on line $linenum\n"; |
| 65 | + continue; |
| 66 | + } |
| 67 | + if( !$page->exists() ) { |
| 68 | + print "Skipping nonexistent page '$line'\n"; |
| 69 | + continue; |
| 70 | + } |
32 | 71 | |
33 | | - # Change to current working directory |
34 | | - $oldCwd = getcwd(); |
35 | | - chdir( $oldCwd ); |
36 | | - |
37 | | - # Options processing |
38 | | - $user = $this->getOption( 'u', 'Delete page script' ); |
39 | | - $reason = $this->getOption( 'r', '' ); |
40 | | - $interval = $this->getOption( 'i', 0 ); |
41 | | - if( $this->hasArg() ) { |
42 | | - $file = fopen( $this->getArg(), 'r' ); |
43 | | - } else { |
44 | | - $file = $this->getStdin(); |
45 | | - } |
46 | 72 | |
47 | | - # Setup |
48 | | - if( !$file ) { |
49 | | - $this->error( "Unable to read file, exiting\n", true ); |
| 73 | + print $page->getPrefixedText(); |
| 74 | + $dbw->begin(); |
| 75 | + if( $page->getNamespace() == NS_FILE ) { |
| 76 | + $art = new ImagePage( $page ); |
| 77 | + $img = wfFindFile( $art->mTitle ); |
| 78 | + if( !$img || !$img->delete( $reason ) ) { |
| 79 | + print "FAILED to delete image file... "; |
50 | 80 | } |
51 | | - $wgUser = User::newFromName( $user ); |
52 | | - $dbw = wfGetDB( DB_MASTER ); |
| 81 | + } else { |
| 82 | + $art = new Article( $page ); |
| 83 | + } |
| 84 | + $success = $art->doDeleteArticle( $reason ); |
| 85 | + $dbw->immediateCommit(); |
| 86 | + if ( $success ) { |
| 87 | + print "\n"; |
| 88 | + } else { |
| 89 | + print " FAILED to delete image page\n"; |
| 90 | + } |
53 | 91 | |
54 | | - # Handle each entry |
55 | | - for ( $linenum = 1; !feof( $file ); $linenum++ ) { |
56 | | - $line = trim( fgets( $file ) ); |
57 | | - if ( $line == '' ) { |
58 | | - continue; |
59 | | - } |
60 | | - $page = Title::newFromText( $line ); |
61 | | - if ( is_null( $page ) ) { |
62 | | - $this->output( "Invalid title '$line' on line $linenum\n" ); |
63 | | - continue; |
64 | | - } |
65 | | - if( !$page->exists() ) { |
66 | | - $this->output( "Skipping nonexistent page '$line'\n" ); |
67 | | - continue; |
68 | | - } |
69 | | - |
70 | | - |
71 | | - $this->output( $page->getPrefixedText() ); |
72 | | - $dbw->begin(); |
73 | | - if( $page->getNamespace() == NS_FILE ) { |
74 | | - $art = new ImagePage( $page ); |
75 | | - $img = wfFindFile( $art->mTitle ); |
76 | | - if( !$img || !$img->delete( $reason ) ) { |
77 | | - $this->output( "FAILED to delete image file... " ); |
78 | | - } |
79 | | - } else { |
80 | | - $art = new Article( $page ); |
81 | | - } |
82 | | - $success = $art->doDeleteArticle( $reason ); |
83 | | - $dbw->immediateCommit(); |
84 | | - if ( $success ) { |
85 | | - $this->output( "\n" ); |
86 | | - } else { |
87 | | - $this->output( " FAILED to delete article\n" ); |
88 | | - } |
89 | | - |
90 | | - if ( $interval ) { |
91 | | - sleep( $interval ); |
92 | | - } |
93 | | - wfWaitForSlaves( 5 ); |
94 | | -} |
| 92 | + if ( $interval ) { |
| 93 | + sleep( $interval ); |
95 | 94 | } |
| 95 | + wfWaitForSlaves( 5 ); |
96 | 96 | } |
97 | 97 | |
98 | | -$maintClass = "DeleteBatch"; |
99 | | -require_once( DO_MAINTENANCE ); |
| 98 | + |
| 99 | + |
Index: trunk/phase3/maintenance/waitForSlave.php |
— | — | @@ -5,16 +5,11 @@ |
6 | 6 | * @ingroup Maintenance |
7 | 7 | */ |
8 | 8 | |
9 | | -require_once( "Maintenance.php" ); |
10 | | - |
11 | | -class WaitForSlave extends Maintenance { |
12 | | - public function __construct() { |
13 | | - $this->addArgs( array( 'maxlag' ) ); |
14 | | - } |
15 | | - public function execute() { |
16 | | - wfWaitForSlaves( $this->getArg( 0, 10 ) ); |
17 | | - } |
| 9 | +require_once( "commandLine.inc" ); |
| 10 | +if ( isset( $args[0] ) ) { |
| 11 | + wfWaitForSlaves($args[0]); |
| 12 | +} else { |
| 13 | + wfWaitForSlaves(10); |
18 | 14 | } |
19 | 15 | |
20 | | -$maintClass = "WaitForSlave"; |
21 | | -require_once( DO_MAINTENANCE ); |
| 16 | + |
Index: trunk/phase3/maintenance/eval.php |
— | — | @@ -16,66 +16,57 @@ |
17 | 17 | * @ingroup Maintenance |
18 | 18 | */ |
19 | 19 | |
20 | | -require_once( "Maintenance.php" ); |
| 20 | +$wgUseNormalUser = (bool)getenv('MW_WIKIUSER'); |
21 | 21 | |
22 | | -class EvalPrompt extends Maintenance { |
| 22 | +$optionsWithArgs = array( 'd' ); |
23 | 23 | |
24 | | - public function __construct() { |
25 | | - parent::__construct(); |
26 | | - $this->mDescription = "This script lets a command-line user start up the wiki engine and then poke\n" . |
27 | | - "about by issuing PHP commands directly."; |
28 | | - $this->addParam( 'd', "Enable MediaWiki debug output", false, true ); |
| 24 | +/** */ |
| 25 | +require_once( "commandLine.inc" ); |
| 26 | + |
| 27 | +if ( isset( $options['d'] ) ) { |
| 28 | + $d = $options['d']; |
| 29 | + if ( $d > 0 ) { |
| 30 | + $wgDebugLogFile = '/dev/stdout'; |
29 | 31 | } |
30 | | - |
31 | | - public function execute() { |
32 | | - global $wgUseNormalUser; |
33 | | - $wgUseNormalUser = (bool)getenv('MW_WIKIUSER'); |
34 | | - if ( $this->hasOption('d') ) { |
35 | | - $d = $this->getOption('d'); |
36 | | - if ( $d > 0 ) { |
37 | | - $wgDebugLogFile = '/dev/stdout'; |
38 | | - } |
39 | | - if ( $d > 1 ) { |
40 | | - $lb = wfGetLB(); |
41 | | - foreach ( $lb->mServers as $i => $server ) { |
42 | | - $lb->mServers[$i]['flags'] |= DBO_DEBUG; |
43 | | - } |
44 | | - } |
45 | | - if ( $d > 2 ) { |
46 | | - $wgDebugFunctionEntry = true; |
47 | | - } |
| 32 | + if ( $d > 1 ) { |
| 33 | + $lb = wfGetLB(); |
| 34 | + foreach ( $lb->mServers as $i => $server ) { |
| 35 | + $lb->mServers[$i]['flags'] |= DBO_DEBUG; |
48 | 36 | } |
49 | | - |
50 | | - if ( function_exists( 'readline_add_history' ) |
51 | | - && function_exists( 'posix_isatty' ) && posix_isatty( 0 /*STDIN*/ ) ) |
52 | | - { |
53 | | - $useReadline = true; |
54 | | - } else { |
55 | | - $useReadline = false; |
56 | | - } |
57 | | - |
58 | | - if ( $useReadline ) { |
59 | | - $historyFile = "{$_ENV['HOME']}/.mweval_history"; |
60 | | - readline_read_history( $historyFile ); |
61 | | - } |
62 | | - |
63 | | - while ( ( $line = readconsole( '> ' ) ) !== false ) { |
64 | | - if ( $useReadline ) { |
65 | | - readline_add_history( $line ); |
66 | | - readline_write_history( $historyFile ); |
67 | | - } |
68 | | - $val = eval( $line . ";" ); |
69 | | - if( is_null( $val ) ) { |
70 | | - echo "\n"; |
71 | | - } elseif( is_string( $val ) || is_numeric( $val ) ) { |
72 | | - echo "$val\n"; |
73 | | - } else { |
74 | | - var_dump( $val ); |
75 | | - } |
76 | | - } |
77 | | - print "\n"; |
78 | 37 | } |
| 38 | + if ( $d > 2 ) { |
| 39 | + $wgDebugFunctionEntry = true; |
| 40 | + } |
79 | 41 | } |
80 | 42 | |
81 | | -$maintClass = "EvalPrompt"; |
82 | | -require_once( DO_MAINTENANCE ); |
| 43 | +if ( function_exists( 'readline_add_history' ) |
| 44 | + && function_exists( 'posix_isatty' ) && posix_isatty( 0 /*STDIN*/ ) ) |
| 45 | +{ |
| 46 | + $useReadline = true; |
| 47 | +} else { |
| 48 | + $useReadline = false; |
| 49 | +} |
| 50 | + |
| 51 | +if ( $useReadline ) { |
| 52 | + $historyFile = "{$_ENV['HOME']}/.mweval_history"; |
| 53 | + readline_read_history( $historyFile ); |
| 54 | +} |
| 55 | + |
| 56 | +while ( ( $line = readconsole( '> ' ) ) !== false ) { |
| 57 | + if ( $useReadline ) { |
| 58 | + readline_add_history( $line ); |
| 59 | + readline_write_history( $historyFile ); |
| 60 | + } |
| 61 | + $val = eval( $line . ";" ); |
| 62 | + if( is_null( $val ) ) { |
| 63 | + echo "\n"; |
| 64 | + } elseif( is_string( $val ) || is_numeric( $val ) ) { |
| 65 | + echo "$val\n"; |
| 66 | + } else { |
| 67 | + var_dump( $val ); |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +print "\n"; |
| 72 | + |
| 73 | + |
Index: trunk/phase3/maintenance/renameDbPrefix.php |
— | — | @@ -6,59 +6,62 @@ |
7 | 7 | * @file |
8 | 8 | * @ingroup Maintenance |
9 | 9 | */ |
10 | | - |
11 | | -require_once( "Maintenance.php" ); |
| 10 | +$optionsWithArgs = array( 'old', 'new', 'help' ); |
12 | 11 | |
13 | | -class RenameDbPrefix extends Maintenance { |
14 | | - public function __construct() { |
15 | | - parent::__construct(); |
16 | | - $this->addParam( "old", "Old db prefix [0 for none]", true, true ); |
17 | | - $this->addParam( "new", "New db prefix [0 for none]", true, true ); |
| 12 | +require_once( 'commandLine.inc' ); |
| 13 | + |
| 14 | +if( @$options['help'] || !isset( $options['old'] ) || !isset( $options['new'] ) ) { |
| 15 | + print "usage: renameDbPrefix.php [--help] [--old x] [new y]\n"; |
| 16 | + print " --help : this help message\n"; |
| 17 | + print " --old x : old db prefix x\n"; |
| 18 | + print " --old 0 : EMPTY old db prefix x\n"; |
| 19 | + print " --new y : new db prefix y\n"; |
| 20 | + print " --new 0 : EMPTY new db prefix\n"; |
| 21 | + wfDie(); |
| 22 | +} |
| 23 | + |
| 24 | +// Allow for no old prefix |
| 25 | +if( $options['old'] === '0' ) { |
| 26 | + $old = ''; |
| 27 | +} else { |
| 28 | + // Use nice safe, sane, prefixes |
| 29 | + preg_match( '/^[a-zA-Z]+_$/', $options['old'], $m ); |
| 30 | + $old = isset( $m[0] ) ? $m[0] : false; |
| 31 | +} |
| 32 | +// Allow for no new prefix |
| 33 | +if( $options['new'] === '0' ) { |
| 34 | + $new = ''; |
| 35 | +} else { |
| 36 | + // Use nice safe, sane, prefixes |
| 37 | + preg_match( '/^[a-zA-Z]+_$/', $options['new'], $m ); |
| 38 | + $new = isset( $m[0] ) ? $m[0] : false; |
| 39 | +} |
| 40 | + |
| 41 | +if( $old === false || $new === false ) { |
| 42 | + print "Invalid prefix!\n"; |
| 43 | + wfDie(); |
| 44 | +} |
| 45 | +if( $old === $new ) { |
| 46 | + print "Same prefix. Nothing to rename!\n"; |
| 47 | + wfDie(); |
| 48 | +} |
| 49 | + |
| 50 | +print "Renaming DB prefix for tables of $wgDBname from '$old' to '$new'\n"; |
| 51 | +$count = 0; |
| 52 | + |
| 53 | +$dbw = wfGetDB( DB_MASTER ); |
| 54 | +$res = $dbw->query( "SHOW TABLES LIKE '".$dbw->escapeLike( $old )."%'" ); |
| 55 | +foreach( $res as $row ) { |
| 56 | + // XXX: odd syntax. MySQL outputs an oddly cased "Tables of X" |
| 57 | + // sort of message. Best not to try $row->x stuff... |
| 58 | + $fields = get_object_vars( $row ); |
| 59 | + // Silly for loop over one field... |
| 60 | + foreach( $fields as $resName => $table ) { |
| 61 | + // $old should be regexp safe ([a-zA-Z_]) |
| 62 | + $newTable = preg_replace( '/^'.$old.'/', $new, $table ); |
| 63 | + print "Renaming table $table to $newTable\n"; |
| 64 | + $dbw->query( "RENAME TABLE $table TO $newTable" ); |
18 | 65 | } |
19 | | - |
20 | | - public function execute() { |
21 | | - // Allow for no old prefix |
22 | | - if( $this->getOption( 'old', 0 ) === '0' ) { |
23 | | - $old = ''; |
24 | | - } else { |
25 | | - // Use nice safe, sane, prefixes |
26 | | - preg_match( '/^[a-zA-Z]+_$/', $this->getOption('old'), $m ); |
27 | | - $old = isset( $m[0] ) ? $m[0] : false; |
28 | | - } |
29 | | - // Allow for no new prefix |
30 | | - if( $this->getOption( 'new', 0 ) === '0' ) { |
31 | | - $new = ''; |
32 | | - } else { |
33 | | - // Use nice safe, sane, prefixes |
34 | | - preg_match( '/^[a-zA-Z]+_$/', $this->getOption('new'), $m ); |
35 | | - $new = isset( $m[0] ) ? $m[0] : false; |
36 | | - } |
37 | | - |
38 | | - if( $old === false || $new === false ) { |
39 | | - $this->error( "Invalid prefix!\n", true ); |
40 | | - } |
41 | | - if( $old === $new ) { |
42 | | - $this->( "Same prefix. Nothing to rename!\n", true ); |
43 | | - } |
44 | | - |
45 | | - $this->output( "Renaming DB prefix for tables of $wgDBname from '$old' to '$new'\n" ); |
46 | | - $count = 0; |
47 | | - |
48 | | - $dbw = wfGetDB( DB_MASTER ); |
49 | | - $res = $dbw->query( "SHOW TABLES LIKE '".$dbw->escapeLike( $old )."%'" ); |
50 | | - foreach( $res as $row ) { |
51 | | - // XXX: odd syntax. MySQL outputs an oddly cased "Tables of X" |
52 | | - // sort of message. Best not to try $row->x stuff... |
53 | | - $fields = get_object_vars( $row ); |
54 | | - // Silly for loop over one field... |
55 | | - foreach( $fields as $resName => $table ) { |
56 | | - // $old should be regexp safe ([a-zA-Z_]) |
57 | | - $newTable = preg_replace( '/^'.$old.'/', $new, $table ); |
58 | | - $this->output( "Renaming table $table to $newTable\n" ); |
59 | | - $dbw->query( "RENAME TABLE $table TO $newTable" ); |
60 | | - } |
61 | | - $count++; |
62 | | - } |
63 | | - $this->output( "Done! [$count tables]\n" ); |
64 | | - } |
| 66 | + $count++; |
65 | 67 | } |
| 68 | +print "Done! [$count tables]\n"; |
\ No newline at end of file |
Index: trunk/phase3/maintenance/benchmarkPurge.php |
— | — | @@ -6,87 +6,74 @@ |
7 | 7 | * @ingroup Maintenance |
8 | 8 | */ |
9 | 9 | |
10 | | -require_once( "Maintenance.php" ); |
| 10 | +/** */ |
| 11 | +require_once( "commandLine.inc" ); |
11 | 12 | |
12 | | -class BenchmarkPurge extends Maintenance { |
13 | | - |
14 | | - public function __construct() { |
15 | | - parent::__construct(); |
16 | | - $this->addParams( "count", "How many URLs to feed to Squid for purging", false, true ); |
17 | | - $this->mDescription = "Benchmark the Squid purge functions."; |
| 13 | +/** |
| 14 | + * Run a bunch of URLs through SquidUpdate::purge() |
| 15 | + * to benchmark Squid response times. |
| 16 | + * @param $urls array A bunch of URLs to purge |
| 17 | + * @param $trials int How many times to run the test? |
| 18 | + */ |
| 19 | +function benchSquid( $urls, $trials = 1 ) { |
| 20 | + $start = wfTime(); |
| 21 | + for( $i = 0; $i < $trials; $i++) { |
| 22 | + SquidUpdate::purge( $urls ); |
18 | 23 | } |
19 | | - |
20 | | - public function execute() { |
21 | | - global $wgUseSquid; |
22 | | - if( !$wgUseSquid ) { |
23 | | - $this->error( "Squid purge benchmark doesn't do much without squid support on.\n". true ); |
24 | | - } else { |
25 | | - $this->output( "There are " . count( $wgSquidServers ) . " defined squid servers:\n" ); |
26 | | - if( $this->hasOption( 'count' ) ) { |
27 | | - $lengths = array( intval( $this->getOption('count') ) ); |
28 | | - } else { |
29 | | - $lengths = array( 1, 10, 100 ); |
30 | | - } |
31 | | - foreach( $lengths as $length ) { |
32 | | - $urls = $this->randomUrlList( $length ); |
33 | | - $trial = $this->benchSquid( $urls ); |
34 | | - $this->output( $trial . "\n" ); |
35 | | - } |
36 | | - } |
| 24 | + $delta = wfTime() - $start; |
| 25 | + $pertrial = $delta / $trials; |
| 26 | + $pertitle = $pertrial / count( $urls ); |
| 27 | + return sprintf( "%4d titles in %6.2fms (%6.2fms each)", |
| 28 | + count( $urls ), $pertrial * 1000.0, $pertitle * 1000.0 ); |
| 29 | +} |
| 30 | + |
| 31 | +/** |
| 32 | + * Get an array of randomUrl()'s. |
| 33 | + * @param $length int How many urls to add to the array |
| 34 | + */ |
| 35 | +function randomUrlList( $length ) { |
| 36 | + $list = array(); |
| 37 | + for( $i = 0; $i < $length; $i++ ) { |
| 38 | + $list[] = randomUrl(); |
37 | 39 | } |
38 | | - |
39 | | - /** |
40 | | - * Run a bunch of URLs through SquidUpdate::purge() |
41 | | - * to benchmark Squid response times. |
42 | | - * @param $urls array A bunch of URLs to purge |
43 | | - * @param $trials int How many times to run the test? |
44 | | - */ |
45 | | - private function benchSquid( $urls, $trials = 1 ) { |
46 | | - $start = wfTime(); |
47 | | - for( $i = 0; $i < $trials; $i++) { |
48 | | - SquidUpdate::purge( $urls ); |
49 | | - } |
50 | | - $delta = wfTime() - $start; |
51 | | - $pertrial = $delta / $trials; |
52 | | - $pertitle = $pertrial / count( $urls ); |
53 | | - return sprintf( "%4d titles in %6.2fms (%6.2fms each)", |
54 | | - count( $urls ), $pertrial * 1000.0, $pertitle * 1000.0 ); |
| 40 | + return $list; |
| 41 | +} |
| 42 | + |
| 43 | +/** |
| 44 | + * Return a random URL of the wiki. Not necessarily an actual title in the |
| 45 | + * database, but at least a URL that looks like one. |
| 46 | + */ |
| 47 | +function randomUrl() { |
| 48 | + global $wgServer, $wgArticlePath; |
| 49 | + return $wgServer . str_replace( '$1', randomTitle(), $wgArticlePath ); |
| 50 | +} |
| 51 | + |
| 52 | +/** |
| 53 | + * Create a random title string (not necessarily a Title object). |
| 54 | + * For use with randomUrl(). |
| 55 | + */ |
| 56 | +function randomTitle() { |
| 57 | + $str = ''; |
| 58 | + $length = mt_rand( 1, 20 ); |
| 59 | + for( $i = 0; $i < $length; $i++ ) { |
| 60 | + $str .= chr( mt_rand( ord('a'), ord('z') ) ); |
55 | 61 | } |
56 | | - |
57 | | - /** |
58 | | - * Get an array of randomUrl()'s. |
59 | | - * @param $length int How many urls to add to the array |
60 | | - */ |
61 | | - private function randomUrlList( $length ) { |
62 | | - $list = array(); |
63 | | - for( $i = 0; $i < $length; $i++ ) { |
64 | | - $list[] = $this->randomUrl(); |
65 | | - } |
66 | | - return $list; |
| 62 | + return ucfirst( $str ); |
| 63 | +} |
| 64 | + |
| 65 | +if( !$wgUseSquid ) { |
| 66 | + wfDie( "Squid purge benchmark doesn't do much without squid support on.\n" ); |
| 67 | +} else { |
| 68 | + printf( "There are %d defined squid servers:\n", count( $wgSquidServers ) ); |
| 69 | + #echo implode( "\n", $wgSquidServers ) . "\n"; |
| 70 | + if( isset( $options['count'] ) ) { |
| 71 | + $lengths = array( intval( $options['count'] ) ); |
| 72 | + } else { |
| 73 | + $lengths = array( 1, 10, 100 ); |
67 | 74 | } |
68 | | - |
69 | | - /** |
70 | | - * Return a random URL of the wiki. Not necessarily an actual title in the |
71 | | - * database, but at least a URL that looks like one. |
72 | | - */ |
73 | | - private function randomUrl() { |
74 | | - global $wgServer, $wgArticlePath; |
75 | | - return $wgServer . str_replace( '$1', $this->randomTitle(), $wgArticlePath ); |
| 75 | + foreach( $lengths as $length ) { |
| 76 | + $urls = randomUrlList( $length ); |
| 77 | + $trial = benchSquid( $urls ); |
| 78 | + print "$trial\n"; |
76 | 79 | } |
77 | | - |
78 | | - /** |
79 | | - * Create a random title string (not necessarily a Title object). |
80 | | - * For use with randomUrl(). |
81 | | - */ |
82 | | - private function randomTitle() { |
83 | | - $str = ''; |
84 | | - $length = mt_rand( 1, 20 ); |
85 | | - for( $i = 0; $i < $length; $i++ ) { |
86 | | - $str .= chr( mt_rand( ord('a'), ord('z') ) ); |
87 | | - } |
88 | | - return ucfirst( $str ); |
89 | | - } |
90 | 80 | } |
91 | | - |
92 | | -$maintClass = "BenchmarkPurge"; |
93 | | -require_once( DO_MAINTENANCE ); |
Index: trunk/phase3/maintenance/nukePage.php |
— | — | @@ -1,4 +1,5 @@ |
2 | 2 | <?php |
| 3 | + |
3 | 4 | /** |
4 | 5 | * Erase a page record from the database |
5 | 6 | * Irreversible (can't use standard undelete) and does not update link tables |
— | — | @@ -8,92 +9,21 @@ |
9 | 10 | * @author Rob Church <robchur@gmail.com> |
10 | 11 | */ |
11 | 12 | |
12 | | -require_once( "Maintenance.php" ); |
| 13 | +require_once( 'commandLine.inc' ); |
| 14 | +require_once( 'nukePage.inc' ); |
13 | 15 | |
14 | | -class NukePage extends Maintenance { |
15 | | - public function __construct() { |
16 | | - parent::__construct(); |
17 | | - $this->mDescription = "Remove a page record from the database"; |
18 | | - $this->addParam( 'delete', "Actually delete the page" ); |
19 | | - $this->addArgs( array( 'title' ) ); |
20 | | - } |
| 16 | +echo( "Erase Page Record\n\n" ); |
21 | 17 | |
22 | | - public function execute() { |
| 18 | +if( isset( $args[0] ) ) { |
| 19 | + NukePage( $args[0], true ); |
| 20 | +} else { |
| 21 | + ShowUsage(); |
| 22 | +} |
23 | 23 | |
24 | | - $name = $this->getArg(); |
25 | | - $delete = $this->getOption( 'delete', false ); |
26 | | - |
27 | | - $dbw = wfGetDB( DB_MASTER ); |
28 | | - $dbw->begin(); |
29 | | - |
30 | | - $tbl_pag = $dbw->tableName( 'page' ); |
31 | | - $tbl_rec = $dbw->tableName( 'recentchanges' ); |
32 | | - $tbl_rev = $dbw->tableName( 'revision' ); |
33 | | - |
34 | | - # Get page ID |
35 | | - $this->output( "Searching for \"$name\"..." ); |
36 | | - $title = Title::newFromText( $name ); |
37 | | - if( $title ) { |
38 | | - $id = $title->getArticleID(); |
39 | | - $real = $title->getPrefixedText(); |
40 | | - $isGoodArticle = $title->isContentPage(); |
41 | | - $this->output( "found \"$real\" with ID $id.\n" ); |
42 | | - |
43 | | - # Get corresponding revisions |
44 | | - $this->output( "Searching for revisions..." ); |
45 | | - $res = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_page = $id" ); |
46 | | - while( $row = $dbw->fetchObject( $res ) ) { |
47 | | - $revs[] = $row->rev_id; |
48 | | - } |
49 | | - $count = count( $revs ); |
50 | | - $this->output( "found $count.\n" ); |
51 | | - |
52 | | - # Delete the page record and associated recent changes entries |
53 | | - if( $delete ) { |
54 | | - $this->output( "Deleting page record..." ); |
55 | | - $dbw->query( "DELETE FROM $tbl_pag WHERE page_id = $id" ); |
56 | | - $this->output( "done.\n" ); |
57 | | - $this->output( "Cleaning up recent changes..." ); |
58 | | - $dbw->query( "DELETE FROM $tbl_rec WHERE rc_cur_id = $id" ); |
59 | | - $this->output( "done.\n" ); |
60 | | - } |
61 | | - |
62 | | - $dbw->commit(); |
63 | | - |
64 | | - # Delete revisions as appropriate |
65 | | - if( $delete && $count ) { |
66 | | - $this->output( "Deleting revisions..." ); |
67 | | - $this->deleteRevisions( $revs ); |
68 | | - $this->output( "done.\n" ); |
69 | | - $this->purgeRedundantText( true ); |
70 | | - } |
71 | | - |
72 | | - # Update stats as appropriate |
73 | | - if ( $delete ) { |
74 | | - $this->output( "Updating site stats..." ); |
75 | | - $ga = $isGoodArticle ? -1 : 0; // if it was good, decrement that too |
76 | | - $stats = new SiteStatsUpdate( 0, -$count, $ga, -1 ); |
77 | | - $stats->doUpdate(); |
78 | | - $this->output( "done.\n" ); |
79 | | - } |
80 | | - } else { |
81 | | - $this->output( "not found in database.\n" ); |
82 | | - $dbw->commit(); |
83 | | - } |
84 | | - } |
85 | | - |
86 | | - public function deleteRevisions( $ids ) { |
87 | | - $dbw = wfGetDB( DB_MASTER ); |
88 | | - $dbw->begin(); |
89 | | - |
90 | | - $tbl_rev = $dbw->tableName( 'revision' ); |
91 | | - |
92 | | - $set = implode( ', ', $ids ); |
93 | | - $dbw->query( "DELETE FROM $tbl_rev WHERE rev_id IN ( $set )" ); |
94 | | - |
95 | | - $dbw->commit(); |
96 | | - } |
| 24 | +/** Show script usage information */ |
| 25 | +function ShowUsage() { |
| 26 | + echo( "Remove a page record from the database.\n\n" ); |
| 27 | + echo( "Usage: php nukePage.php <title>\n\n" ); |
| 28 | + echo( " <title> : Page title; spaces escaped with underscores\n\n" ); |
97 | 29 | } |
98 | 30 | |
99 | | -$maintClass = "NukePage"; |
100 | | -require_once( DO_MAINTENANCE ); |
\ No newline at end of file |
Index: trunk/phase3/maintenance/updateArticleCount.php |
— | — | @@ -3,84 +3,38 @@ |
4 | 4 | * Maintenance script to provide a better count of the number of articles |
5 | 5 | * and update the site statistics table, if desired |
6 | 6 | * |
| 7 | + * @file |
7 | 8 | * @ingroup Maintenance |
8 | 9 | * @author Rob Church <robchur@gmail.com> |
9 | 10 | */ |
10 | 11 | |
11 | | -require_once( "Maintenance.php" ); |
| 12 | +$options = array( 'update', 'help' ); |
| 13 | +require_once( 'commandLine.inc' ); |
| 14 | +require_once( 'updateArticleCount.inc' ); |
| 15 | +echo( "Update Article Count\n\n" ); |
12 | 16 | |
13 | | -class UpdateArticleCount extends Maintenance { |
| 17 | +if( isset( $options['help'] ) && $options['help'] ) { |
| 18 | + echo( "Usage: php updateArticleCount.php [--update]\n\n" ); |
| 19 | + echo( "--update : Update site statistics table\n" ); |
| 20 | + exit( 0 ); |
| 21 | +} |
14 | 22 | |
15 | | - // Content namespaces |
16 | | - private $namespaces; |
| 23 | +echo( "Counting articles..." ); |
| 24 | +$counter = new ArticleCounter(); |
| 25 | +$result = $counter->count(); |
17 | 26 | |
18 | | - public function __construct() { |
19 | | - global $wgContentNamespaces; |
20 | | - parent::__construct(); |
21 | | - $this->mDescription = "Count of the number of articles and update the site statistics table"; |
22 | | - $this->addParam( 'update', 'Update the site_stats table with the new count' ); |
23 | | - $this->namespaces = $wgContentNamespaces; |
| 27 | +if( $result !== false ) { |
| 28 | + echo( "found {$result}.\n" ); |
| 29 | + if( isset( $options['update'] ) && $options['update'] ) { |
| 30 | + echo( "Updating site statistics table... " ); |
| 31 | + $dbw = wfGetDB( DB_MASTER ); |
| 32 | + $dbw->update( 'site_stats', array( 'ss_good_articles' => $result ), array( 'ss_row_id' => 1 ), __METHOD__ ); |
| 33 | + echo( "done.\n" ); |
| 34 | + } else { |
| 35 | + echo( "To update the site statistics table, run the script with the --update option.\n" ); |
24 | 36 | } |
25 | | - |
26 | | - public function execute() { |
27 | | - $this->output( "Counting articles..." ); |
28 | | - $result = $this->count(); |
29 | | - |
30 | | - if( $result !== false ) { |
31 | | - $this->output( "found {$result}.\n" ); |
32 | | - if( isset( $options['update'] ) && $options['update'] ) { |
33 | | - $this->output( "Updating site statistics table... " ); |
34 | | - $dbw = wfGetDB( DB_MASTER ); |
35 | | - $dbw->update( 'site_stats', array( 'ss_good_articles' => $result ), array( 'ss_row_id' => 1 ), __METHOD__ ); |
36 | | - $this->output( "done.\n" ); |
37 | | - } else { |
38 | | - $this->output( "To update the site statistics table, run the script with the --update option.\n" ); |
39 | | - } |
40 | | - } else { |
41 | | - $this->output( "failed.\n" ); |
42 | | - } |
43 | | - } |
44 | | - |
45 | | - /** |
46 | | - * Produce a comma-delimited set of namespaces |
47 | | - * Includes paranoia |
48 | | - * |
49 | | - * @return string |
50 | | - */ |
51 | | - private function makeNsSet() { |
52 | | - foreach( $this->namespaces as $namespace ) |
53 | | - $namespaces[] = intval( $namespace ); |
54 | | - return implode( ', ', $namespaces ); |
55 | | - } |
56 | | - |
57 | | - /** |
58 | | - * Produce SQL for the query |
59 | | - * |
60 | | - * @param $dbr Database handle |
61 | | - * @return string |
62 | | - */ |
63 | | - private function makeSql( $dbr ) { |
64 | | - list( $page, $pagelinks ) = $dbr->tableNamesN( 'page', 'pagelinks' ); |
65 | | - $nsset = $this->makeNsSet(); |
66 | | - return "SELECT COUNT(DISTINCT page_namespace, page_title) AS pagecount " . |
67 | | - "FROM $page, $pagelinks " . |
68 | | - "WHERE pl_from=page_id and page_namespace IN ( $nsset ) " . |
69 | | - "AND page_is_redirect = 0 AND page_len > 0"; |
70 | | - } |
71 | | - |
72 | | - /** |
73 | | - * Count the number of valid content pages in the wiki |
74 | | - * |
75 | | - * @return mixed Integer, or false if there's a problem |
76 | | - */ |
77 | | - private function count() { |
78 | | - $dbr = wfGetDB( DB_SLAVE ); |
79 | | - $res = $dbr->query( $this->makeSql( $dbr ), __METHOD__ ); |
80 | | - $row = $dbr->fetchObject( $res ); |
81 | | - $dbr->freeResult( $res ); |
82 | | - return $row->pagecount; |
83 | | - } |
| 37 | +} else { |
| 38 | + echo( "failed.\n" ); |
84 | 39 | } |
| 40 | +echo( "\n" ); |
85 | 41 | |
86 | | -$maintClass = "UpdateArticleCount"; |
87 | | -require_once( DO_MAINTENANCE ); |
Index: trunk/phase3/maintenance/checkUsernames.php |
— | — | @@ -7,33 +7,36 @@ |
8 | 8 | * @ingroup Maintenance |
9 | 9 | */ |
10 | 10 | |
| 11 | +error_reporting(E_ALL ^ E_NOTICE); |
| 12 | +require_once 'commandLine.inc'; |
11 | 13 | |
12 | | -require_once( "Maintenance.php" ); |
| 14 | +class checkUsernames { |
| 15 | + var $stderr, $log; |
13 | 16 | |
14 | | -class CheckUsernames extends Maintenance { |
15 | | - |
16 | | - public function __construct() { |
17 | | - parent::__construct(); |
18 | | - $this->mDescription = "Verify that database usernames are actually valid"; |
| 17 | + function checkUsernames() { |
| 18 | + $this->stderr = fopen( 'php://stderr', 'wt' ); |
19 | 19 | } |
| 20 | + function main() { |
| 21 | + $fname = 'checkUsernames::main'; |
20 | 22 | |
21 | | - function execute() { |
22 | 23 | $dbr = wfGetDB( DB_SLAVE ); |
23 | 24 | |
24 | 25 | $res = $dbr->select( 'user', |
25 | 26 | array( 'user_id', 'user_name' ), |
26 | 27 | null, |
27 | | - __METHOD__ |
| 28 | + $fname |
28 | 29 | ); |
29 | 30 | |
30 | 31 | while ( $row = $dbr->fetchObject( $res ) ) { |
31 | 32 | if ( ! User::isValidUserName( $row->user_name ) ) { |
32 | | - $this->error( sprintf( "%s: %6d: '%s'\n", wfWikiID(), $row->user_id, $row->user_name ) ); |
| 33 | + $out = sprintf( "%s: %6d: '%s'\n", wfWikiID(), $row->user_id, $row->user_name ); |
| 34 | + fwrite( $this->stderr, $out ); |
33 | 35 | wfDebugLog( 'checkUsernames', $out ); |
34 | 36 | } |
35 | 37 | } |
36 | 38 | } |
37 | 39 | } |
38 | 40 | |
39 | | -$maintClass = "CheckUsernames"; |
40 | | -require_once( "doMaintenance.php" ); |
| 41 | +$cun = new checkUsernames(); |
| 42 | +$cun->main(); |
| 43 | + |
Index: trunk/phase3/maintenance/checkImages.php |
— | — | @@ -1,63 +1,51 @@ |
2 | 2 | <?php |
3 | | -/** |
4 | | - * Check images to see if they exist, are readable, etc etc |
5 | | - */ |
6 | | -require_once( "Maintenance.php" ); |
7 | 3 | |
8 | | -class CheckImages extends Maintenance { |
| 4 | +require( 'commandLine.inc' ); |
9 | 5 | |
10 | | - public function __construct() { |
11 | | - parent::__construct(); |
12 | | - $this->mDescription = "Check images to see if they exist, are readable, etc"; |
13 | | - } |
14 | | - |
15 | | - public function execute() { |
16 | | - $batchSize = 1000; |
17 | | - $start = ''; |
18 | | - $dbr = wfGetDB( DB_SLAVE ); |
| 6 | +$batchSize = 1000; |
| 7 | +$start = ''; |
| 8 | +$dbr = wfGetDB( DB_SLAVE ); |
| 9 | +$localRepo = RepoGroup::singleton()->getLocalRepo(); |
19 | 10 | |
20 | | - $numImages = 0; |
21 | | - $numGood = 0; |
22 | | - |
23 | | - do { |
24 | | - $res = $dbr->select( 'image', '*', array( 'img_name > ' . $dbr->addQuotes( $start ) ), |
25 | | - __METHOD__, array( 'LIMIT' => $batchSize ) ); |
26 | | - foreach ( $res as $row ) { |
27 | | - $numImages++; |
28 | | - $start = $row->img_name; |
29 | | - $file = RepoGroup::singleton()->getLocalRepo()->newFileFromRow( $row ); |
30 | | - $path = $file->getPath(); |
31 | | - if ( !$path ) { |
32 | | - $this->output( "{$row->img_name}: not locally accessible\n"; |
33 | | - continue; |
34 | | - } |
35 | | - $stat = @stat( $file->getPath() ); |
36 | | - if ( !$stat ) { |
37 | | - $this->output( "{$row->img_name}: missing\n" ); |
38 | | - continue; |
39 | | - } |
40 | | - |
41 | | - if ( $stat['mode'] & 040000 ) { |
42 | | - $this->output( "{$row->img_name}: is a directory\n" ); |
43 | | - continue; |
44 | | - } |
45 | | - |
46 | | - if ( $stat['size'] == 0 && $row->img_size != 0 ) { |
47 | | - $this->output( "{$row->img_name}: truncated, was {$row->img_size}\n" ); |
48 | | - continue; |
49 | | - } |
50 | | - |
51 | | - if ( $stat['size'] != $row->img_size ) { |
52 | | - $this->output( "{$row->img_name}: size mismatch DB={$row->img_size}, actual={$stat['size']}\n" ); |
53 | | - continue; |
54 | | - } |
55 | | - |
56 | | - $numGood++; |
57 | | - } |
58 | | - |
59 | | - } while ( $res->numRows() ); |
60 | | - |
61 | | - $this->output( "Good images: $numGood/$numImages\n" ); |
| 11 | +$numImages = 0; |
| 12 | +$numGood = 0; |
| 13 | + |
| 14 | +do { |
| 15 | + $res = $dbr->select( 'image', '*', array( 'img_name > ' . $dbr->addQuotes( $start ) ), |
| 16 | + 'checkImages.php', array( 'LIMIT' => $batchSize ) ); |
| 17 | + foreach ( $res as $row ) { |
| 18 | + $numImages++; |
| 19 | + $start = $row->img_name; |
| 20 | + $file = $localRepo->newFileFromRow( $row ); |
| 21 | + $path = $file->getPath(); |
| 22 | + if ( !$path ) { |
| 23 | + echo "{$row->img_name}: not locally accessible\n"; |
| 24 | + continue; |
| 25 | + } |
| 26 | + $stat = @stat( $file->getPath() ); |
| 27 | + if ( !$stat ) { |
| 28 | + echo "{$row->img_name}: missing\n"; |
| 29 | + continue; |
| 30 | + } |
| 31 | + |
| 32 | + if ( $stat['mode'] & 040000 ) { |
| 33 | + echo "{$row->img_name}: is a directory\n"; |
| 34 | + continue; |
| 35 | + } |
| 36 | + |
| 37 | + if ( $stat['size'] == 0 && $row->img_size != 0 ) { |
| 38 | + echo "{$row->img_name}: truncated, was {$row->img_size}\n"; |
| 39 | + continue; |
| 40 | + } |
| 41 | + |
| 42 | + if ( $stat['size'] != $row->img_size ) { |
| 43 | + echo "{$row->img_name}: size mismatch DB={$row->img_size}, actual={$stat['size']}\n"; |
| 44 | + continue; |
| 45 | + } |
| 46 | + |
| 47 | + $numGood++; |
62 | 48 | } |
63 | | -} |
64 | 49 | |
| 50 | +} while ( $res->numRows() ); |
| 51 | + |
| 52 | +echo "Good images: $numGood/$numImages\n"; |
Index: trunk/phase3/maintenance/clear_stats.php |
— | — | @@ -6,34 +6,33 @@ |
7 | 7 | * @ingroup Maintenance |
8 | 8 | */ |
9 | 9 | |
10 | | -require_once( 'Maintenance.php' ); |
| 10 | +require_once('commandLine.inc'); |
11 | 11 | |
12 | | -class clear_stats extends Maintenance { |
| 12 | +foreach ( $wgLocalDatabases as $db ) { |
| 13 | + noisyDelete("$db:stats:request_with_session"); |
| 14 | + noisyDelete("$db:stats:request_without_session"); |
| 15 | + noisyDelete("$db:stats:pcache_hit"); |
| 16 | + noisyDelete("$db:stats:pcache_miss_invalid"); |
| 17 | + noisyDelete("$db:stats:pcache_miss_expired"); |
| 18 | + noisyDelete("$db:stats:pcache_miss_absent"); |
| 19 | + noisyDelete("$db:stats:pcache_miss_stub"); |
| 20 | + noisyDelete("$db:stats:image_cache_hit"); |
| 21 | + noisyDelete("$db:stats:image_cache_miss"); |
| 22 | + noisyDelete("$db:stats:image_cache_update"); |
| 23 | + noisyDelete("$db:stats:diff_cache_hit"); |
| 24 | + noisyDelete("$db:stats:diff_cache_miss"); |
| 25 | + noisyDelete("$db:stats:diff_uncacheable"); |
| 26 | +} |
13 | 27 | |
14 | | - public function __construct() { |
15 | | - parent::__construct(); |
16 | | - $this->mDescription = "Remove all statistics tracking from memcached"; |
17 | | - } |
18 | | - |
19 | | - public function execute() { |
20 | | - global $wgLocalDatabases, $wgMemc; |
21 | | - foreach ( $wgLocalDatabases as $db ) { |
22 | | - $wgMemc->delete("$db:stats:request_with_session"); |
23 | | - $wgMemc->delete("$db:stats:request_without_session"); |
24 | | - $wgMemc->delete("$db:stats:pcache_hit"); |
25 | | - $wgMemc->delete("$db:stats:pcache_miss_invalid"); |
26 | | - $wgMemc->delete("$db:stats:pcache_miss_expired"); |
27 | | - $wgMemc->delete("$db:stats:pcache_miss_absent"); |
28 | | - $wgMemc->delete("$db:stats:pcache_miss_stub"); |
29 | | - $wgMemc->delete("$db:stats:image_cache_hit"); |
30 | | - $wgMemc->delete("$db:stats:image_cache_miss"); |
31 | | - $wgMemc->delete("$db:stats:image_cache_update"); |
32 | | - $wgMemc->delete("$db:stats:diff_cache_hit"); |
33 | | - $wgMemc->delete("$db:stats:diff_cache_miss"); |
34 | | - $wgMemc->delete("$db:stats:diff_uncacheable"); |
35 | | - } |
36 | | - } |
| 28 | +function noisyDelete( $key ) { |
| 29 | + global $wgMemc; |
| 30 | + /* |
| 31 | + print "$key "; |
| 32 | + if ( $wgMemc->delete($key) ) { |
| 33 | + print "deleted\n"; |
| 34 | + } else { |
| 35 | + print "FAILED\n"; |
| 36 | + }*/ |
| 37 | + $wgMemc->delete($key); |
37 | 38 | } |
38 | 39 | |
39 | | -$maintClass = "clear_stats"; |
40 | | -require_once( DO_MAINTENANCE ); |
Index: trunk/phase3/maintenance/updaters.inc |
— | — | @@ -1038,7 +1038,10 @@ |
1039 | 1039 | wfOut( "ok.\n" ); |
1040 | 1040 | return; |
1041 | 1041 | } |
1042 | | - SiteStats::init( false ); |
| 1042 | + |
| 1043 | + global $IP; |
| 1044 | + require_once "$IP/maintenance/initStats.inc"; |
| 1045 | + wfInitStats(); |
1043 | 1046 | } |
1044 | 1047 | |
1045 | 1048 | function do_active_users_init() { |
Index: trunk/phase3/maintenance/populateLogSearch.php |
— | — | @@ -9,88 +9,13 @@ |
10 | 10 | * @ingroup Maintenance |
11 | 11 | */ |
12 | 12 | |
13 | | -require_once( "Maintenance.php" ); |
14 | | - |
15 | | -class PopulateLogSearch extends Maintenance { |
16 | | - |
17 | | - const LOG_SEARCH_BATCH_SIZE = 100; |
18 | | - |
19 | | - public function __construct() { |
20 | | - parent::__construct(); |
21 | | - $this->mDescription = "Migrate log params to new table and index for searching"; |
22 | | - } |
23 | | - |
24 | | - public function execute() { |
25 | | - $db = wfGetDB( DB_MASTER ); |
26 | | - if ( !$db->tableExists( 'log_search' ) ) { |
27 | | - $this->error( "log_search does not exist\n", true ); |
28 | | - } |
29 | | - $start = $db->selectField( 'logging', 'MIN(log_id)', false, __FUNCTION__ ); |
30 | | - if( !$start ) { |
31 | | - $this->output( "Nothing to do.\n" ); |
32 | | - return true; |
33 | | - } |
34 | | - $end = $db->selectField( 'logging', 'MAX(log_id)', false, __FUNCTION__ ); |
| 13 | +require_once 'commandLine.inc'; |
| 14 | +require_once 'populateLogSearch.inc'; |
35 | 15 | |
36 | | - # Do remaining chunk |
37 | | - $end += self::LOG_SEARCH_BATCH_SIZE - 1; |
38 | | - $blockStart = $start; |
39 | | - $blockEnd = $start + self::LOG_SEARCH_BATCH_SIZE - 1; |
40 | | - while( $blockEnd <= $end ) { |
41 | | - $this->output( "...doing log_id from $blockStart to $blockEnd\n" ); |
42 | | - $cond = "log_id BETWEEN $blockStart AND $blockEnd"; |
43 | | - $res = $db->select( 'logging', '*', $cond, __FUNCTION__ ); |
44 | | - $batch = array(); |
45 | | - while( $row = $db->fetchObject( $res ) ) { |
46 | | - // RevisionDelete logs - revisions |
47 | | - if( LogEventsList::typeAction( $row, array('delete','suppress'), 'revision' ) ) { |
48 | | - $params = LogPage::extractParams( $row->log_params ); |
49 | | - // Param format: <urlparam> <item CSV> [<ofield> <nfield>] |
50 | | - if( count($params) >= 2 ) { |
51 | | - $field = RevisionDeleter::getRelationType($params[0]); |
52 | | - // B/C, the params may start with a title key |
53 | | - if( $field == null ) { |
54 | | - array_shift($params); |
55 | | - $field = RevisionDeleter::getRelationType($params[0]); |
56 | | - } |
57 | | - if( $field == null ) { |
58 | | - $this->output( "Invalid param type for $row->log_id\n" ); |
59 | | - continue; // skip this row |
60 | | - } |
61 | | - $items = explode(',',$params[1]); |
62 | | - $log = new LogPage( $row->log_type ); |
63 | | - $log->addRelations( $field, $items, $row->log_id ); |
64 | | - } |
65 | | - // RevisionDelete logs - log events |
66 | | - } else if( LogEventsList::typeAction( $row, array('delete','suppress'), 'event' ) ) { |
67 | | - $params = LogPage::extractParams( $row->log_params ); |
68 | | - // Param format: <item CSV> [<ofield> <nfield>] |
69 | | - if( count($params) >= 1 ) { |
70 | | - $items = explode(',',$params[0]); |
71 | | - $log = new LogPage( $row->log_type ); |
72 | | - $log->addRelations( 'log_id', $items, $row->log_id ); |
73 | | - } |
74 | | - } |
75 | | - } |
76 | | - $blockStart += self::LOG_SEARCH_BATCH_SIZE; |
77 | | - $blockEnd += self::LOG_SEARCH_BATCH_SIZE; |
78 | | - wfWaitForSlaves( 5 ); |
79 | | - } |
80 | | - if( $db->insert( |
81 | | - 'updatelog', |
82 | | - array( 'ul_key' => 'populate log_search' ), |
83 | | - __FUNCTION__, |
84 | | - 'IGNORE' |
85 | | - ) |
86 | | - ) { |
87 | | - $this->output( "log_search population complete.\n" ); |
88 | | - return true; |
89 | | - } else { |
90 | | - $this->output( "Could not insert log_search population row.\n" ); |
91 | | - return false; |
92 | | - } |
93 | | - } |
| 16 | +$db =& wfGetDB( DB_MASTER ); |
| 17 | +if ( !$db->tableExists( 'log_search' ) ) { |
| 18 | + echo "log_search does not exist\n"; |
| 19 | + exit( 1 ); |
94 | 20 | } |
95 | 21 | |
96 | | -$maintClass = "PopulateLogSearch"; |
97 | | -require_once( DO_MAINTENANCE ); |
| 22 | +migrate_log_params( $db ); |
Index: trunk/phase3/maintenance/deleteRevision.php |
— | — | @@ -6,52 +6,42 @@ |
7 | 7 | * @ingroup Maintenance |
8 | 8 | */ |
9 | 9 | |
10 | | -require_once( "Maintenance.php" ); |
| 10 | +require_once( 'commandLine.inc' ); |
11 | 11 | |
12 | | -class DeleteRevision extends Maintenance { |
13 | | - |
14 | | - public function __construct() { |
15 | | - parent::__construct(); |
16 | | - $this->mDescription = "Delete one or more revisions by moving them to the archive table"; |
17 | | - } |
18 | | - |
19 | | - public function execute() { |
20 | | - if( count( $this->mArgs ) == 0 ) { |
21 | | - $this->error( "No revisions specified", true ); |
22 | | - } |
| 12 | +$dbw = wfGetDB( DB_MASTER ); |
23 | 13 | |
24 | | - $this->output( "Deleting revision(s) " . implode( ',', $this->mArgs ) . |
25 | | - " from " . wfWikiID() . "...\n" ); |
26 | | - $dbw = wfGetDB( DB_MASTER ); |
27 | | - |
28 | | - $affected = 0; |
29 | | - foreach ( $this->mArgs as $revID ) { |
30 | | - $dbw->insertSelect( 'archive', array( 'page', 'revision' ), |
31 | | - array( |
32 | | - 'ar_namespace' => 'page_namespace', |
33 | | - 'ar_title' => 'page_title', |
34 | | - 'ar_comment' => 'rev_comment', |
35 | | - 'ar_user' => 'rev_user', |
36 | | - 'ar_user_text' => 'rev_user_text', |
37 | | - 'ar_timestamp' => 'rev_timestamp', |
38 | | - 'ar_minor_edit' => 'rev_minor_edit', |
39 | | - 'ar_rev_id' => 'rev_id', |
40 | | - 'ar_text_id' => 'rev_text_id', |
41 | | - ), array( |
42 | | - 'rev_id' => $revID, |
43 | | - 'page_id = rev_page' |
44 | | - ), __METHOD__ |
45 | | - ); |
46 | | - if ( !$dbw->affectedRows() ) { |
47 | | - $this->output( "Revision $revID not found\n" ); |
48 | | - } else { |
49 | | - $affected += $dbw->affectedRows(); |
50 | | - $dbw->delete( 'revision', array( 'rev_id' => $revID ) ); |
51 | | - } |
52 | | - } |
53 | | - $this->output( "Deleted $affected revisions\n" ); |
| 14 | +if ( count( $args ) == 0 ) { |
| 15 | + echo "Usage: php deleteRevision.php <revid> [<revid> ...]\n"; |
| 16 | + exit(1); |
| 17 | +} |
| 18 | + |
| 19 | +echo "Deleting revision(s) " . implode( ',', $args ) . " from ".wfWikiID()."...\n"; |
| 20 | + |
| 21 | +$affected = 0; |
| 22 | +foreach ( $args as $revID ) { |
| 23 | + $dbw->insertSelect( 'archive', array( 'page', 'revision' ), |
| 24 | + array( |
| 25 | + 'ar_namespace' => 'page_namespace', |
| 26 | + 'ar_title' => 'page_title', |
| 27 | + 'ar_comment' => 'rev_comment', |
| 28 | + 'ar_user' => 'rev_user', |
| 29 | + 'ar_user_text' => 'rev_user_text', |
| 30 | + 'ar_timestamp' => 'rev_timestamp', |
| 31 | + 'ar_minor_edit' => 'rev_minor_edit', |
| 32 | + 'ar_rev_id' => 'rev_id', |
| 33 | + 'ar_text_id' => 'rev_text_id', |
| 34 | + ), array( |
| 35 | + 'rev_id' => $revID, |
| 36 | + 'page_id = rev_page' |
| 37 | + ), $fname |
| 38 | + ); |
| 39 | + if ( !$dbw->affectedRows() ) { |
| 40 | + echo "Revision $revID not found\n"; |
| 41 | + } else { |
| 42 | + $affected += $dbw->affectedRows(); |
| 43 | + $dbw->delete( 'revision', array( 'rev_id' => $revID ) ); |
54 | 44 | } |
55 | 45 | } |
56 | 46 | |
57 | | -$maintClass = "DeleteRevision"; |
58 | | -require_once( DO_MAINTENANCE ); |
| 47 | +print "Deleted $affected revisions\n"; |
| 48 | + |
Index: trunk/phase3/maintenance/checkAutoLoader.php |
— | — | @@ -1,40 +1,29 @@ |
2 | 2 | <?php |
3 | | -/** |
4 | | - * Check the autoloader |
5 | | - */ |
| 3 | +if ( php_sapi_name() != 'cli' ) exit; |
6 | 4 | |
7 | | -require_once( "Maintenance.php" ); |
| 5 | +$IP = dirname(__FILE__) .'/..'; |
| 6 | +require( "$IP/includes/AutoLoader.php" ); |
| 7 | +$files = array_unique( $wgAutoloadLocalClasses ); |
8 | 8 | |
9 | | -class CheckAutoLoader extends Maintenance { |
10 | | - public function __construct() { |
11 | | - parent::__construct(); |
12 | | - $this->mDescription = "AutoLoader sanity checks"; |
| 9 | +foreach ( $files as $file ) { |
| 10 | + if( function_exists( 'parsekit_compile_file' ) ){ |
| 11 | + $parseInfo = parsekit_compile_file( "$IP/$file" ); |
| 12 | + $classes = array_keys( $parseInfo['class_table'] ); |
| 13 | + } else { |
| 14 | + $contents = file_get_contents( "$IP/$file" ); |
| 15 | + $m = array(); |
| 16 | + preg_match_all( '/\n\s*class\s+([a-zA-Z0-9_]+)/', $contents, $m, PREG_PATTERN_ORDER ); |
| 17 | + $classes = $m[1]; |
13 | 18 | } |
14 | | - public function execute() { |
15 | | - global $wgAutoloadLocalClasses, $IP; |
16 | | - $files = array_unique( $wgAutoloadLocalClasses ); |
17 | | - |
18 | | - foreach( $files as $file ) { |
19 | | - if( function_exists( 'parsekit_compile_file' ) ){ |
20 | | - $parseInfo = parsekit_compile_file( "$IP/$file" ); |
21 | | - $classes = array_keys( $parseInfo['class_table'] ); |
22 | | - } else { |
23 | | - $contents = file_get_contents( "$IP/$file" ); |
24 | | - $m = array(); |
25 | | - preg_match_all( '/\n\s*class\s+([a-zA-Z0-9_]+)/', $contents, $m, PREG_PATTERN_ORDER ); |
26 | | - $classes = $m[1]; |
27 | | - } |
28 | | - foreach ( $classes as $class ) { |
29 | | - if ( !isset( $wgAutoloadLocalClasses[$class] ) ) { |
30 | | - //printf( "%-50s Unlisted, in %s\n", $class, $file ); |
31 | | - $this->output( "\t'$class' => '$file',\n" ); |
32 | | - } elseif ( $wgAutoloadLocalClasses[$class] !== $file ) { |
33 | | - $this->output( "$class: Wrong file: found in $file, listed in " . $wgAutoloadLocalClasses[$class] . "\n" ); |
34 | | - } |
35 | | - } |
| 19 | + foreach ( $classes as $class ) { |
| 20 | + if ( !isset( $wgAutoloadLocalClasses[$class] ) ) { |
| 21 | + //printf( "%-50s Unlisted, in %s\n", $class, $file ); |
| 22 | + echo " '$class' => '$file',\n"; |
| 23 | + } elseif ( $wgAutoloadLocalClasses[$class] !== $file ) { |
| 24 | + echo "$class: Wrong file: found in $file, listed in " . $wgAutoloadLocalClasses[$class] . "\n"; |
36 | 25 | } |
37 | 26 | } |
| 27 | + |
38 | 28 | } |
39 | 29 | |
40 | | -$maintClass = "CheckAutoLoader"; |
41 | | -require_once( DO_MAINTENANCE ); |
| 30 | + |
Index: trunk/phase3/maintenance/clear_interwiki_cache.php |
— | — | @@ -3,36 +3,25 @@ |
4 | 4 | * This script is used to clear the interwiki links for ALL languages in |
5 | 5 | * memcached. |
6 | 6 | * |
| 7 | + * @file |
7 | 8 | * @ingroup Maintenance |
8 | 9 | */ |
9 | 10 | |
10 | | -require_once( "Maintenance.php" ); |
| 11 | +/** */ |
| 12 | +require_once('commandLine.inc'); |
11 | 13 | |
12 | | -class ClearInterwikiCache extends Maintenance { |
| 14 | +$dbr = wfGetDB( DB_SLAVE ); |
| 15 | +$res = $dbr->select( 'interwiki', array( 'iw_prefix' ), false ); |
| 16 | +$prefixes = array(); |
| 17 | +while ( $row = $dbr->fetchObject( $res ) ) { |
| 18 | + $prefixes[] = $row->iw_prefix; |
| 19 | +} |
13 | 20 | |
14 | | - public function __construct() { |
15 | | - parent::__construct(); |
16 | | - $this->mDescription = "Clear all interwiki links for all languages from the cache"; |
| 21 | +foreach ( $wgLocalDatabases as $db ) { |
| 22 | + print "$db "; |
| 23 | + foreach ( $prefixes as $prefix ) { |
| 24 | + $wgMemc->delete("$db:interwiki:$prefix"); |
17 | 25 | } |
18 | | - |
19 | | - public function execute() { |
20 | | - global $wgLocalDatabases; |
21 | | - $dbr = wfGetDB( DB_SLAVE ); |
22 | | - $res = $dbr->select( 'interwiki', array( 'iw_prefix' ), false ); |
23 | | - $prefixes = array(); |
24 | | - while ( $row = $dbr->fetchObject( $res ) ) { |
25 | | - $prefixes[] = $row->iw_prefix; |
26 | | - } |
27 | | - |
28 | | - foreach ( $wgLocalDatabases as $db ) { |
29 | | - $this->output( "$db..." ); |
30 | | - foreach ( $prefixes as $prefix ) { |
31 | | - $wgMemc->delete("$db:interwiki:$prefix"); |
32 | | - } |
33 | | - $this->output( "done\n" ); |
34 | | - } |
35 | | - } |
36 | 26 | } |
| 27 | +print "\n"; |
37 | 28 | |
38 | | -$maintClass = "ClearInterwikiCache"; |
39 | | -require_once( DO_MAINTENANCE ); |
Index: trunk/phase3/maintenance/fetchText.php |
— | — | @@ -6,48 +6,34 @@ |
7 | 7 | * @ingroup Maintenance |
8 | 8 | */ |
9 | 9 | |
10 | | -require_once( "Maintenance.php" ); |
| 10 | +require "commandLine.inc"; |
11 | 11 | |
12 | | -class FetchText extends Maintenance { |
13 | | - public function __construct() { |
14 | | - parent::__construct(); |
15 | | - $this->mDescription = "Fetch the revision text from an old_id"; |
| 12 | +$db = wfGetDB( DB_SLAVE ); |
| 13 | +$stdin = fopen( "php://stdin", "rt" ); |
| 14 | +while( !feof( $stdin ) ) { |
| 15 | + $line = fgets( $stdin ); |
| 16 | + if( $line === false ) { |
| 17 | + // We appear to have lost contact... |
| 18 | + break; |
16 | 19 | } |
| 20 | + $textId = intval( $line ); |
| 21 | + $text = doGetText( $db, $textId ); |
| 22 | + echo strlen( $text ) . "\n"; |
| 23 | + echo $text; |
| 24 | +} |
17 | 25 | |
18 | | - public function execute() { |
19 | | - $db = wfGetDB( DB_SLAVE ); |
20 | | - $stdin = $this->getStdin(); |
21 | | - while( !feof( $stdin ) ) { |
22 | | - $line = fgets( $stdin ); |
23 | | - if( $line === false ) { |
24 | | - // We appear to have lost contact... |
25 | | - break; |
26 | | - } |
27 | | - $textId = intval( $line ); |
28 | | - $text = $this->doGetText( $db, $textId ); |
29 | | - $this->output( strlen( $text ) . "\n". $text ); |
30 | | - } |
| 26 | +/** |
| 27 | + * May throw a database error if, say, the server dies during query. |
| 28 | + */ |
| 29 | +function doGetText( $db, $id ) { |
| 30 | + $id = intval( $id ); |
| 31 | + $row = $db->selectRow( 'text', |
| 32 | + array( 'old_text', 'old_flags' ), |
| 33 | + array( 'old_id' => $id ), |
| 34 | + 'TextPassDumper::getText' ); |
| 35 | + $text = Revision::getRevisionText( $row ); |
| 36 | + if( $text === false ) { |
| 37 | + return false; |
31 | 38 | } |
32 | | - |
33 | | - /** |
34 | | - * May throw a database error if, say, the server dies during query. |
35 | | - * @param $db Database object |
36 | | - * @param $id int The old_id |
37 | | - * @return String |
38 | | - */ |
39 | | - private function doGetText( $db, $id ) { |
40 | | - $id = intval( $id ); |
41 | | - $row = $db->selectRow( 'text', |
42 | | - array( 'old_text', 'old_flags' ), |
43 | | - array( 'old_id' => $id ), |
44 | | - 'TextPassDumper::getText' ); |
45 | | - $text = Revision::getRevisionText( $row ); |
46 | | - if( $text === false ) { |
47 | | - return false; |
48 | | - } |
49 | | - return $text; |
50 | | - } |
| 39 | + return $text; |
51 | 40 | } |
52 | | - |
53 | | -$maintClass = "FetchText"; |
54 | | -require_once( DO_MAINTENANCE ); |
Index: trunk/phase3/maintenance/showStats.php |
— | — | @@ -14,41 +14,35 @@ |
15 | 15 | * @license GNU General Public License 2.0 or later |
16 | 16 | */ |
17 | 17 | |
18 | | -require_once( "Maintenance.php" ); |
| 18 | +require_once( 'commandLine.inc' ); |
19 | 19 | |
20 | | -class ShowStats extends Maintenance { |
21 | | - public function __construct() { |
22 | | - $this->mDescription = "Show the cached statistics"; |
23 | | - } |
24 | | - public function execute() { |
25 | | - $fields = array( |
26 | | - 'ss_total_views' => 'Total views', |
27 | | - 'ss_total_edits' => 'Total edits', |
28 | | - 'ss_good_articles' => 'Number of articles', |
29 | | - 'ss_total_pages' => 'Total pages', |
30 | | - 'ss_users' => 'Number of users', |
31 | | - 'ss_admins' => 'Number of admins', |
32 | | - 'ss_images' => 'Number of images', |
33 | | - ); |
34 | | - |
35 | | - // Get cached stats from slave database |
36 | | - $dbr = wfGetDB( DB_SLAVE ); |
37 | | - $stats = $dbr->selectRow( 'site_stats', '*', '', __METHOD__ ); |
38 | | - |
39 | | - // Get maximum size for each column |
40 | | - $max_length_value = $max_length_desc = 0; |
41 | | - foreach( $fields as $field => $desc ) { |
42 | | - $max_length_value = max( $max_length_value, strlen( $stats->$field ) ); |
43 | | - $max_length_desc = max( $max_length_desc , strlen( $desc )) ; |
44 | | - } |
45 | | - |
46 | | - // Show them |
47 | | - foreach( $fields as $field => $desc ) { |
48 | | - $this->output( sprintf( "%-{$max_length_desc}s: %{$max_length_value}d\n", $desc, $stats->$field ) ); |
49 | | - } |
50 | | - } |
| 20 | +# |
| 21 | +# Configuration |
| 22 | +# |
| 23 | +$fields = array( |
| 24 | + 'ss_total_views' => 'Total views', |
| 25 | + 'ss_total_edits' => 'Total edits', |
| 26 | + 'ss_good_articles' => 'Number of articles', |
| 27 | + 'ss_total_pages' => 'Total pages', |
| 28 | + 'ss_users' => 'Number of users', |
| 29 | + 'ss_admins' => 'Number of admins', |
| 30 | + 'ss_images' => 'Number of images', |
| 31 | +); |
| 32 | + |
| 33 | +// Get cached stats from slave database |
| 34 | +$dbr = wfGetDB( DB_SLAVE ); |
| 35 | +$fname = 'showStats'; |
| 36 | +$stats = $dbr->selectRow( 'site_stats', '*', '' ); |
| 37 | + |
| 38 | +// Get maximum size for each column |
| 39 | +$max_length_value = $max_length_desc = 0; |
| 40 | +foreach( $fields as $field => $desc ) { |
| 41 | + $max_length_value = max( $max_length_value, strlen( $stats->$field ) ); |
| 42 | + $max_length_desc = max( $max_length_desc , strlen( $desc )) ; |
51 | 43 | } |
52 | 44 | |
53 | | -$maintClass = "ShowStats"; |
54 | | -require_once( DO_MAINTENANCE ); |
| 45 | +// Show them |
| 46 | +foreach( $fields as $field => $desc ) { |
| 47 | + printf( "%-{$max_length_desc}s: %{$max_length_value}d\n", $desc, $stats->$field ); |
| 48 | +} |
55 | 49 | |
Index: trunk/phase3/maintenance/populateParentId.php |
— | — | @@ -1,105 +1,18 @@ |
2 | 2 | <?php |
| 3 | + |
3 | 4 | /* |
4 | 5 | * Makes the required database updates for rev_parent_id |
5 | 6 | * to be of any use. It can be used for some simple tracking |
6 | 7 | * and to find new page edits by users. |
7 | 8 | */ |
8 | 9 | |
9 | | -require_once( "Maintenance.php" ); |
10 | | - |
11 | | -class PopulateParentId extends Maintenance { |
12 | | - |
13 | | - // Batch size |
14 | | - const BATCH_SIZE = 200; |
15 | | - |
16 | | - public function __construct() { |
17 | | - parent::__construct(); |
18 | | - $this->mDescription = "Populates rev_parent_id"; |
19 | | - } |
20 | | - |
21 | | - public function execute() { |
22 | | - $db = wfGetDB( DB_MASTER ); |
23 | | - if ( !$db->tableExists( 'revision' ) ) { |
24 | | - $this->error( "revision table does not exist\n", true ); |
25 | | - } |
26 | | - $this->output( "Populating rev_parent_id column\n" ); |
27 | | - $start = $db->selectField( 'revision', 'MIN(rev_id)', false, __FUNCTION__ ); |
28 | | - $end = $db->selectField( 'revision', 'MAX(rev_id)', false, __FUNCTION__ ); |
29 | | - if( is_null( $start ) || is_null( $end ) ){ |
30 | | - $this->output( "...revision table seems to be empty.\n" ); |
31 | | - $db->insert( 'updatelog', |
32 | | - array( 'ul_key' => 'populate rev_parent_id' ), |
33 | | - __FUNCTION__, |
34 | | - 'IGNORE' ); |
35 | | - return; |
36 | | - } |
37 | | - # Do remaining chunk |
38 | | - $end += self::BATCH_SIZE - 1; |
39 | | - $blockStart = intval( $start ); |
40 | | - $blockEnd = intval( $start ) + self::BATCH_SIZE - 1; |
41 | | - $count = 0; |
42 | | - $changed = 0; |
43 | | - while( $blockEnd <= $end ) { |
44 | | - $this->output( "...doing rev_id from $blockStart to $blockEnd\n" ); |
45 | | - $cond = "rev_id BETWEEN $blockStart AND $blockEnd"; |
46 | | - $res = $db->select( 'revision', |
47 | | - array('rev_id','rev_page','rev_timestamp','rev_parent_id'), |
48 | | - $cond, __FUNCTION__ ); |
49 | | - # Go through and update rev_parent_id from these rows. |
50 | | - # Assume that the previous revision of the title was |
51 | | - # the original previous revision of the title when the |
52 | | - # edit was made... |
53 | | - foreach( $res as $row ) { |
54 | | - # First, check rows with the same timestamp other than this one |
55 | | - # with a smaller rev ID. The highest ID "wins". This avoids loops |
56 | | - # as timestamp can only decrease and never loops with IDs (from parent to parent) |
57 | | - $previousID = $db->selectField( 'revision', 'rev_id', |
58 | | - array( 'rev_page' => $row->rev_page, 'rev_timestamp' => $row->rev_timestamp, |
59 | | - "rev_id < " . intval( $row->rev_id ) ), |
60 | | - __FUNCTION__, |
61 | | - array( 'ORDER BY' => 'rev_id DESC' ) ); |
62 | | - # If there are none, check the the highest ID with a lower timestamp |
63 | | - if( !$previousID ) { |
64 | | - # Get the highest older timestamp |
65 | | - $lastTimestamp = $db->selectField( 'revision', 'rev_timestamp', |
66 | | - array( 'rev_page' => $row->rev_page, "rev_timestamp < " . $db->addQuotes( $row->rev_timestamp ) ), |
67 | | - __FUNCTION__, |
68 | | - array( 'ORDER BY' => 'rev_timestamp DESC' ) ); |
69 | | - # If there is one, let the highest rev ID win |
70 | | - if( $lastTimestamp ) { |
71 | | - $previousID = $db->selectField( 'revision', 'rev_id', |
72 | | - array( 'rev_page' => $row->rev_page, 'rev_timestamp' => $lastTimestamp ), |
73 | | - __FUNCTION__, |
74 | | - array( 'ORDER BY' => 'rev_id DESC' ) ); |
75 | | - } |
76 | | - } |
77 | | - $previousID = intval($previousID); |
78 | | - if( $previousID != $row->rev_parent_id ) |
79 | | - $changed++; |
80 | | - # Update the row... |
81 | | - $db->update( 'revision', |
82 | | - array( 'rev_parent_id' => $previousID ), |
83 | | - array( 'rev_id' => $row->rev_id ), |
84 | | - __FUNCTION__ ); |
85 | | - $count++; |
86 | | - } |
87 | | - $blockStart += self::BATCH_SIZE - 1; |
88 | | - $blockEnd += self::BATCH_SIZE - 1; |
89 | | - wfWaitForSlaves( 5 ); |
90 | | - } |
91 | | - $logged = $db->insert( 'updatelog', |
92 | | - array( 'ul_key' => 'populate rev_parent_id' ), |
93 | | - __FUNCTION__, |
94 | | - 'IGNORE' ); |
95 | | - if( $logged ) { |
96 | | - $this->output( "rev_parent_id population complete ... {$count} rows [{$changed} changed]\n" ); |
97 | | - return true; |
98 | | - } else { |
99 | | - $this->output( "Could not insert rev_parent_id population row.\n" ); |
100 | | - return false; |
101 | | - } |
102 | | - } |
| 10 | +require_once 'commandLine.inc'; |
| 11 | +require_once 'populateParentId.inc'; |
| 12 | + |
| 13 | +$db =& wfGetDB( DB_MASTER ); |
| 14 | +if ( !$db->tableExists( 'revision' ) ) { |
| 15 | + echo "revision table does not exist\n"; |
| 16 | + exit( 1 ); |
103 | 17 | } |
104 | 18 | |
105 | | -$maintClass = "PopulateParentId"; |
106 | | -require_once( DO_MAINTENANCE ); |
| 19 | +populate_rev_parent_id( $db ); |
Index: trunk/phase3/maintenance/createAndPromote.php |
— | — | @@ -8,53 +8,61 @@ |
9 | 9 | * @author Rob Church <robchur@gmail.com> |
10 | 10 | */ |
11 | 11 | |
12 | | -require_once( "Maintenance.php" ); |
| 12 | +$options = array( 'help', 'bureaucrat' ); |
| 13 | +require_once( 'commandLine.inc' ); |
13 | 14 | |
14 | | -class CreateAndPromote extends Maintenance { |
| 15 | +if( isset( $options['help'] ) ) { |
| 16 | + showHelp(); |
| 17 | + exit( 1 ); |
| 18 | +} |
15 | 19 | |
16 | | - public function __construct() { |
17 | | - parent::__construct(); |
18 | | - $this->mDescription = "Create a new user account with administrator rights"; |
19 | | - $this->addParam( "bureaucrat", "Grant the account bureaucrat rights" ); |
20 | | - $this->addArgs( array( "username", "password" ) ); |
21 | | - } |
| 20 | +if( count( $args ) < 2 ) { |
| 21 | + echo( "Please provide a username and password for the new account.\n" ); |
| 22 | + die( 1 ); |
| 23 | +} |
22 | 24 | |
23 | | - public function execute() { |
24 | | - $username = $this->getArg(0); |
25 | | - $password = $this->getArg(1); |
26 | | - |
27 | | - $this->output( wfWikiID() . ": Creating and promoting User:{$username}..." ); |
28 | | - |
29 | | - $user = User::newFromName( $username ); |
30 | | - if( !is_object( $user ) ) { |
31 | | - $this->error( "invalid username.\n", true ); |
32 | | - } elseif( 0 != $user->idForName() ) { |
33 | | - $this->error( "account exists.\n", true ); |
34 | | - } |
| 25 | +$username = $args[0]; |
| 26 | +$password = $args[1]; |
35 | 27 | |
36 | | - # Try to set the password |
37 | | - try { |
38 | | - $user->setPassword( $password ); |
39 | | - } catch( PasswordError $pwe ) { |
40 | | - $this->error( $pwe->getText(), true ); |
41 | | - } |
| 28 | +echo( wfWikiID() . ": Creating and promoting User:{$username}..." ); |
42 | 29 | |
43 | | - # Insert the account into the database |
44 | | - $user->addToDatabase(); |
45 | | - $user->saveSettings(); |
46 | | - |
47 | | - # Promote user |
48 | | - $user->addGroup( 'sysop' ); |
49 | | - if( $this->hasOption( 'bureaucrat' ) ) |
50 | | - $user->addGroup( 'bureaucrat' ); |
51 | | - |
52 | | - # Increment site_stats.ss_users |
53 | | - $ssu = new SiteStatsUpdate( 0, 0, 0, 0, 1 ); |
54 | | - $ssu->doUpdate(); |
55 | | - |
56 | | - $this->output( "done.\n" ); |
57 | | - } |
| 30 | +# Validate username and check it doesn't exist |
| 31 | +$user = User::newFromName( $username ); |
| 32 | +if( !is_object( $user ) ) { |
| 33 | + echo( "invalid username.\n" ); |
| 34 | + die( 1 ); |
| 35 | +} elseif( 0 != $user->idForName() ) { |
| 36 | + echo( "account exists.\n" ); |
| 37 | + die( 1 ); |
58 | 38 | } |
59 | 39 | |
60 | | -$maintClass = "CreateAndPromote"; |
61 | | -require_once( DO_MAINTENANCE ); |
| 40 | +# Insert the account into the database |
| 41 | +$user->addToDatabase(); |
| 42 | +$user->setPassword( $password ); |
| 43 | +$user->saveSettings(); |
| 44 | + |
| 45 | +# Promote user |
| 46 | +$user->addGroup( 'sysop' ); |
| 47 | +if( isset( $option['bureaucrat'] ) ) |
| 48 | + $user->addGroup( 'bureaucrat' ); |
| 49 | + |
| 50 | +# Increment site_stats.ss_users |
| 51 | +$ssu = new SiteStatsUpdate( 0, 0, 0, 0, 1 ); |
| 52 | +$ssu->doUpdate(); |
| 53 | + |
| 54 | +echo( "done.\n" ); |
| 55 | + |
| 56 | +function showHelp() { |
| 57 | + echo( <<<EOT |
| 58 | +Create a new user account with administrator rights |
| 59 | + |
| 60 | +USAGE: php createAndPromote.php [--bureaucrat|--help] <username> <password> |
| 61 | + |
| 62 | + --bureaucrat |
| 63 | + Grant the account bureaucrat rights |
| 64 | + --help |
| 65 | + Show this help information |
| 66 | + |
| 67 | +EOT |
| 68 | + ); |
| 69 | +} |
\ No newline at end of file |
Index: trunk/phase3/maintenance/deleteDefaultMessages.php |
— | — | @@ -1,53 +1,48 @@ |
2 | 2 | <?php |
| 3 | + |
3 | 4 | /** |
4 | 5 | * Deletes all pages in the MediaWiki namespace which were last edited by |
5 | 6 | * "MediaWiki default". |
6 | 7 | * |
| 8 | + * @file |
7 | 9 | * @ingroup Maintenance |
8 | 10 | */ |
9 | 11 | |
10 | | -require_once( "Maintenance.php" ); |
| 12 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 13 | + require_once( 'commandLine.inc' ); |
| 14 | + deleteDefaultMessages(); |
| 15 | +} |
11 | 16 | |
12 | | -class DeleteDefaultMessages extends Maintenance { |
13 | | - public function __construct() { |
14 | | - parent::__construct(); |
15 | | - $this->mDescription = "Deletes all pages in the MediaWiki namespace" . |
16 | | - " which were last edited by \"MediaWiki default\""; |
17 | | - } |
| 17 | +function deleteDefaultMessages() { |
| 18 | + $user = 'MediaWiki default'; |
| 19 | + $reason = 'No longer required'; |
18 | 20 | |
19 | | - public function execute() { |
20 | | - $user = 'MediaWiki default'; |
21 | | - $reason = 'No longer required'; |
| 21 | + global $wgUser; |
| 22 | + $wgUser = User::newFromName( $user ); |
| 23 | + $wgUser->addGroup( 'bot' ); |
| 24 | + |
| 25 | + $dbr = wfGetDB( DB_SLAVE ); |
| 26 | + $res = $dbr->select( array( 'page', 'revision' ), |
| 27 | + array( 'page_namespace', 'page_title' ), |
| 28 | + array( |
| 29 | + 'page_namespace' => NS_MEDIAWIKI, |
| 30 | + 'page_latest=rev_id', |
| 31 | + 'rev_user_text' => 'MediaWiki default', |
| 32 | + ) |
| 33 | + ); |
22 | 34 | |
23 | | - global $wgUser; |
24 | | - $wgUser = User::newFromName( $user ); |
25 | | - $wgUser->addGroup( 'bot' ); |
| 35 | + $dbw = wfGetDB( DB_MASTER ); |
26 | 36 | |
27 | | - $dbr = wfGetDB( DB_SLAVE ); |
28 | | - $res = $dbr->select( array( 'page', 'revision' ), |
29 | | - array( 'page_namespace', 'page_title' ), |
30 | | - array( |
31 | | - 'page_namespace' => NS_MEDIAWIKI, |
32 | | - 'page_latest=rev_id', |
33 | | - 'rev_user_text' => 'MediaWiki default', |
34 | | - ) |
35 | | - ); |
36 | | - |
37 | | - $dbw = wfGetDB( DB_MASTER ); |
38 | | - |
39 | | - while ( $row = $dbr->fetchObject( $res ) ) { |
40 | | - if ( function_exists( 'wfWaitForSlaves' ) ) { |
41 | | - wfWaitForSlaves( 5 ); |
42 | | - } |
43 | | - $dbw->ping(); |
44 | | - $title = Title::makeTitle( $row->page_namespace, $row->page_title ); |
45 | | - $article = new Article( $title ); |
46 | | - $dbw->begin(); |
47 | | - $article->doDeleteArticle( $reason ); |
48 | | - $dbw->commit(); |
| 37 | + while ( $row = $dbr->fetchObject( $res ) ) { |
| 38 | + if ( function_exists( 'wfWaitForSlaves' ) ) { |
| 39 | + wfWaitForSlaves( 5 ); |
49 | 40 | } |
| 41 | + $dbw->ping(); |
| 42 | + $title = Title::makeTitle( $row->page_namespace, $row->page_title ); |
| 43 | + $article = new Article( $title ); |
| 44 | + $dbw->begin(); |
| 45 | + $article->doDeleteArticle( $reason ); |
| 46 | + $dbw->commit(); |
50 | 47 | } |
51 | 48 | } |
52 | 49 | |
53 | | -$maintClass = "DeleteDefaultMessages"; |
54 | | -require_once( DO_MAINTENANCE ); |
Index: trunk/phase3/maintenance/updateSpecialPages.php |
— | — | @@ -6,114 +6,114 @@ |
7 | 7 | * @file |
8 | 8 | * @ingroup Maintenance |
9 | 9 | */ |
10 | | - |
11 | | -require_once( "Maintenance.php" ); |
| 10 | +$options = array('only','help'); |
12 | 11 | |
13 | | -class UpdateSpecialPages extends Maintenance { |
14 | | - public function __construct() { |
15 | | - parent::__construct(); |
16 | | - $this->addParam( 'list', 'List special page names' ); |
17 | | - $this->addParam( 'only', 'Only update "page". Ex: --only=BrokenRedirects', false, true ); |
18 | | - $this->addParam( 'override', 'Also update pages that have updates disabled' ); |
| 12 | +require_once( 'commandLine.inc' ); |
| 13 | + |
| 14 | +require_once( "$IP/includes/SpecialPage.php" ); |
| 15 | +require_once( "$IP/includes/QueryPage.php" ); |
| 16 | + |
| 17 | +if(@$options['help']) { |
| 18 | + print "usage:updateSpecialPages.php [--help] [--only=page]\n"; |
| 19 | + print " --help : this help message\n"; |
| 20 | + print " --list : list special pages names\n"; |
| 21 | + print " --only=page : only update 'page'. Ex: --only=BrokenRedirects\n"; |
| 22 | + print " --override : update even pages which have had updates disabled\n"; |
| 23 | + wfDie(); |
| 24 | +} |
| 25 | + |
| 26 | +$wgOut->disable(); |
| 27 | +$dbw = wfGetDB( DB_MASTER ); |
| 28 | + |
| 29 | +foreach( $wgSpecialPageCacheUpdates as $special => $call ) { |
| 30 | + if( !is_callable($call) ) { |
| 31 | + print "Uncallable function $call!\n"; |
| 32 | + continue; |
19 | 33 | } |
| 34 | + $t1 = explode( ' ', microtime() ); |
| 35 | + call_user_func( $call, $dbw ); |
| 36 | + $t2 = explode( ' ', microtime() ); |
| 37 | + printf( '%-30s ', $special ); |
| 38 | + $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); |
| 39 | + $hours = intval( $elapsed / 3600 ); |
| 40 | + $minutes = intval( $elapsed % 3600 / 60 ); |
| 41 | + $seconds = $elapsed - $hours * 3600 - $minutes * 60; |
| 42 | + if ( $hours ) { |
| 43 | + print $hours . 'h '; |
| 44 | + } |
| 45 | + if ( $minutes ) { |
| 46 | + print $minutes . 'm '; |
| 47 | + } |
| 48 | + printf( "completed in %.2fs\n", $seconds ); |
| 49 | + # Wait for the slave to catch up |
| 50 | + wfWaitForSlaves( 5 ); |
| 51 | +} |
20 | 52 | |
21 | | - public function execute() { |
22 | | - global $wgOut; |
23 | | - $wgOut->disable(); |
24 | | - $dbw = wfGetDB( DB_MASTER ); |
| 53 | +foreach( $wgQueryPages as $page ) { |
| 54 | + @list( $class, $special, $limit ) = $page; |
25 | 55 | |
26 | | - foreach( $wgSpecialPageCacheUpdates as $special => $call ) { |
27 | | - if( !is_callable($call) ) { |
28 | | - $this->error( "Uncallable function $call!\n" ); |
29 | | - continue; |
30 | | - } |
| 56 | + # --list : just show the name of pages |
| 57 | + if( @$options['list'] ) { |
| 58 | + print "$special\n"; |
| 59 | + continue; |
| 60 | + } |
| 61 | + |
| 62 | + if ( !isset( $options['override'] ) && $wgDisableQueryPageUpdate && in_array( $special, $wgDisableQueryPageUpdate ) ) { |
| 63 | + printf("%-30s disabled\n", $special); |
| 64 | + continue; |
| 65 | + } |
| 66 | + |
| 67 | + $specialObj = SpecialPage::getPage( $special ); |
| 68 | + if ( !$specialObj ) { |
| 69 | + print "No such special page: $special\n"; |
| 70 | + exit; |
| 71 | + } |
| 72 | + if ( !class_exists( $class ) ) { |
| 73 | + $file = $specialObj->getFile(); |
| 74 | + require_once( $file ); |
| 75 | + } |
| 76 | + $queryPage = new $class; |
| 77 | + |
| 78 | + if( !isset($options['only']) or $options['only'] == $queryPage->getName() ) { |
| 79 | + printf( '%-30s ', $special ); |
| 80 | + if ( $queryPage->isExpensive() ) { |
31 | 81 | $t1 = explode( ' ', microtime() ); |
32 | | - call_user_func( $call, $dbw ); |
| 82 | + # Do the query |
| 83 | + $num = $queryPage->recache( $limit === null ? $wgQueryCacheLimit : $limit ); |
33 | 84 | $t2 = explode( ' ', microtime() ); |
34 | | - $this->output( sprintf( '%-30s ', $special ) ); |
35 | | - $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); |
36 | | - $hours = intval( $elapsed / 3600 ); |
37 | | - $minutes = intval( $elapsed % 3600 / 60 ); |
38 | | - $seconds = $elapsed - $hours * 3600 - $minutes * 60; |
39 | | - if ( $hours ) { |
40 | | - $this->output( $hours . 'h ' ); |
41 | | - } |
42 | | - if ( $minutes ) { |
43 | | - $this->output( $minutes . 'm ' ); |
44 | | - } |
45 | | - $this->output( sprintf( "completed in %.2fs\n", $seconds ) ); |
46 | | - # Wait for the slave to catch up |
47 | | - wfWaitForSlaves( 5 ); |
48 | | - } |
49 | | - |
50 | | - foreach( $wgQueryPages as $page ) { |
51 | | - @list( $class, $special, $limit ) = $page; |
52 | | - |
53 | | - # --list : just show the name of pages |
54 | | - if( $this->hasOption('list') ) { |
55 | | - $this->output( "$special\n" ); |
56 | | - continue; |
57 | | - } |
58 | | - |
59 | | - if ( $this->hasOption('override') && $wgDisableQueryPageUpdate && in_array( $special, $wgDisableQueryPageUpdate ) ) { |
60 | | - $this->output( sprintf( "%-30s disabled\n", $special ) ); |
61 | | - continue; |
62 | | - } |
63 | | - |
64 | | - $specialObj = SpecialPage::getPage( $special ); |
65 | | - if ( !$specialObj ) { |
66 | | - $this->output( "No such special page: $special\n" ); |
67 | | - exit; |
68 | | - } |
69 | | - if ( !class_exists( $class ) ) { |
70 | | - $file = $specialObj->getFile(); |
71 | | - require_once( $file ); |
72 | | - } |
73 | | - $queryPage = new $class; |
74 | | - |
75 | | - if( !$this->hasOption('only') || $this->getOption('only') == $queryPage->getName() ) { |
76 | | - $this->output( sprintf( '%-30s ', $special ) ); |
77 | | - if ( $queryPage->isExpensive() ) { |
78 | | - $t1 = explode( ' ', microtime() ); |
79 | | - # Do the query |
80 | | - $num = $queryPage->recache( $limit === null ? $wgQueryCacheLimit : $limit ); |
81 | | - $t2 = explode( ' ', microtime() ); |
82 | | - if ( $num === false ) { |
83 | | - $this->output( "FAILED: database error\n" ); |
84 | | - } else { |
85 | | - $this->output( "got $num rows in " ); |
86 | | - |
87 | | - $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); |
88 | | - $hours = intval( $elapsed / 3600 ); |
89 | | - $minutes = intval( $elapsed % 3600 / 60 ); |
90 | | - $seconds = $elapsed - $hours * 3600 - $minutes * 60; |
91 | | - if ( $hours ) { |
92 | | - $this->output( $hours . 'h ' ); |
93 | | - } |
94 | | - if ( $minutes ) { |
95 | | - $this->output( $minutes . 'm ' ); |
96 | | - } |
97 | | - $this->output( sprintf( "%.2fs\n", $seconds ) ); |
| 85 | + if ( $num === false ) { |
| 86 | + print "FAILED: database error\n"; |
| 87 | + } else { |
| 88 | + print "got $num rows in "; |
| 89 | + |
| 90 | + $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]); |
| 91 | + $hours = intval( $elapsed / 3600 ); |
| 92 | + $minutes = intval( $elapsed % 3600 / 60 ); |
| 93 | + $seconds = $elapsed - $hours * 3600 - $minutes * 60; |
| 94 | + if ( $hours ) { |
| 95 | + print $hours . 'h '; |
98 | 96 | } |
99 | | - # Reopen any connections that have closed |
100 | | - if ( !wfGetLB()->pingAll()) { |
101 | | - $this->output( "\n" ); |
102 | | - do { |
103 | | - $this->error( "Connection failed, reconnecting in 10 seconds...\n" ); |
104 | | - sleep(10); |
105 | | - } while ( !wfGetLB()->pingAll() ); |
106 | | - $this->output( "Reconnected\n\n" ); |
107 | | - } else { |
108 | | - # Commit the results |
109 | | - $dbw->immediateCommit(); |
| 97 | + if ( $minutes ) { |
| 98 | + print $minutes . 'm '; |
110 | 99 | } |
111 | | - # Wait for the slave to catch up |
112 | | - wfWaitForSlaves( 5 ); |
113 | | - } else { |
114 | | - $this->output( "cheap, skipped\n" ); |
115 | | - } |
116 | | - } |
| 100 | + printf( "%.2fs\n", $seconds ); |
117 | 101 | } |
| 102 | + # Reopen any connections that have closed |
| 103 | + if ( !wfGetLB()->pingAll()) { |
| 104 | + print "\n"; |
| 105 | + do { |
| 106 | + print "Connection failed, reconnecting in 10 seconds...\n"; |
| 107 | + sleep(10); |
| 108 | + } while ( !wfGetLB()->pingAll() ); |
| 109 | + print "Reconnected\n\n"; |
| 110 | + } else { |
| 111 | + # Commit the results |
| 112 | + $dbw->immediateCommit(); |
| 113 | + } |
| 114 | + # Wait for the slave to catch up |
| 115 | + wfWaitForSlaves( 5 ); |
| 116 | + } else { |
| 117 | + print "cheap, skipped\n"; |
| 118 | + } |
118 | 119 | } |
119 | 120 | } |
120 | | - |
Index: trunk/phase3/maintenance/README |
— | — | @@ -10,8 +10,8 @@ |
11 | 11 | |
12 | 12 | Certain scripts will require elevated access to the database. In order to |
13 | 13 | provide this, first create a MySQL user with "all" permissions on the wiki |
14 | | -database, and then set $wgDBadminuser and $wgDBadminpassword in your |
15 | | -LocalSettings.php |
| 14 | +database, and then place their username and password in an AdminSettings.php |
| 15 | +file in the directory above. See AdminSettings.sample for specifics on this. |
16 | 16 | |
17 | 17 | === Brief explanation of files === |
18 | 18 | |
Index: trunk/phase3/maintenance/attachLatest.php |
— | — | @@ -25,58 +25,49 @@ |
26 | 26 | * @ingroup Maintenance |
27 | 27 | */ |
28 | 28 | |
29 | | -require_once( "Maintenance.php" ); |
| 29 | +require_once( 'commandLine.inc' ); |
30 | 30 | |
31 | | -class AttachLatest extends Maintenance { |
32 | | - |
33 | | - public function __construct() { |
34 | | - parent::__construct(); |
35 | | - $this->addParam( "fix", "Actually fix the entries, will dry run otherwise" ); |
36 | | - $this->mDescription = "Fix page_latest entries in the page table"; |
| 31 | +$fixit = isset( $options['fix'] ); |
| 32 | +$fname = 'attachLatest'; |
| 33 | + |
| 34 | +echo "Looking for pages with page_latest set to 0...\n"; |
| 35 | +$dbw = wfGetDB( DB_MASTER ); |
| 36 | +$result = $dbw->select( 'page', |
| 37 | + array( 'page_id', 'page_namespace', 'page_title' ), |
| 38 | + array( 'page_latest' => 0 ), |
| 39 | + $fname ); |
| 40 | + |
| 41 | +$n = 0; |
| 42 | +while( $row = $dbw->fetchObject( $result ) ) { |
| 43 | + $pageId = intval( $row->page_id ); |
| 44 | + $title = Title::makeTitle( $row->page_namespace, $row->page_title ); |
| 45 | + $name = $title->getPrefixedText(); |
| 46 | + $latestTime = $dbw->selectField( 'revision', |
| 47 | + 'MAX(rev_timestamp)', |
| 48 | + array( 'rev_page' => $pageId ), |
| 49 | + $fname ); |
| 50 | + if( !$latestTime ) { |
| 51 | + echo wfWikiID()." $pageId [[$name]] can't find latest rev time?!\n"; |
| 52 | + continue; |
37 | 53 | } |
38 | | - |
39 | | - public function execute() { |
40 | | - $this->output( "Looking for pages with page_latest set to 0...\n" ); |
41 | | - $dbw = wfGetDB( DB_MASTER ); |
42 | | - $result = $dbw->select( 'page', |
43 | | - array( 'page_id', 'page_namespace', 'page_title' ), |
44 | | - array( 'page_latest' => 0 ), |
45 | | - __METHOD__ ); |
46 | 54 | |
47 | | - $n = 0; |
48 | | - while( $row = $dbw->fetchObject( $result ) ) { |
49 | | - $pageId = intval( $row->page_id ); |
50 | | - $title = Title::makeTitle( $row->page_namespace, $row->page_title ); |
51 | | - $name = $title->getPrefixedText(); |
52 | | - $latestTime = $dbw->selectField( 'revision', |
53 | | - 'MAX(rev_timestamp)', |
54 | | - array( 'rev_page' => $pageId ), |
55 | | - __METHOD__ ); |
56 | | - if( !$latestTime ) { |
57 | | - $this->output( wfWikiID()." $pageId [[$name]] can't find latest rev time?!\n" ); |
58 | | - continue; |
59 | | - } |
60 | | - |
61 | | - $revision = Revision::loadFromTimestamp( $dbw, $title, $latestTime ); |
62 | | - if( is_null( $revision ) ) { |
63 | | - $this->output( wfWikiID()." $pageId [[$name]] latest time $latestTime, can't find revision id\n" ); |
64 | | - continue; |
65 | | - } |
66 | | - $id = $revision->getId(); |
67 | | - $this->output( wfWikiID()." $pageId [[$name]] latest time $latestTime, rev id $id\n" ); |
68 | | - if( $this->hasOption('fix') ) { |
69 | | - $article = new Article( $title ); |
70 | | - $article->updateRevisionOn( $dbw, $revision ); |
71 | | - } |
72 | | - $n++; |
73 | | - } |
74 | | - $dbw->freeResult( $result ); |
75 | | - $this->output( "Done! Processed $n pages.\n" ); |
76 | | - if( !$this->hasOption('fix') ) { |
77 | | - $this->output( "This was a dry run; rerun with --fix to update page_latest.\n" ); |
78 | | - } |
| 55 | + $revision = Revision::loadFromTimestamp( $dbw, $title, $latestTime ); |
| 56 | + if( is_null( $revision ) ) { |
| 57 | + echo wfWikiID()." $pageId [[$name]] latest time $latestTime, can't find revision id\n"; |
| 58 | + continue; |
79 | 59 | } |
| 60 | + $id = $revision->getId(); |
| 61 | + echo wfWikiID()." $pageId [[$name]] latest time $latestTime, rev id $id\n"; |
| 62 | + if( $fixit ) { |
| 63 | + $article = new Article( $title ); |
| 64 | + $article->updateRevisionOn( $dbw, $revision ); |
| 65 | + } |
| 66 | + $n++; |
80 | 67 | } |
| 68 | +$dbw->freeResult( $result ); |
| 69 | +echo "Done! Processed $n pages.\n"; |
| 70 | +if( !$fixit ) { |
| 71 | + echo "This was a dry run; rerun with --fix to update page_latest.\n"; |
| 72 | +} |
81 | 73 | |
82 | | -$maintClass = "AttachLatest"; |
83 | | -require_once( DO_MAINTENANCE ); |
| 74 | + |
Index: trunk/phase3/maintenance/checkBadRedirects.php |
— | — | @@ -1,42 +1,30 @@ |
2 | 2 | <?php |
3 | | -/** |
4 | | - * CheckBadRedirects - See if pages marked as being redirects |
5 | | - * really are. |
6 | | - */ |
7 | | - |
8 | | -require_once( "Maintenance.php" ); |
9 | 3 | |
10 | | -class CheckBadRedirects extends Maintenance { |
11 | | - public function __construct() { |
12 | | - parent::__construct(); |
13 | | - $this->mDescription = "Look for bad redirects"; |
14 | | - } |
| 4 | +require "commandLine.inc"; |
15 | 5 | |
16 | | - public function execute() { |
17 | | - $this->output( "Fetching redirects...\n" ); |
18 | | - $dbr = wfGetDB( DB_SLAVE ); |
19 | | - $result = $dbr->select( |
20 | | - array( 'page' ), |
21 | | - array( 'page_namespace','page_title', 'page_latest' ), |
22 | | - array( 'page_is_redirect' => 1 ) ); |
23 | | - |
24 | | - $count = $result->numRows(); |
25 | | - $this->output( "Found $count total redirects.\n" . |
26 | | - "Looking for bad redirects:\n\n" ); |
27 | | - |
28 | | - foreach( $result as $row ) { |
29 | | - $title = Title::makeTitle( $row->page_namespace, $row->page_title ); |
30 | | - $rev = Revision::newFromId( $row->page_latest ); |
31 | | - if( $rev ) { |
32 | | - $target = Title::newFromRedirect( $rev->getText() ); |
33 | | - if( !$target ) { |
34 | | - $this->output( $title->getPrefixedText() . "\n" ); |
35 | | - } |
36 | | - } |
| 6 | +echo "Fetching redirects...\n"; |
| 7 | +$dbr = wfGetDB( DB_SLAVE ); |
| 8 | +$result = $dbr->select( |
| 9 | + array( 'page' ), |
| 10 | + array( 'page_namespace','page_title', 'page_latest' ), |
| 11 | + array( 'page_is_redirect' => 1 ) ); |
| 12 | + |
| 13 | +$count = $result->numRows(); |
| 14 | +echo "Found $count total redirects.\n"; |
| 15 | +echo "Looking for bad redirects:\n"; |
| 16 | +echo "\n"; |
| 17 | + |
| 18 | +foreach( $result as $row ) { |
| 19 | + $title = Title::makeTitle( $row->page_namespace, $row->page_title ); |
| 20 | + $rev = Revision::newFromId( $row->page_latest ); |
| 21 | + if( $rev ) { |
| 22 | + $target = Title::newFromRedirect( $rev->getText() ); |
| 23 | + if( !$target ) { |
| 24 | + echo $title->getPrefixedText(); |
| 25 | + echo "\n"; |
37 | 26 | } |
38 | | - $this->output( "\ndone.\n" ); |
39 | 27 | } |
40 | 28 | } |
41 | 29 | |
42 | | -$maintClass = "CheckBadRedirects"; |
43 | | -require_once( DO_MAINTENANCE ); |
| 30 | +echo "\n"; |
| 31 | +echo "done.\n"; |
Index: trunk/phase3/maintenance/showJobs.php |
— | — | @@ -9,19 +9,10 @@ |
10 | 10 | * @author Tim Starling |
11 | 11 | * @author Ashar Voultoiz |
12 | 12 | */ |
13 | | - |
14 | | -require_once( "Maintenance.php" ); |
| 13 | +require_once( 'commandLine.inc' ); |
15 | 14 | |
16 | | -class ShowJobs extends Maintenance { |
17 | | - public function __construct() { |
18 | | - parent::__construct(); |
19 | | - $this->mDescription = "Show number of jobs waiting in master database"; |
20 | | - } |
21 | | - public function execute() { |
22 | | - $dbw = wfGetDB( DB_MASTER ); |
23 | | - $this->output( $dbw->selectField( 'job', 'count(*)', '', 'runJobs.php' ) . "\n" ); |
24 | | - } |
25 | | -} |
| 15 | +$dbw = wfGetDB( DB_MASTER ); |
| 16 | +$count = $dbw->selectField( 'job', 'count(*)', '', 'runJobs.php' ); |
| 17 | +print $count."\n"; |
26 | 18 | |
27 | | -$maintClass = "ShowJobs"; |
28 | | -require_once( DO_MAINTENANCE ); |
| 19 | + |
Index: trunk/phase3/maintenance/mctest.php |
— | — | @@ -8,63 +8,58 @@ |
9 | 9 | * @ingroup Maintenance |
10 | 10 | */ |
11 | 11 | |
12 | | -require_once( "Maintenance.php" ); |
| 12 | +$optionsWithArgs = array( 'i' ); |
13 | 13 | |
14 | | -class mcTest extends Maintenance { |
15 | | - public function __construct() { |
16 | | - parent::__construct(); |
17 | | - $this->mDescription = "Makes several 'set', 'incr' and 'get' requests on every" |
18 | | - . " memcached server and shows a report"; |
19 | | - $this->addParam( 'i', 'Number of iterations', false, true ); |
20 | | - $this->addArgs( array( 'server' ) ); |
21 | | - } |
| 14 | +require_once('commandLine.inc'); |
22 | 15 | |
23 | | - public function execute() { |
24 | | - global $wgMemCachedServers; |
| 16 | +function microtime_float() |
| 17 | +{ |
| 18 | + list($usec, $sec) = explode(" ", microtime()); |
| 19 | + return ((float)$usec + (float)$sec); |
| 20 | +} |
25 | 21 | |
26 | | - $iterations = $this->getOption( 'i', 100 ); |
27 | | - if( $this->hasArg() ) |
28 | | - $wgMemCachedServers = array( $this->getArg() ); |
29 | 22 | |
30 | | - foreach ( $wgMemCachedServers as $server ) { |
31 | | - $this->output( $server . " " ); |
32 | | - $mcc = new MemCachedClientforWiki( array('persistant' => true) ); |
33 | | - $mcc->set_servers( array( $server ) ); |
34 | | - $set = 0; |
35 | | - $incr = 0; |
36 | | - $get = 0; |
37 | | - $time_start = $this->microtime_float(); |
38 | | - for ( $i=1; $i<=$iterations; $i++ ) { |
39 | | - if ( !is_null( $mcc->set( "test$i", $i ) ) ) { |
40 | | - $set++; |
41 | | - } |
42 | | - } |
43 | | - for ( $i=1; $i<=$iterations; $i++ ) { |
44 | | - if ( !is_null( $mcc->incr( "test$i", $i ) ) ) { |
45 | | - $incr++; |
46 | | - } |
47 | | - } |
48 | | - for ( $i=1; $i<=$iterations; $i++ ) { |
49 | | - $value = $mcc->get( "test$i" ); |
50 | | - if ( $value == $i*2 ) { |
51 | | - $get++; |
52 | | - } |
53 | | - } |
54 | | - $exectime = $this->microtime_float() - $time_start; |
55 | | - |
56 | | - $this->output( "set: $set incr: $incr get: $get time: $exectime\n" ); |
| 23 | +#$wgDebugLogFile = '/dev/stdout'; |
| 24 | + |
| 25 | +if ( isset( $args[0] ) ) { |
| 26 | + $wgMemCachedServers = array( $args[0] ); |
| 27 | +} |
| 28 | +if ( isset( $options['i'] ) ) { |
| 29 | + $iterations = $options['i']; |
| 30 | +} else { |
| 31 | + $iterations = 100; |
| 32 | +} |
| 33 | + |
| 34 | +foreach ( $wgMemCachedServers as $server ) { |
| 35 | + print "$server "; |
| 36 | + $mcc = new MemCachedClientforWiki( array('persistant' => true) ); |
| 37 | + $mcc->set_servers( array( $server ) ); |
| 38 | + $set = 0; |
| 39 | + $incr = 0; |
| 40 | + $get = 0; |
| 41 | + $time_start=microtime_float(); |
| 42 | + for ( $i=1; $i<=$iterations; $i++ ) { |
| 43 | + if ( !is_null( $mcc->set( "test$i", $i ) ) ) { |
| 44 | + $set++; |
57 | 45 | } |
58 | 46 | } |
59 | 47 | |
60 | | - /** |
61 | | - * Return microtime() as a float |
62 | | - * @return float |
63 | | - */ |
64 | | - private function microtime_float() { |
65 | | - list($usec, $sec) = explode(" ", microtime()); |
66 | | - return ((float)$usec + (float)$sec); |
| 48 | + for ( $i=1; $i<=$iterations; $i++ ) { |
| 49 | + if ( !is_null( $mcc->incr( "test$i", $i ) ) ) { |
| 50 | + $incr++; |
| 51 | + } |
67 | 52 | } |
| 53 | + |
| 54 | + for ( $i=1; $i<=$iterations; $i++ ) { |
| 55 | + $value = $mcc->get( "test$i" ); |
| 56 | + if ( $value == $i*2 ) { |
| 57 | + $get++; |
| 58 | + } |
| 59 | + } |
| 60 | + $exectime=microtime_float()-$time_start; |
| 61 | + |
| 62 | + print "set: $set incr: $incr get: $get time: $exectime\n"; |
68 | 63 | } |
69 | 64 | |
70 | | -$maintClass = "mcTest"; |
71 | | -require_once( DO_MAINTENANCE ); |
| 65 | + |
| 66 | + |
Index: trunk/phase3/maintenance/sql.php |
— | — | @@ -7,56 +7,38 @@ |
8 | 8 | * @ingroup Database Maintenance |
9 | 9 | */ |
10 | 10 | |
11 | | -require_once( "Maintenance.php" ); |
| 11 | +require_once( dirname(__FILE__) . '/' . 'commandLine.inc' ); |
12 | 12 | |
13 | | -class MwSql extends Maintenance { |
14 | | - public function __construct() { |
15 | | - parent::__construct(); |
16 | | - $this->mDescription = "Send SQL queries to a MediaWiki database"; |
17 | | - } |
| 13 | +if ( isset( $options['help'] ) ) { |
| 14 | + echo "Send SQL queries to a MediaWiki database.\nUsage: php sql.php [<file>]\n"; |
| 15 | + exit( 1 ); |
| 16 | +} |
18 | 17 | |
19 | | - public function execute() { |
20 | | - if ( $this->hasArg() ) { |
21 | | - $fileName = $this->getArg(); |
22 | | - $file = fopen( $fileName, 'r' ); |
23 | | - $promptCallback = false; |
24 | | - } else { |
25 | | - $file = $this->getStdin(); |
26 | | - $promptObject = new SqlPromptPrinter( "> " ); |
27 | | - $promptCallback = $promptObject->cb(); |
28 | | - } |
29 | | - |
30 | | - if ( !$file ) |
31 | | - $this->error( "Unable to open input file\n", true ); |
| 18 | +if ( isset( $args[0] ) ) { |
| 19 | + $fileName = $args[0]; |
| 20 | + $file = fopen( $fileName, 'r' ); |
| 21 | + $promptCallback = false; |
| 22 | +} else { |
| 23 | + $file = STDIN; |
| 24 | + $promptObject = new SqlPromptPrinter( "> " ); |
| 25 | + $promptCallback = $promptObject->cb(); |
| 26 | +} |
32 | 27 | |
33 | | - $dbw = wfGetDB( DB_MASTER ); |
34 | | - $error = $dbw->sourceStream( $file, $promptCallback, array( $this, 'sqlPrintResult' ) ); |
35 | | - if ( $error !== true ) { |
36 | | - $this->error( $error, true ); |
37 | | - } else { |
38 | | - exit( 0 ); |
39 | | - } |
40 | | - } |
| 28 | +if ( !$file ) { |
| 29 | + echo "Unable to open input file\n"; |
| 30 | + exit( 1 ); |
| 31 | +} |
41 | 32 | |
42 | | - /** |
43 | | - * Print the results, callback for $db->sourceStream() |
44 | | - * @param $res The results object |
45 | | - * @param $db Database object |
46 | | - */ |
47 | | - public function sqlPrintResult( $res, $db ) { |
48 | | - if ( !$res ) { |
49 | | - // Do nothing |
50 | | - } elseif ( is_object( $res ) && $res->numRows() ) { |
51 | | - while ( $row = $res->fetchObject() ) { |
52 | | - $this->output( print_r( $row, true ) ); |
53 | | - } |
54 | | - } else { |
55 | | - $affected = $db->affectedRows(); |
56 | | - $this->output( "Query OK, $affected row(s) affected\n" ); |
57 | | - } |
58 | | - } |
| 33 | +$dbw =& wfGetDB( DB_MASTER ); |
| 34 | +$error = $dbw->sourceStream( $file, $promptCallback, 'sqlPrintResult' ); |
| 35 | +if ( $error !== true ) { |
| 36 | + echo $error; |
| 37 | + exit( 1 ); |
| 38 | +} else { |
| 39 | + exit( 0 ); |
59 | 40 | } |
60 | 41 | |
| 42 | +//----------------------------------------------------------------------------- |
61 | 43 | class SqlPromptPrinter { |
62 | 44 | function __construct( $prompt ) { |
63 | 45 | $this->prompt = $prompt; |
— | — | @@ -71,5 +53,17 @@ |
72 | 54 | } |
73 | 55 | } |
74 | 56 | |
75 | | -$maintClass = "MwSql"; |
76 | | -require_once( DO_MAINTENANCE ); |
| 57 | +function sqlPrintResult( $res, $db ) { |
| 58 | + if ( !$res ) { |
| 59 | + // Do nothing |
| 60 | + } elseif ( is_object( $res ) && $res->numRows() ) { |
| 61 | + while ( $row = $res->fetchObject() ) { |
| 62 | + print_r( $row ); |
| 63 | + } |
| 64 | + } else { |
| 65 | + $affected = $db->affectedRows(); |
| 66 | + echo "Query OK, $affected row(s) affected\n"; |
| 67 | + } |
| 68 | +} |
| 69 | + |
| 70 | + |
Index: trunk/phase3/maintenance/reassignEdits.php |
— | — | @@ -1,153 +1,56 @@ |
2 | 2 | <?php |
| 3 | + |
3 | 4 | /** |
4 | 5 | * Reassign edits from a user or IP address to another user |
5 | 6 | * |
| 7 | + * @file |
6 | 8 | * @ingroup Maintenance |
7 | 9 | * @author Rob Church <robchur@gmail.com> |
8 | 10 | * @licence GNU General Public Licence 2.0 or later |
9 | 11 | */ |
10 | 12 | |
11 | | -require_once( "Maintenance.php" ); |
| 13 | +$options = array( 'force', 'norc', 'quiet', 'report' ); |
| 14 | +require_once( 'commandLine.inc' ); |
| 15 | +require_once( 'reassignEdits.inc' ); |
12 | 16 | |
13 | | -class ReassignEdits extends Maintenance { |
14 | | - public function __construct() { |
15 | | - parent::__construct(); |
16 | | - $this->mDescription = "Reassign edits from one user to another"; |
17 | | - $this->addParam( "force", "Reassign even if the target user doesn't exist" ); |
18 | | - $this->addParam( "norc", "Don't update the recent changes table" ); |
19 | | - $this->addParam( "report", "Print out details of what would be changed, but don't update it" ); |
20 | | - $this->addArgs( array( 'from', 'to' ) ); |
21 | | - } |
| 17 | +# Set silent mode; --report overrides --quiet |
| 18 | +if( !@$options['report'] && @$options['quiet'] ) |
| 19 | + setSilent(); |
22 | 20 | |
23 | | - public function execute() { |
24 | | - if( $this->hasArg(0) && $this->hasArg(1) ) { |
25 | | - # Set up the users involved |
26 | | - $from =& $this->initialiseUser( $this->getArg(0) ); |
27 | | - $to =& $this->initialiseUser( $this->getArg(1) ); |
28 | | - |
29 | | - # If the target doesn't exist, and --force is not set, stop here |
30 | | - if( $to->getId() || $this->hasOption('force') ) { |
31 | | - # Reassign the edits |
32 | | - $report = $this->hasOption('report'); |
33 | | - $count = $this->reassignEdits( $from, $to, !$this->hasOption('norc'), $report ); |
34 | | - # If reporting, and there were items, advise the user to run without --report |
35 | | - if( $report ) |
36 | | - $this->output( "Run the script again without --report to update.\n" ); |
37 | | - } else { |
38 | | - $ton = $to->getName(); |
39 | | - $this->error( "User '{$ton}' not found.\n" ); |
40 | | - } |
41 | | - } |
42 | | - } |
| 21 | +out( "Reassign Edits\n\n" ); |
43 | 22 | |
44 | | - /** |
45 | | - * Reassign edits from one user to another |
46 | | - * |
47 | | - * @param $from User to take edits from |
48 | | - * @param $to User to assign edits to |
49 | | - * @param $rc Update the recent changes table |
50 | | - * @param $report Don't change things; just echo numbers |
51 | | - * @return integer Number of entries changed, or that would be changed |
52 | | - */ |
53 | | - private function reassignEdits( &$from, &$to, $rc = false, $report = false ) { |
54 | | - $dbw = wfGetDB( DB_MASTER ); |
55 | | - $dbw->immediateBegin(); |
| 23 | +if( @$args[0] && @$args[1] ) { |
56 | 24 | |
57 | | - # Count things |
58 | | - $this->output( "Checking current edits..." ); |
59 | | - $res = $dbw->select( 'revision', 'COUNT(*) AS count', $this->userConditions( $from, 'rev_user', 'rev_user_text' ), __METHOD__ ); |
60 | | - $row = $dbw->fetchObject( $res ); |
61 | | - $cur = $row->count; |
62 | | - $this->output( "found {$cur}.\n" ); |
63 | | - |
64 | | - $this->output( "Checking deleted edits..." ); |
65 | | - $res = $dbw->select( 'archive', 'COUNT(*) AS count', $this->userConditions( $from, 'ar_user', 'ar_user_text' ), __METHOD__ ); |
66 | | - $row = $dbw->fetchObject( $res ); |
67 | | - $del = $row->count; |
68 | | - $this->output( "found {$del}.\n" ); |
69 | | - |
70 | | - # Don't count recent changes if we're not supposed to |
71 | | - if( $rc ) { |
72 | | - $this->output( "Checking recent changes..." ); |
73 | | - $res = $dbw->select( 'recentchanges', 'COUNT(*) AS count', $this->userConditions( $from, 'rc_user', 'rc_user_text' ), __METHOD__ ); |
74 | | - $row = $dbw->fetchObject( $res ); |
75 | | - $rec = $row->count; |
76 | | - $this->output( "found {$rec}.\n" ); |
77 | | - } else { |
78 | | - $rec = 0; |
79 | | - } |
| 25 | + # Set up the users involved |
| 26 | + $from =& initialiseUser( $args[0] ); |
| 27 | + $to =& initialiseUser( $args[1] ); |
80 | 28 | |
81 | | - $total = $cur + $del + $rec; |
82 | | - $this->output( "\nTotal entries to change: {$total}\n" ); |
83 | | - |
84 | | - if( !$report ) { |
85 | | - if( $total ) { |
86 | | - # Reassign edits |
87 | | - $this->output( "\nReassigning current edits..." ); |
88 | | - $res = $dbw->update( 'revision', userSpecification( $to, 'rev_user', 'rev_user_text' ), $this->userConditions( $from, 'rev_user', 'rev_user_text' ), __METHOD__ ); |
89 | | - $this->output( "done.\nReassigning deleted edits..." ); |
90 | | - $res = $dbw->update( 'archive', userSpecification( $to, 'ar_user', 'ar_user_text' ), $this->userConditions( $from, 'ar_user', 'ar_user_text' ), __METHOD__ ); |
91 | | - $this->output( "done.\n" ); |
92 | | - # Update recent changes if required |
93 | | - if( $rc ) { |
94 | | - $this->output( "Updating recent changes..." ); |
95 | | - $res = $dbw->update( 'recentchanges', $this->userSpecification( $to, 'rc_user', 'rc_user_text' ), $this->userConditions( $from, 'rc_user', 'rc_user_text' ), __METHOD__ ); |
96 | | - $this->output( "done.\n" ); |
97 | | - } |
98 | | - } |
99 | | - } |
100 | | - |
101 | | - $dbw->immediateCommit(); |
102 | | - return (int)$total; |
| 29 | + # If the target doesn't exist, and --force is not set, stop here |
| 30 | + if( $to->getId() || @$options['force'] ) { |
| 31 | + # Reassign the edits |
| 32 | + $report = @$options['report']; |
| 33 | + $count = reassignEdits( $from, $to, !@$options['norc'], $report ); |
| 34 | + # If reporting, and there were items, advise the user to run without --report |
| 35 | + if( $report ) |
| 36 | + out( "Run the script again without --report to update.\n" ); |
| 37 | + } else { |
| 38 | + $ton = $to->getName(); |
| 39 | + echo( "User '{$ton}' not found.\n" ); |
103 | 40 | } |
104 | 41 | |
105 | | - /** |
106 | | - * Return the most efficient set of user conditions |
107 | | - * i.e. a user => id mapping, or a user_text => text mapping |
108 | | - * |
109 | | - * @param $user User for the condition |
110 | | - * @param $idfield Field name containing the identifier |
111 | | - * @param $utfield Field name containing the user text |
112 | | - * @return array |
113 | | - */ |
114 | | - private function userConditions( &$user, $idfield, $utfield ) { |
115 | | - return $user->getId() ? array( $idfield => $user->getId() ) : array( $utfield => $user->getName() ); |
116 | | - } |
117 | | - |
118 | | - /** |
119 | | - * Return user specifications |
120 | | - * i.e. user => id, user_text => text |
121 | | - * |
122 | | - * @param $user User for the spec |
123 | | - * @param $idfield Field name containing the identifier |
124 | | - * @param $utfield Field name containing the user text |
125 | | - * @return array |
126 | | - */ |
127 | | - private function userSpecification( &$user, $idfield, $utfield ) { |
128 | | - return array( $idfield => $user->getId(), $utfield => $user->getName() ); |
129 | | - } |
130 | | - |
131 | | - /** |
132 | | - * Initialise the user object |
133 | | - * |
134 | | - * @param $username Username or IP address |
135 | | - * @return User |
136 | | - */ |
137 | | - private function initialiseUser( $username ) { |
138 | | - if( User::isIP( $username ) ) { |
139 | | - $user = new User(); |
140 | | - $user->setId( 0 ); |
141 | | - $user->setName( $username ); |
142 | | - } else { |
143 | | - $user = User::newFromName( $username ); |
144 | | - } |
145 | | - $user->load(); |
146 | | - return $user; |
147 | | - } |
| 42 | +} else { |
| 43 | + ShowUsage(); |
| 44 | +} |
148 | 45 | |
149 | | - |
| 46 | +/** Show script usage information */ |
| 47 | +function ShowUsage() { |
| 48 | + echo( "Reassign edits from one user to another.\n\n" ); |
| 49 | + echo( "Usage: php reassignEdits.php [--force|--quiet|--norc|--report] <from> <to>\n\n" ); |
| 50 | + echo( " <from> : Name of the user to assign edits from\n" ); |
| 51 | + echo( " <to> : Name of the user to assign edits to\n" ); |
| 52 | + echo( " --force : Reassign even if the target user doesn't exist\n" ); |
| 53 | + echo( " --quiet : Don't print status information (except for errors)\n" ); |
| 54 | + echo( " --norc : Don't update the recent changes table\n" ); |
| 55 | + echo( " --report : Print out details of what would be changed, but don't update it\n\n" ); |
150 | 56 | } |
151 | 57 | |
152 | | -$maintClass = "ReassignEdits"; |
153 | | -require_once( DO_MAINTENANCE ); |
154 | | - |
Index: trunk/phase3/maintenance/removeUnusedAccounts.php |
— | — | @@ -8,89 +8,63 @@ |
9 | 9 | * @author Rob Church <robchur@gmail.com> |
10 | 10 | */ |
11 | 11 | |
12 | | -require_once( "Maintenance.php" ); |
| 12 | +$options = array( 'help', 'delete' ); |
| 13 | +require_once( 'commandLine.inc' ); |
| 14 | +require_once( 'removeUnusedAccounts.inc' ); |
| 15 | +echo( "Remove Unused Accounts\n\n" ); |
| 16 | +$fname = 'removeUnusedAccounts'; |
13 | 17 | |
14 | | -class RemoveUnusedAccounts extends Maintenance { |
15 | | - public function __construct() { |
16 | | - parent::__construct(); |
17 | | - $this->addParam( 'delete', 'Actually delete the account' ); |
18 | | - $this->addParam( 'ignore-groups', 'List of comma-separated groups to exclude', false, true ); |
19 | | - $this->addParam( 'ignore-touched', 'Skip accounts touched in last N days', false, true ); |
20 | | - } |
| 18 | +if( isset( $options['help'] ) ) { |
| 19 | + showHelp(); |
| 20 | + exit(1); |
| 21 | +} |
21 | 22 | |
22 | | - public function execute() { |
23 | | - |
24 | | - $this->output( "Remove unused accounts\n\n" ); |
25 | | - |
26 | | - # Do an initial scan for inactive accounts and report the result |
27 | | - $this->output( "Checking for unused user accounts...\n" ); |
28 | | - $del = array(); |
29 | | - $dbr = wfGetDB( DB_SLAVE ); |
30 | | - $res = $dbr->select( 'user', array( 'user_id', 'user_name', 'user_touched' ), '', __METHOD__ ); |
31 | | - if( $this->hasOption('ignore-groups') ) { |
32 | | - $excludedGroups = explode( ',', $this->getOption('ignore-groups') ); |
33 | | - } else { |
34 | | - $excludedGroups = array(); |
| 23 | +# Do an initial scan for inactive accounts and report the result |
| 24 | +echo( "Checking for unused user accounts...\n" ); |
| 25 | +$del = array(); |
| 26 | +$dbr = wfGetDB( DB_SLAVE ); |
| 27 | +$res = $dbr->select( 'user', array( 'user_id', 'user_name', 'user_touched' ), '', $fname ); |
| 28 | +if( isset( $options['ignore-groups'] ) ) { |
| 29 | + $excludedGroups = explode( ',', $options['ignore-groups'] ); |
| 30 | +} else { $excludedGroups = array(); } |
| 31 | +$touchedSeconds = 0; |
| 32 | +if( isset( $options['ignore-touched'] ) ) { |
| 33 | + $touchedParamError = 0; |
| 34 | + if( ctype_digit( $options['ignore-touched'] ) ) { |
| 35 | + if( $options['ignore-touched'] <= 0 ) { |
| 36 | + $touchedParamError = 1; |
35 | 37 | } |
36 | | - $touched = $this->getOption( 'ignore-touched', "1" ); |
37 | | - if( !ctype_digit( $touched ) ) { |
38 | | - $this->error( "Please put a valid positive integer on the --ignore-touched parameter.\n", true ); |
39 | | - } |
40 | | - $touchedSeconds = 86400 * $touched; |
41 | | - while( $row = $dbr->fetchObject( $res ) ) { |
42 | | - # Check the account, but ignore it if it's within a $excludedGroups group or if it's touched within the $touchedSeconds seconds. |
43 | | - $instance = User::newFromId( $row->user_id ); |
44 | | - if( count( array_intersect( $instance->getEffectiveGroups(), $excludedGroups ) ) == 0 |
45 | | - && $this->isInactiveAccount( $row->user_id, true ) |
46 | | - && wfTimestamp( TS_UNIX, $row->user_touched ) < wfTimestamp( TS_UNIX, time() - $touchedSeconds ) |
47 | | - ) { |
48 | | - # Inactive; print out the name and flag it |
49 | | - $del[] = $row->user_id; |
50 | | - $this->output( $row->user_name . "\n" ); |
51 | | - } |
52 | | - } |
53 | | - $count = count( $del ); |
54 | | - $this->output( "...found {$count}.\n" ); |
55 | | - |
56 | | - # If required, go back and delete each marked account |
57 | | - if( $count > 0 && $this->hasOption('delete') ) { |
58 | | - $this->output( "\nDeleting inactive accounts..." ); |
59 | | - $dbw = wfGetDB( DB_MASTER ); |
60 | | - $dbw->delete( 'user', array( 'user_id' => $del ), __METHOD__ ); |
61 | | - $this->output( "done.\n" ); |
62 | | - # Update the site_stats.ss_users field |
63 | | - $users = $dbw->selectField( 'user', 'COUNT(*)', array(), __METHOD__ ); |
64 | | - $dbw->update( 'site_stats', array( 'ss_users' => $users ), array( 'ss_row_id' => 1 ), __METHOD__ ); |
65 | | - } elseif( $count > 0 ) { |
66 | | - $this->output( "\nRun the script again with --delete to remove them from the database.\n" ); |
67 | | - } |
68 | | - $this->output( "\n" ); |
| 38 | + } else { $touchedParamError = 1; } |
| 39 | + if( $touchedParamError == 1 ) { |
| 40 | + die( "Please put a valid positive integer on the --ignore-touched parameter.\n" ); |
| 41 | + } else { $touchedSeconds = 86400 * $options['ignore-touched']; } |
| 42 | +} |
| 43 | +while( $row = $dbr->fetchObject( $res ) ) { |
| 44 | + # Check the account, but ignore it if it's within a $excludedGroups group or if it's touched within the $touchedSeconds seconds. |
| 45 | + $instance = User::newFromId( $row->user_id ); |
| 46 | + if( count( array_intersect( $instance->getEffectiveGroups(), $excludedGroups ) ) == 0 |
| 47 | + && isInactiveAccount( $row->user_id, true ) |
| 48 | + && wfTimestamp( TS_UNIX, $row->user_touched ) < wfTimestamp( TS_UNIX, time() - $touchedSeconds ) |
| 49 | + ) { |
| 50 | + # Inactive; print out the name and flag it |
| 51 | + $del[] = $row->user_id; |
| 52 | + echo( $row->user_name . "\n" ); |
69 | 53 | } |
70 | | - |
71 | | - /** |
72 | | - * Could the specified user account be deemed inactive? |
73 | | - * (No edits, no deleted edits, no log entries, no current/old uploads) |
74 | | - * |
75 | | - * @param $id User's ID |
76 | | - * @param $master Perform checking on the master |
77 | | - * @return bool |
78 | | - */ |
79 | | - private function isInactiveAccount( $id, $master = false ) { |
80 | | - $dbo = wfGetDB( $master ? DB_MASTER : DB_SLAVE ); |
81 | | - $checks = array( 'revision' => 'rev', 'archive' => 'ar', 'logging' => 'log', |
82 | | - 'image' => 'img', 'oldimage' => 'oi' ); |
83 | | - $count = 0; |
84 | | - |
85 | | - $dbo->immediateBegin(); |
86 | | - foreach( $checks as $table => $fprefix ) { |
87 | | - $conds = array( $fprefix . '_user' => $id ); |
88 | | - $count += (int)$dbo->selectField( $table, 'COUNT(*)', $conds, __METHOD__ ); |
89 | | - } |
90 | | - $dbo->immediateCommit(); |
91 | | - |
92 | | - return $count == 0; |
93 | | - } |
94 | 54 | } |
| 55 | +$count = count( $del ); |
| 56 | +echo( "...found {$count}.\n" ); |
95 | 57 | |
96 | | -$maintClass = "RemoveUnusedAccounts"; |
97 | | -require_once( DO_MAINTENANCE ); |
| 58 | +# If required, go back and delete each marked account |
| 59 | +if( $count > 0 && isset( $options['delete'] ) ) { |
| 60 | + echo( "\nDeleting inactive accounts..." ); |
| 61 | + $dbw = wfGetDB( DB_MASTER ); |
| 62 | + $dbw->delete( 'user', array( 'user_id' => $del ), $fname ); |
| 63 | + echo( "done.\n" ); |
| 64 | + # Update the site_stats.ss_users field |
| 65 | + $users = $dbw->selectField( 'user', 'COUNT(*)', array(), $fname ); |
| 66 | + $dbw->update( 'site_stats', array( 'ss_users' => $users ), array( 'ss_row_id' => 1 ), $fname ); |
| 67 | +} else { |
| 68 | + if( $count > 0 ) |
| 69 | + echo( "\nRun the script again with --delete to remove them from the database.\n" ); |
| 70 | +} |
| 71 | +echo( "\n" ); |
Index: trunk/phase3/maintenance/initStats.php |
— | — | @@ -9,22 +9,23 @@ |
10 | 10 | * @author Rob Church <robchur@gmail.com> |
11 | 11 | * @licence GNU General Public Licence 2.0 or later |
12 | 12 | */ |
| 13 | + |
| 14 | +$options = array( 'help', 'update', 'noviews' ); |
| 15 | +require_once( 'commandLine.inc' ); |
| 16 | +echo( "Refresh Site Statistics\n\n" ); |
13 | 17 | |
14 | | -require_once( "Maintenance.php" ); |
| 18 | +if( isset( $options['help'] ) ) { |
| 19 | + showHelp(); |
| 20 | + exit(1); |
| 21 | +} |
15 | 22 | |
16 | | -class InitStats extends Maintenance { |
17 | | - public function __construct() { |
18 | | - parent::__construct(); |
19 | | - $this->mDescription = "Re-initialise the site statistics tables"; |
20 | | - $this->addParam( 'update', 'Update the existing statistics (preserves the ss_total_views field)' ); |
21 | | - $this->addParam( 'noviews', "Don't update the page view counter" ); |
22 | | - } |
| 23 | +require "$IP/maintenance/initStats.inc"; |
| 24 | +wfInitStats( $options ); |
23 | 25 | |
24 | | - public function execute() { |
25 | | - $this->output( "Refresh Site Statistics\n\n" ); |
26 | | - SiteStats::init( $this->hasOption('update'), $this->hasOption('noviews') ); |
27 | | - } |
| 26 | +function showHelp() { |
| 27 | + echo( "Re-initialise the site statistics tables.\n\n" ); |
| 28 | + echo( "Usage: php initStats.php [--update|--noviews]\n\n" ); |
| 29 | + echo( " --update : Update the existing statistics (preserves the ss_total_views field)\n" ); |
| 30 | + echo( "--noviews : Don't update the page view counter\n\n" ); |
28 | 31 | } |
29 | 32 | |
30 | | -$maintClass = "InitStats"; |
31 | | -require_once( DO_MAINTENANCE ); |
Index: trunk/phase3/maintenance/runJobs.php |
— | — | @@ -10,77 +10,71 @@ |
11 | 11 | * @ingroup Maintenance |
12 | 12 | */ |
13 | 13 | |
14 | | -require_once( "Maintenance.php" ); |
| 14 | +$optionsWithArgs = array( 'maxjobs', 'type', 'procs' ); |
| 15 | +$wgUseNormalUser = true; |
| 16 | +require_once( 'commandLine.inc' ); |
15 | 17 | |
16 | | -class RunJobs extends Maintenance { |
17 | | - public function __construct() { |
18 | | - global $wgUseNormalUser; |
19 | | - parent::__construct(); |
20 | | - $this->mDescription = "Run pending jobs"; |
21 | | - $this->addParam( 'maxjobs', 'Maximum number of jobs to run', false, true ); |
22 | | - $this->addParam( 'type', 'Type of job to run', false, true ); |
23 | | - $this->addParam( 'procs', 'Number of processes to use', false, true ); |
24 | | - $wgUseNormalUser = true; |
| 18 | +if ( isset( $options['procs'] ) ) { |
| 19 | + $procs = intval( $options['procs'] ); |
| 20 | + if ( $procs < 1 || $procs > 1000 ) { |
| 21 | + echo "Invalid argument to --procs\n"; |
| 22 | + exit( 1 ); |
25 | 23 | } |
| 24 | + $fc = new ForkController( $procs ); |
| 25 | + if ( $fc->start( $procs ) != 'child' ) { |
| 26 | + exit( 0 ); |
| 27 | + } |
| 28 | +} |
26 | 29 | |
27 | | - public function execute() { |
28 | | - global $wgTitle; |
29 | | - if ( $this->hasOption( 'procs' ) ) { |
30 | | - $procs = intval( $this->getOption('procs') ); |
31 | | - if ( $procs < 1 || $procs > 1000 ) { |
32 | | - $this->error( "Invalid argument to --procs\n", true ); |
33 | | - } |
34 | | - $fc = new ForkController( $procs ); |
35 | | - if ( $fc->start( $procs ) != 'child' ) { |
36 | | - exit( 0 ); |
37 | | - } |
38 | | - } |
39 | | - $maxJobs = $this->getOption( 'maxjobs', 10000 ); |
40 | | - $type = $this->getOption( 'type', false ); |
41 | | - $wgTitle = Title::newFromText( 'RunJobs.php' ); |
42 | | - $dbw = wfGetDB( DB_MASTER ); |
43 | | - $n = 0; |
44 | | - $conds = ''; |
45 | | - if ($type !== false) |
46 | | - $conds = "job_cmd = " . $dbw->addQuotes($type); |
| 30 | +if ( isset( $options['maxjobs'] ) ) { |
| 31 | + $maxJobs = $options['maxjobs']; |
| 32 | +} else { |
| 33 | + $maxJobs = 10000; |
| 34 | +} |
47 | 35 | |
48 | | - while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) { |
49 | | - $offset=0; |
50 | | - for (;;) { |
51 | | - $job = ($type == false) ? |
52 | | - Job::pop($offset) |
53 | | - : Job::pop_type($type); |
54 | | - |
55 | | - if ($job == false) |
56 | | - break; |
57 | | - |
58 | | - wfWaitForSlaves( 5 ); |
59 | | - $t = microtime( true ); |
60 | | - $offset=$job->id; |
61 | | - $status = $job->run(); |
62 | | - $t = microtime( true ) - $t; |
63 | | - $timeMs = intval( $t * 1000 ); |
64 | | - if ( !$status ) { |
65 | | - $this->runJobsLog( $job->toString() . " t=$timeMs error={$job->error}" ); |
66 | | - } else { |
67 | | - $this->runJobsLog( $job->toString() . " t=$timeMs good" ); |
68 | | - } |
69 | | - if ( $maxJobs && ++$n > $maxJobs ) { |
70 | | - break 2; |
71 | | - } |
72 | | - } |
| 36 | +$type = false; |
| 37 | +if ( isset( $options['type'] ) ) |
| 38 | + $type = $options['type']; |
| 39 | + |
| 40 | +$wgTitle = Title::newFromText( 'RunJobs.php' ); |
| 41 | + |
| 42 | +$dbw = wfGetDB( DB_MASTER ); |
| 43 | +$n = 0; |
| 44 | +$conds = ''; |
| 45 | +if ($type !== false) |
| 46 | + $conds = "job_cmd = " . $dbw->addQuotes($type); |
| 47 | + |
| 48 | +while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) { |
| 49 | + $offset=0; |
| 50 | + for (;;) { |
| 51 | + $job = ($type == false) ? |
| 52 | + Job::pop($offset) |
| 53 | + : Job::pop_type($type); |
| 54 | + |
| 55 | + if ($job == false) |
| 56 | + break; |
| 57 | + |
| 58 | + wfWaitForSlaves( 5 ); |
| 59 | + $t = microtime( true ); |
| 60 | + $offset=$job->id; |
| 61 | + $status = $job->run(); |
| 62 | + $t = microtime( true ) - $t; |
| 63 | + $timeMs = intval( $t * 1000 ); |
| 64 | + if ( !$status ) { |
| 65 | + runJobsLog( $job->toString() . " t=$timeMs error={$job->error}" ); |
| 66 | + } else { |
| 67 | + runJobsLog( $job->toString() . " t=$timeMs good" ); |
73 | 68 | } |
| 69 | + if ( $maxJobs && ++$n > $maxJobs ) { |
| 70 | + break 2; |
| 71 | + } |
74 | 72 | } |
| 73 | +} |
75 | 74 | |
76 | | - /** |
77 | | - * Log the job message |
78 | | - * @param $msg String The message to log |
79 | | - */ |
80 | | - private function runJobsLog( $msg ) { |
81 | | - $this->output( wfTimestamp( TS_DB ) . " $msg\n" ); |
82 | | - wfDebugLog( 'runJobs', $msg ); |
83 | | - } |
| 75 | + |
| 76 | +function runJobsLog( $msg ) { |
| 77 | + print wfTimestamp( TS_DB ) . " $msg\n"; |
| 78 | + wfDebugLog( 'runJobs', $msg ); |
84 | 79 | } |
85 | 80 | |
86 | | -$maintClass = "RunJobs"; |
87 | | -require_once( DO_MAINTENANCE ); |
| 81 | + |
Index: trunk/phase3/maintenance/updateSearchIndex.php |
— | — | @@ -5,159 +5,58 @@ |
6 | 6 | * Usage: php updateSearchIndex.php [-s START] [-e END] [-p POSFILE] [-l LOCKTIME] [-q] |
7 | 7 | * Where START is the starting timestamp |
8 | 8 | * END is the ending timestamp |
9 | | - * POSFILE is a file to load timestamps from and save them to, searchUpdate.WIKI_ID.pos by default |
10 | | - * LOCKTIME is how long the searchindex and revision tables will be locked for |
| 9 | + * POSFILE is a file to load timestamps from and save them to, searchUpdate.pos by default |
| 10 | + * LOCKTIME is how long the searchindex and cur tables will be locked for |
11 | 11 | * -q means quiet |
12 | 12 | * |
| 13 | + * @file |
13 | 14 | * @ingroup Maintenance |
14 | 15 | */ |
15 | | - |
16 | | -require_once( "Maintenance.php" ); |
17 | 16 | |
18 | | -class UpdateSearchIndex extends Maintenance { |
| 17 | +/** */ |
| 18 | +$optionsWithArgs = array( 's', 'e', 'p' ); |
19 | 19 | |
20 | | - public function __construct() { |
21 | | - parent::__construct(); |
22 | | - $this->mDescription = "Script for periodic off-peak updating of the search index"; |
23 | | - $this->addParam( 's', 'starting timestamp', false, true ); |
24 | | - $this->addParam( 'e', 'Ending timestamp', false, true ); |
25 | | - $this->addParam( 'p', 'File for saving/loading timestamps, searchUpdate.WIKI_ID.pos by default', false, true ); |
26 | | - $this->addParam( 'l', 'How long the searchindex and revision tables will be locked for', false, true ); |
27 | | - } |
| 20 | +require_once( 'commandLine.inc' ); |
| 21 | +require_once( 'updateSearchIndex.inc' ); |
28 | 22 | |
29 | | - public function execute() { |
30 | | - $posFile = $this->getOption( 'p', 'searchUpdate.' . wfWikiId() . '.pos' ); |
31 | | - $end = $this->getOption( 'e', wfTimestampNow() ); |
32 | | - if ( $this->hasOption( 's' ) ) { |
33 | | - $start = $this->getOption('s'); |
34 | | - } elseif( is_readable( 'searchUpdate.pos' ) ) { |
35 | | - # B/c to the old position file name which was hardcoded |
36 | | - # We can safely delete the file when we're done though. |
37 | | - $start = file_get_contents( 'searchUpdate.pos' ); |
38 | | - unlink( 'searchUpdate.pos' ); |
39 | | - } else { |
40 | | - $start = @file_get_contents( $posFile ); |
41 | | - if ( !$start ) { |
42 | | - $start = wfTimestamp( TS_MW, time() - 86400 ); |
43 | | - } |
44 | | - } |
45 | | - $lockTime = $this->getOption( 'l', 20 ); |
46 | | - |
47 | | - $this->updateSearchIndex( $start, $end, $lockTime ); |
48 | | - $file = fopen( $posFile, 'w' ); |
49 | | - fwrite( $file, $end ); |
50 | | - fclose( $file ); |
51 | | - } |
52 | | - |
53 | | - private function updateSearchIndex( $start, $end, $maxLockTime ) { |
54 | | - global $wgDisableSearchUpdate; |
| 23 | +if ( isset( $options['p'] ) ) { |
| 24 | + $posFile = $options['p']; |
| 25 | +} else { |
| 26 | + $posFile = 'searchUpdate.' . wfWikiId() . '.pos'; |
| 27 | +} |
55 | 28 | |
56 | | - $wgDisableSearchUpdate = false; |
| 29 | +if ( isset( $options['e'] ) ) { |
| 30 | + $end = $options['e']; |
| 31 | +} else { |
| 32 | + $end = wfTimestampNow(); |
| 33 | +} |
57 | 34 | |
58 | | - $dbw = wfGetDB( DB_MASTER ); |
59 | | - $recentchanges = $dbw->tableName( 'recentchanges' ); |
| 35 | +if ( isset( $options['s'] ) ) { |
| 36 | + $start = $options['s']; |
| 37 | +} elseif( is_readable( 'searchUpdate.pos' ) ) { |
| 38 | + # B/c to the old position file name which was hardcoded |
| 39 | + # We can safely delete the file when we're done though. |
| 40 | + $start = file_get_contents( 'searchUpdate.pos' ); |
| 41 | + unlink( 'searchUpdate.pos' ); |
| 42 | +} else { |
| 43 | + $start = @file_get_contents( $posFile ); |
| 44 | + if ( !$start ) { |
| 45 | + $start = wfTimestamp( TS_MW, time() - 86400 ); |
| 46 | + } |
| 47 | +} |
60 | 48 | |
61 | | - $this->output( "Updating searchindex between $start and $end\n" ); |
| 49 | +if ( isset( $options['l'] ) ) { |
| 50 | + $lockTime = $options['l']; |
| 51 | +} else { |
| 52 | + $lockTime = 20; |
| 53 | +} |
62 | 54 | |
63 | | - # Select entries from recentchanges which are on top and between the specified times |
64 | | - $start = $dbw->strencode( $start ); |
65 | | - $end = $dbw->strencode( $end ); |
| 55 | +$quiet = (bool)(@$options['q']); |
66 | 56 | |
67 | | - $page = $dbw->tableName( 'page' ); |
68 | | - $sql = "SELECT rc_cur_id,rc_type,rc_moved_to_ns,rc_moved_to_title FROM $recentchanges |
69 | | - JOIN $page ON rc_cur_id=page_id AND rc_this_oldid=page_latest |
70 | | - WHERE rc_timestamp BETWEEN '$start' AND '$end' |
71 | | - "; |
72 | | - $res = $dbw->query( $sql, __METHOD__ ); |
| 57 | +updateSearchIndex( $start, $end, $lockTime, $quiet ); |
73 | 58 | |
| 59 | +$file = fopen( $posFile, 'w' ); |
| 60 | +fwrite( $file, $end ); |
| 61 | +fclose( $file ); |
74 | 62 | |
75 | | - # Lock searchindex |
76 | | - if ( $maxLockTime ) { |
77 | | - $this->output( " --- Waiting for lock ---" ); |
78 | | - $this->lockSearchindex( $dbw ); |
79 | | - $lockTime = time(); |
80 | | - $this->output( "\n" ); |
81 | | - } |
82 | 63 | |
83 | | - # Loop through the results and do a search update |
84 | | - while ( $row = $dbw->fetchObject( $res ) ) { |
85 | | - # Allow reads to be processed |
86 | | - if ( $maxLockTime && time() > $lockTime + $maxLockTime ) { |
87 | | - $this->output( " --- Relocking ---" ); |
88 | | - $this->relockSearchindex( $dbw ); |
89 | | - $lockTime = time(); |
90 | | - $this->output( "\n" ); |
91 | | - } |
92 | | - if ( $row->rc_type == RC_LOG ) { |
93 | | - continue; |
94 | | - } elseif ( $row->rc_type == RC_MOVE || $row->rc_type == RC_MOVE_OVER_REDIRECT ) { |
95 | | - # Rename searchindex entry |
96 | | - $titleObj = Title::makeTitle( $row->rc_moved_to_ns, $row->rc_moved_to_title ); |
97 | | - $title = $titleObj->getPrefixedDBkey(); |
98 | | - $this->output( "$title..." ); |
99 | | - $u = new SearchUpdate( $row->rc_cur_id, $title, false ); |
100 | | - $this->output( "\n" ); |
101 | | - } else { |
102 | | - // Get current revision |
103 | | - $rev = Revision::loadFromPageId( $dbw, $row->rc_cur_id ); |
104 | | - if( $rev ) { |
105 | | - $titleObj = $rev->getTitle(); |
106 | | - $title = $titleObj->getPrefixedDBkey(); |
107 | | - $this->output( $title ); |
108 | | - # Update searchindex |
109 | | - $u = new SearchUpdate( $row->rc_cur_id, $titleObj->getText(), $rev->getText() ); |
110 | | - $u->doUpdate(); |
111 | | - $this->output( "\n" ); |
112 | | - } |
113 | | - } |
114 | | - } |
115 | | - |
116 | | - # Unlock searchindex |
117 | | - if ( $maxLockTime ) { |
118 | | - $this->output( " --- Unlocking --" ); |
119 | | - $this->unlockSearchindex( $dbw ); |
120 | | - $this->output( "\n" ); |
121 | | - } |
122 | | - $this->output( "Done\n" ); |
123 | | - } |
124 | | - |
125 | | - /** |
126 | | - * Lock the search index |
127 | | - * @param &$db Database object |
128 | | - */ |
129 | | - private function lockSearchindex( &$db ) { |
130 | | - $write = array( 'searchindex' ); |
131 | | - $read = array( 'page', 'revision', 'text', 'interwiki' ); |
132 | | - $items = array(); |
133 | | - |
134 | | - foreach( $write as $table ) { |
135 | | - $items[] = $db->tableName( $table ) . ' LOW_PRIORITY WRITE'; |
136 | | - } |
137 | | - foreach( $read as $table ) { |
138 | | - $items[] = $db->tableName( $table ) . ' READ'; |
139 | | - } |
140 | | - $sql = "LOCK TABLES " . implode( ',', $items ); |
141 | | - $db->query( $sql, 'updateSearchIndex.php ' . __METHOD__ ); |
142 | | - } |
143 | | - |
144 | | - /** |
145 | | - * Unlock the tables |
146 | | - * @param &$db Database object |
147 | | - */ |
148 | | - private function unlockSearchindex( &$db ) { |
149 | | - $db->query( "UNLOCK TABLES", 'updateSearchIndex.php ' . __METHOD__ ); |
150 | | - } |
151 | | - |
152 | | - /** |
153 | | - * Unlock and lock again |
154 | | - * Since the lock is low-priority, queued reads will be able to complete |
155 | | - * @param &$db Database object |
156 | | - */ |
157 | | - private function relockSearchindex( &$db ) { |
158 | | - $this->unlockSearchindex( $db ); |
159 | | - $this->lockSearchindex( $db ); |
160 | | - } |
161 | | -} |
162 | | - |
163 | | -$maintClass = "UpdateSearchIndex"; |
164 | | -require_once( DO_MAINTENANCE ); |
Index: trunk/phase3/maintenance/moveBatch.php |
— | — | @@ -1,7 +1,9 @@ |
2 | 2 | <?php |
| 3 | + |
3 | 4 | /** |
4 | 5 | * Maintenance script to move a batch of pages |
5 | 6 | * |
| 7 | + * @file |
6 | 8 | * @ingroup Maintenance |
7 | 9 | * @author Tim Starling |
8 | 10 | * |
— | — | @@ -18,77 +20,77 @@ |
19 | 21 | * e.g. immobile_namespace for namespaces which can't be moved |
20 | 22 | */ |
21 | 23 | |
22 | | -require_once( "Maintenance.php" ); |
| 24 | +$oldCwd = getcwd(); |
| 25 | +$optionsWithArgs = array( 'u', 'r', 'i' ); |
| 26 | +require_once( 'commandLine.inc' ); |
23 | 27 | |
24 | | -class MoveBatch extends Maintenance { |
25 | | - public function __construct() { |
26 | | - parent::__construct(); |
27 | | - $this->mDescription = "Moves a batch of pages"; |
28 | | - $this->addParam( 'u', "User to perform move", false, true ); |
29 | | - $this->addParam( 'r', "Reason to move page", false, true ); |
30 | | - $this->addParam( 'i', "Interval to sleep between moves" ); |
31 | | - $this->addArgs( array( 'listfile' ) ); |
| 28 | +chdir( $oldCwd ); |
| 29 | + |
| 30 | +# Options processing |
| 31 | + |
| 32 | +$filename = 'php://stdin'; |
| 33 | +$user = 'Move page script'; |
| 34 | +$reason = ''; |
| 35 | +$interval = 0; |
| 36 | + |
| 37 | +if ( isset( $args[0] ) ) { |
| 38 | + $filename = $args[0]; |
| 39 | +} |
| 40 | +if ( isset( $options['u'] ) ) { |
| 41 | + $user = $options['u']; |
| 42 | +} |
| 43 | +if ( isset( $options['r'] ) ) { |
| 44 | + $reason = $options['r']; |
| 45 | +} |
| 46 | +if ( isset( $options['i'] ) ) { |
| 47 | + $interval = $options['i']; |
| 48 | +} |
| 49 | + |
| 50 | +$wgUser = User::newFromName( $user ); |
| 51 | + |
| 52 | + |
| 53 | +# Setup complete, now start |
| 54 | + |
| 55 | +$file = fopen( $filename, 'r' ); |
| 56 | +if ( !$file ) { |
| 57 | + print "Unable to read file, exiting\n"; |
| 58 | + exit; |
| 59 | +} |
| 60 | + |
| 61 | +$dbw = wfGetDB( DB_MASTER ); |
| 62 | + |
| 63 | +for ( $linenum = 1; !feof( $file ); $linenum++ ) { |
| 64 | + $line = fgets( $file ); |
| 65 | + if ( $line === false ) { |
| 66 | + break; |
32 | 67 | } |
33 | | - |
34 | | - public function execute() { |
35 | | - global $wgUser; |
| 68 | + $parts = array_map( 'trim', explode( '|', $line ) ); |
| 69 | + if ( count( $parts ) != 2 ) { |
| 70 | + print "Error on line $linenum, no pipe character\n"; |
| 71 | + continue; |
| 72 | + } |
| 73 | + $source = Title::newFromText( $parts[0] ); |
| 74 | + $dest = Title::newFromText( $parts[1] ); |
| 75 | + if ( is_null( $source ) || is_null( $dest ) ) { |
| 76 | + print "Invalid title on line $linenum\n"; |
| 77 | + continue; |
| 78 | + } |
36 | 79 | |
37 | | - # Change to current working directory |
38 | | - $oldCwd = getcwd(); |
39 | | - chdir( $oldCwd ); |
40 | 80 | |
41 | | - # Options processing |
42 | | - $user = $this->getOption( 'u', 'Move page script' ); |
43 | | - $reason = $this->getOption( 'r', '' ); |
44 | | - $interval = $this->getOption( 'i', 0 ); |
45 | | - if( $this->hasArg() ) { |
46 | | - $file = fopen( $this->getArg(), 'r' ); |
47 | | - } else { |
48 | | - $file = $this->getStdin(); |
49 | | - } |
| 81 | + print $source->getPrefixedText() . ' --> ' . $dest->getPrefixedText(); |
| 82 | + $dbw->begin(); |
| 83 | + $err = $source->moveTo( $dest, false, $reason ); |
| 84 | + if( $err !== true ) { |
| 85 | + print "\nFAILED: $err"; |
| 86 | + } |
| 87 | + $dbw->immediateCommit(); |
| 88 | + print "\n"; |
50 | 89 | |
51 | | - # Setup |
52 | | - if( !$file ) { |
53 | | - $this->error( "Unable to read file, exiting\n", true ); |
54 | | - } |
55 | | - $wgUser = User::newFromName( $user ); |
56 | | - |
57 | | - # Setup complete, now start |
58 | | - $dbw = wfGetDB( DB_MASTER ); |
59 | | - for ( $linenum = 1; !feof( $file ); $linenum++ ) { |
60 | | - $line = fgets( $file ); |
61 | | - if ( $line === false ) { |
62 | | - break; |
63 | | - } |
64 | | - $parts = array_map( 'trim', explode( '|', $line ) ); |
65 | | - if ( count( $parts ) != 2 ) { |
66 | | - $this->error( "Error on line $linenum, no pipe character\n" ); |
67 | | - continue; |
68 | | - } |
69 | | - $source = Title::newFromText( $parts[0] ); |
70 | | - $dest = Title::newFromText( $parts[1] ); |
71 | | - if ( is_null( $source ) || is_null( $dest ) ) { |
72 | | - $this->error( "Invalid title on line $linenum\n" ); |
73 | | - continue; |
74 | | - } |
75 | | - |
76 | | - |
77 | | - $this->output( $source->getPrefixedText() . ' --> ' . $dest->getPrefixedText() ); |
78 | | - $dbw->begin(); |
79 | | - $err = $source->moveTo( $dest, false, $reason ); |
80 | | - if( $err !== true ) { |
81 | | - $this->output( "\nFAILED: $err" ); |
82 | | - } |
83 | | - $dbw->immediateCommit(); |
84 | | - $this->output( "\n" ); |
85 | | - |
86 | | - if ( $interval ) { |
87 | | - sleep( $interval ); |
88 | | - } |
89 | | - wfWaitForSlaves( 5 ); |
90 | | - } |
| 90 | + if ( $interval ) { |
| 91 | + sleep( $interval ); |
91 | 92 | } |
| 93 | + wfWaitForSlaves( 5 ); |
92 | 94 | } |
93 | 95 | |
94 | | -$maintClass = "MoveBatch"; |
95 | | -require_once( DO_MAINTENANCE ); |
| 96 | + |
| 97 | + |
Index: trunk/phase3/maintenance/refreshImageCount.php |
— | — | @@ -7,34 +7,23 @@ |
8 | 8 | * @ingroup Maintenance |
9 | 9 | */ |
10 | 10 | |
11 | | -require_once( "Maintenance.php" ); |
| 11 | +require_once( "commandLine.inc" ); |
12 | 12 | |
13 | | -class RefreshImageCount extends Maintenance { |
14 | | - public function __construct() { |
15 | | - parent::__construct(); |
16 | | - $this->mDescription = "Resets ss_image count, forcing slaves to pick it up."; |
17 | | - } |
18 | | - |
19 | | - public function execute() { |
20 | | - $dbw = wfGetDB( DB_MASTER ); |
| 13 | +$dbw = wfGetDB( DB_MASTER ); |
21 | 14 | |
22 | | - // Load the current value from the master |
23 | | - $count = $dbw->selectField( 'site_stats', 'ss_images' ); |
| 15 | +// Load the current value from the master |
| 16 | +$count = $dbw->selectField( 'site_stats', 'ss_images' ); |
24 | 17 | |
25 | | - $this->output( wfWikiID() . ": forcing ss_images to $count\n" ); |
| 18 | +echo wfWikiID().": forcing ss_images to $count\n"; |
26 | 19 | |
27 | | - // First set to NULL so that it changes on the master |
28 | | - $dbw->update( 'site_stats', |
29 | | - array( 'ss_images' => null ), |
30 | | - array( 'ss_row_id' => 1 ) ); |
31 | | - |
32 | | - // Now this update will be forced to go out |
33 | | - $dbw->update( 'site_stats', |
34 | | - array( 'ss_images' => $count ), |
35 | | - array( 'ss_row_id' => 1 ) ); |
36 | | - } |
37 | | -} |
| 20 | +// First set to NULL so that it changes on the master |
| 21 | +$dbw->update( 'site_stats', |
| 22 | + array( 'ss_images' => null ), |
| 23 | + array( 'ss_row_id' => 1 ) ); |
38 | 24 | |
39 | | -$maintClass = "RefreshImageCount"; |
40 | | -require_once( DO_MAINTENANCE ); |
| 25 | +// Now this update will be forced to go out |
| 26 | +$dbw->update( 'site_stats', |
| 27 | + array( 'ss_images' => $count ), |
| 28 | + array( 'ss_row_id' => 1 ) ); |
41 | 29 | |
| 30 | + |
Index: trunk/phase3/maintenance/purgeOldText.php |
— | — | @@ -1,24 +1,29 @@ |
2 | 2 | <?php |
| 3 | + |
3 | 4 | /** |
4 | 5 | * Purge old text records from the database |
5 | 6 | * |
| 7 | + * @file |
6 | 8 | * @ingroup Maintenance |
7 | 9 | * @author Rob Church <robchur@gmail.com> |
8 | 10 | */ |
9 | 11 | |
10 | | -require_once( "Maintenance.php" ); |
| 12 | +$options = array( 'purge', 'help' ); |
| 13 | +require_once( 'commandLine.inc' ); |
| 14 | +require_once( 'purgeOldText.inc' ); |
11 | 15 | |
12 | | -class PurgeOldText extends Maintenance { |
13 | | - public function __construct() { |
14 | | - parent::__construct(); |
15 | | - $this->mDescription = "Purge old text records from the database"; |
16 | | - $this->addOption( 'purge', 'Performs the deletion' ); |
17 | | - } |
18 | | - |
19 | | - public function execute() { |
20 | | - $this->purgeRedundantText( $this->hasOption('purge') ); |
21 | | - } |
| 16 | +echo( "Purge Old Text\n\n" ); |
| 17 | + |
| 18 | +if( @$options['help'] ) { |
| 19 | + ShowUsage(); |
| 20 | +} else { |
| 21 | + PurgeRedundantText( @$options['purge'] ); |
22 | 22 | } |
23 | 23 | |
24 | | -$maintClass = "PurgeOldText"; |
25 | | -require_once( DO_MAINTENANCE ); |
| 24 | +function ShowUsage() { |
| 25 | + echo( "Prunes unused text records from the database.\n\n" ); |
| 26 | + echo( "Usage: php purgeOldText.php [--purge]\n\n" ); |
| 27 | + echo( "purge : Performs the deletion\n" ); |
| 28 | + echo( " help : Show this usage information\n" ); |
| 29 | +} |
| 30 | + |
Index: trunk/phase3/maintenance/Doxyfile |
— | — | @@ -135,7 +135,7 @@ |
136 | 136 | RECURSIVE = YES |
137 | 137 | EXCLUDE = |
138 | 138 | EXCLUDE_SYMLINKS = YES |
139 | | -EXCLUDE_PATTERNS = LocalSettings.php |
| 139 | +EXCLUDE_PATTERNS = LocalSettings.php AdminSettings.php |
140 | 140 | EXAMPLE_PATH = |
141 | 141 | EXAMPLE_PATTERNS = * |
142 | 142 | EXAMPLE_RECURSIVE = NO |
Index: trunk/phase3/maintenance/getSlaveServer.php |
— | — | @@ -5,32 +5,24 @@ |
6 | 6 | * @file |
7 | 7 | * @ingroup Maintenance |
8 | 8 | */ |
9 | | - |
10 | | -require_once( "Maintenance.php" ); |
11 | 9 | |
12 | | -class GetSlaveServer extends Maintenance { |
13 | | - public function __construct() { |
14 | | - parent::__construct(); |
15 | | - $this->addParam( "group", "Query group to check specifically" ); |
16 | | - $this->mDescription = "Report the hostname of a slave server"; |
17 | | - } |
18 | | - public function execute() { |
19 | | - global $wgAllDBsAreLocalhost; |
20 | | - if( $wgAllDBsAreLocalhost ) { |
21 | | - $host = 'localhost'; |
22 | | - } else { |
23 | | - if( $this->hasOption('group') ) { |
24 | | - $db = wfGetDB( DB_SLAVE, $this->getOption('group') ); |
25 | | - $host = $db->getServer(); |
26 | | - } else { |
27 | | - $lb = wfGetLB(); |
28 | | - $i = $lb->getReaderIndex(); |
29 | | - $host = $lb->getServerName( $i ); |
30 | | - } |
31 | | - } |
32 | | - $this->output( "$host\n" ); |
33 | | - } |
| 10 | +require_once( dirname(__FILE__).'/commandLine.inc' ); |
| 11 | + |
| 12 | +if ( $wgAllDBsAreLocalhost ) { |
| 13 | + # Can't fool the backup script |
| 14 | + print "localhost\n"; |
| 15 | + exit; |
34 | 16 | } |
35 | 17 | |
36 | | -$maintClass = "GetSlaveServer"; |
37 | | -require_once( DO_MAINTENANCE ); |
| 18 | +if( isset( $options['group'] ) ) { |
| 19 | + $db = wfGetDB( DB_SLAVE, $options['group'] ); |
| 20 | + $host = $db->getServer(); |
| 21 | +} else { |
| 22 | + $lb = wfGetLB(); |
| 23 | + $i = $lb->getReaderIndex(); |
| 24 | + $host = $lb->getServerName( $i ); |
| 25 | +} |
| 26 | + |
| 27 | +print "$host\n"; |
| 28 | + |
| 29 | + |
Index: trunk/phase3/maintenance/renderDump.php |
— | — | @@ -27,61 +27,42 @@ |
28 | 28 | * @file |
29 | 29 | * @ingroup Maintenance |
30 | 30 | */ |
31 | | - |
32 | | -require_once( "Maintenance.php" ); |
33 | 31 | |
34 | | -class DumpRenderer extends Maintenance { |
| 32 | +$optionsWithArgs = array( 'report' ); |
35 | 33 | |
36 | | - private $count = 0; |
37 | | - private $outputDirectory, $startTime; |
| 34 | +require_once( 'commandLine.inc' ); |
38 | 35 | |
39 | | - public function __construct() { |
40 | | - parent::__construct(); |
41 | | - $this->mDescription = "Take page text out of an XML dump file and render basic HTML out to files"; |
42 | | - $this->addParam( 'output-dir', 'The directory to output the HTML files to', true, true ); |
| 36 | +class DumpRenderer { |
| 37 | + function __construct( $dir ) { |
| 38 | + $this->stderr = fopen( "php://stderr", "wt" ); |
| 39 | + $this->outputDirectory = $dir; |
| 40 | + $this->count = 0; |
43 | 41 | } |
44 | 42 | |
45 | | - public function execute() { |
46 | | - $this->outputDirectory = $this->getOption( 'output-dir' ); |
47 | | - $this->startTime = wfTime(); |
48 | | - |
49 | | - $source = new ImportStreamSource( $this->getStdin() ); |
50 | | - $importer = new WikiImporter( $source ); |
51 | | - |
52 | | - $importer->setRevisionCallback( |
53 | | - array( &$this, 'handleRevision' ) ); |
54 | | - |
55 | | - return $importer->doImport(); |
56 | | - } |
57 | | - |
58 | | - /** |
59 | | - * Callback function for each revision, turn into HTML and save |
60 | | - * @param $rev Revision |
61 | | - */ |
62 | | - private function handleRevision( $rev ) { |
| 43 | + function handleRevision( $rev ) { |
63 | 44 | $title = $rev->getTitle(); |
64 | 45 | if (!$title) { |
65 | | - $this->error( "Got bogus revision with null title!" ); |
| 46 | + fprintf( $this->stderr, "Got bogus revision with null title!" ); |
66 | 47 | return; |
67 | 48 | } |
68 | 49 | $display = $title->getPrefixedText(); |
69 | | - |
| 50 | + |
70 | 51 | $this->count++; |
71 | | - |
| 52 | + |
72 | 53 | $sanitized = rawurlencode( $display ); |
73 | 54 | $filename = sprintf( "%s/wiki-%07d-%s.html", |
74 | 55 | $this->outputDirectory, |
75 | 56 | $this->count, |
76 | 57 | $sanitized ); |
77 | | - $this->output( sprintf( $this->stderr, "%s\n", $filename, $display ) ); |
78 | | - |
79 | | - // fixme (what?) |
| 58 | + fprintf( $this->stderr, "%s\n", $filename, $display ); |
| 59 | + |
| 60 | + // fixme |
80 | 61 | $user = new User(); |
81 | 62 | $parser = new Parser(); |
82 | 63 | $options = ParserOptions::newFromUser( $user ); |
83 | | - |
| 64 | + |
84 | 65 | $output = $parser->parse( $rev->getText(), $title, $options ); |
85 | | - |
| 66 | + |
86 | 67 | file_put_contents( $filename, |
87 | 68 | "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" " . |
88 | 69 | "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" . |
— | — | @@ -95,7 +76,27 @@ |
96 | 77 | "</body>\n" . |
97 | 78 | "</html>" ); |
98 | 79 | } |
| 80 | + |
| 81 | + function run() { |
| 82 | + $this->startTime = wfTime(); |
| 83 | + |
| 84 | + $file = fopen( 'php://stdin', 'rt' ); |
| 85 | + $source = new ImportStreamSource( $file ); |
| 86 | + $importer = new WikiImporter( $source ); |
| 87 | + |
| 88 | + $importer->setRevisionCallback( |
| 89 | + array( &$this, 'handleRevision' ) ); |
| 90 | + |
| 91 | + return $importer->doImport(); |
| 92 | + } |
99 | 93 | } |
100 | 94 | |
101 | | -$maintClass = "DumpRenderer"; |
102 | | -require_once( DO_MAINTENANCE ); |
| 95 | +if( isset( $options['output-dir'] ) ) { |
| 96 | + $dir = $options['output-dir']; |
| 97 | +} else { |
| 98 | + wfDie( "Must use --output-dir=/some/dir\n" ); |
| 99 | +} |
| 100 | +$render = new DumpRenderer( $dir ); |
| 101 | +$render->run(); |
| 102 | + |
| 103 | + |
Index: trunk/phase3/maintenance/changePassword.php |
— | — | @@ -10,32 +10,47 @@ |
11 | 11 | * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later |
12 | 12 | */ |
13 | 13 | |
14 | | -require_once( "Maintenance.php" ); |
| 14 | +$optionsWithArgs = array( 'user', 'password' ); |
| 15 | +require_once 'commandLine.inc'; |
15 | 16 | |
16 | | -class ChangePassword extends Maintenance { |
17 | | - public function __construct() { |
18 | | - parent::__construct(); |
19 | | - $this->addParam( "user", "The username to operate on", true, true ); |
20 | | - $this->addParam( "password", "The password to use", true, true ); |
21 | | - $this->mDescription = "Change a user's password." |
22 | | - } |
23 | | - |
24 | | - public function execute() { |
25 | | - if( !$this->hasOption('user') || !$this->hasOption('password') ) { |
26 | | - $this->error( "Username or password not provided, halting.", true ); |
| 17 | +$USAGE = |
| 18 | + "Usage: php changePassword.php [--user=user --password=password | --help]\n" . |
| 19 | + "\toptions:\n" . |
| 20 | + "\t\t--help show this message\n" . |
| 21 | + "\t\t--user the username to operate on\n" . |
| 22 | + "\t\t--password the password to use\n"; |
| 23 | + |
| 24 | +if( in_array( '--help', $argv ) ) |
| 25 | + wfDie( $USAGE ); |
| 26 | + |
| 27 | +$cp = new ChangePassword( @$options['user'], @$options['password'] ); |
| 28 | +$cp->main(); |
| 29 | + |
| 30 | +/** |
| 31 | + * @ingroup Maintenance |
| 32 | + */ |
| 33 | +class ChangePassword { |
| 34 | + var $dbw; |
| 35 | + var $user, $password; |
| 36 | + |
| 37 | + function ChangePassword( $user, $password ) { |
| 38 | + global $USAGE; |
| 39 | + if( !strlen( $user ) or !strlen( $password ) ) { |
| 40 | + wfDie( $USAGE ); |
27 | 41 | } |
28 | | - $user = User::newFromName( $this->getOption('user') ); |
29 | | - if( !$user->getId() ) { |
30 | | - $this->error( "No such user: " . $this->getOption('user') . "\n", true ); |
| 42 | + |
| 43 | + $this->user = User::newFromName( $user ); |
| 44 | + if ( !$this->user->getId() ) { |
| 45 | + die ( "No such user: $user\n" ); |
31 | 46 | } |
32 | | - try { |
33 | | - $user->setPassword( $this->getOption('password') ); |
34 | | - $user->saveSettings(); |
35 | | - } catch( PasswordError $pwe ) { |
36 | | - $this->error( $pwe->getText(), true ); |
37 | | - } |
| 47 | + |
| 48 | + $this->password = $password; |
| 49 | + |
| 50 | + $this->dbw = wfGetDB( DB_MASTER ); |
38 | 51 | } |
| 52 | + |
| 53 | + function main() { |
| 54 | + $this->user->setPassword( $this->password ); |
| 55 | + $this->user->saveSettings(); |
| 56 | + } |
39 | 57 | } |
40 | | - |
41 | | -$maintClass = "ChangePassword"; |
42 | | -require_once( DO_MAINTENANCE ); |
Index: trunk/phase3/maintenance/deleteImageMemcached.php |
— | — | @@ -3,36 +3,40 @@ |
4 | 4 | * This script delete image information from memcached. |
5 | 5 | * |
6 | 6 | * Usage example: |
7 | | - * php deleteImageMemcached.php --until "2005-09-05 00:00:00" --sleep 0 |
| 7 | + * php deleteImageMemcached.php --until "2005-09-05 00:00:00" --sleep 0 --report 10 |
8 | 8 | * |
9 | 9 | * @file |
10 | 10 | * @ingroup Maintenance |
11 | 11 | */ |
12 | 12 | |
13 | | -require_once( "Maintenance.php" ); |
| 13 | +$optionsWithArgs = array( 'until', 'sleep', 'report' ); |
14 | 14 | |
15 | | -class DeleteImageCache extends Maintenance { |
16 | | - public function __construct() { |
17 | | - parent::__construct(); |
18 | | - $this->mDescription = "Delete image information from memcached"; |
19 | | - $this->addParam( 'sleep', 'How many seconds to sleep between deletions', true, true ); |
20 | | - $this->addParam( 'until', 'Timestamp to delete all entries prior to', true, true ); |
| 15 | +require_once 'commandLine.inc'; |
| 16 | + |
| 17 | +/** |
| 18 | + * @ingroup Maintenance |
| 19 | + */ |
| 20 | +class DeleteImageCache { |
| 21 | + var $until, $sleep, $report; |
| 22 | + |
| 23 | + function DeleteImageCache( $until, $sleep, $report ) { |
| 24 | + $this->until = $until; |
| 25 | + $this->sleep = $sleep; |
| 26 | + $this->report = $report; |
21 | 27 | } |
22 | 28 | |
23 | | - public function execute() { |
| 29 | + function main() { |
24 | 30 | global $wgMemc; |
| 31 | + $fname = 'DeleteImageCache::main'; |
25 | 32 | |
26 | | - $until = preg_replace( "/[^\d]/", '', $this->getOption('until') ); |
27 | | - $sleep = (int)$this->getOption('sleep') * 1000; // milliseconds |
28 | | - |
29 | 33 | ini_set( 'display_errors', false ); |
30 | 34 | |
31 | 35 | $dbr = wfGetDB( DB_SLAVE ); |
32 | 36 | |
33 | 37 | $res = $dbr->select( 'image', |
34 | 38 | array( 'img_name' ), |
35 | | - array( "img_timestamp < {$until}" ), |
36 | | - __METHOD__ |
| 39 | + array( "img_timestamp < {$this->until}" ), |
| 40 | + $fname |
37 | 41 | ); |
38 | 42 | |
39 | 43 | $i = 0; |
— | — | @@ -40,22 +44,29 @@ |
41 | 45 | |
42 | 46 | while ( $row = $dbr->fetchObject( $res ) ) { |
43 | 47 | if ($i % $this->report == 0) |
44 | | - $this->output( sprintf("%s: %13s done (%s)\n", wfWikiID(), "$i/$total", wfPercent( $i / $total * 100 ) ) ); |
| 48 | + printf("%s: %13s done (%s)\n", wfWikiID(), "$i/$total", wfPercent( $i / $total * 100 )); |
45 | 49 | $md5 = md5( $row->img_name ); |
46 | 50 | $wgMemc->delete( wfMemcKey( 'Image', $md5 ) ); |
47 | 51 | |
48 | | - if ($sleep != 0) |
49 | | - usleep( $sleep ); |
| 52 | + if ($this->sleep != 0) |
| 53 | + usleep( $this->sleep ); |
50 | 54 | |
51 | 55 | ++$i; |
52 | 56 | } |
53 | 57 | } |
54 | 58 | |
55 | | - private function getImageCount() { |
| 59 | + function getImageCount() { |
| 60 | + $fname = 'DeleteImageCache::getImageCount'; |
| 61 | + |
56 | 62 | $dbr = wfGetDB( DB_SLAVE ); |
57 | | - return $dbr->selectField( 'image', 'COUNT(*)', array(), __METHOD__ ); |
| 63 | + return $dbr->selectField( 'image', 'COUNT(*)', array(), $fname ); |
58 | 64 | } |
59 | 65 | } |
60 | 66 | |
61 | | -$maintClass = "DeleteImageCache"; |
62 | | -require_once( DO_MAINTENANCE ); |
| 67 | +$until = preg_replace( "/[^\d]/", '', $options['until'] ); |
| 68 | +$sleep = (int)$options['sleep'] * 1000; // milliseconds |
| 69 | +$report = (int)$options['report']; |
| 70 | + |
| 71 | +$dic = new DeleteImageCache( $until, $sleep, $report ); |
| 72 | +$dic->main(); |
| 73 | + |
Index: trunk/phase3/maintenance/nukeNS.php |
— | — | @@ -19,80 +19,90 @@ |
20 | 20 | * based on nukePage by Rob Church |
21 | 21 | */ |
22 | 22 | |
23 | | -require_once( "Maintenance.php" ); |
| 23 | +require_once( 'commandLine.inc' ); |
| 24 | +require_once( 'nukePage.inc' ); |
24 | 25 | |
25 | | -class NukeNS extends Maintenance { |
26 | | - public function __construct() { |
27 | | - parent::__construct(); |
28 | | - $this->mDescription = "Remove pages with only 1 revision from any namespace"; |
29 | | - $this->addParam( 'delete', "Actually delete the page" ); |
30 | | - $this->addParam( 'ns', 'Namespace to delete from, default NS_MEDIAWIKI', false, true ); |
31 | | - } |
| 26 | +$ns = NS_MEDIAWIKI; |
| 27 | +$delete = false; |
32 | 28 | |
33 | | - public function execute() { |
34 | | - $ns = $this->getOption( 'ns', NS_MEDIAWIKI ); |
35 | | - $delete = $this->getOption( 'delete', false ); |
36 | | - $dbw = wfGetDB( DB_MASTER ); |
37 | | - $dbw->begin(); |
| 29 | +if (isset($options['ns'])) |
| 30 | +{ |
| 31 | + $ns = $options['ns']; |
| 32 | +} |
38 | 33 | |
39 | | - $tbl_pag = $dbw->tableName( 'page' ); |
40 | | - $tbl_rev = $dbw->tableName( 'revision' ); |
41 | | - $res = $dbw->query( "SELECT page_title FROM $tbl_pag WHERE page_namespace = $ns" ); |
| 34 | +if (isset( $options['delete'] ) and $options['delete']) |
| 35 | +{ |
| 36 | + $delete = true; |
| 37 | +} |
42 | 38 | |
43 | | - $n_deleted = 0; |
44 | 39 | |
45 | | - while( $row = $dbw->fetchObject( $res ) ) { |
46 | | - //echo "$ns_name:".$row->page_title, "\n"; |
47 | | - $title = Title::newFromText($row->page_title, $ns); |
48 | | - $id = $title->getArticleID(); |
| 40 | +NukeNS( $ns, $delete); |
49 | 41 | |
50 | | - // Get corresponding revisions |
51 | | - $res2 = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_page = $id" ); |
52 | | - $revs = array(); |
| 42 | +function NukeNS($ns_no, $delete) { |
53 | 43 | |
54 | | - while( $row2 = $dbw->fetchObject( $res2 ) ) { |
55 | | - $revs[] = $row2->rev_id; |
56 | | - } |
57 | | - $count = count( $revs ); |
| 44 | + $dbw = wfGetDB( DB_MASTER ); |
| 45 | + $dbw->begin(); |
| 46 | + |
| 47 | + $tbl_pag = $dbw->tableName( 'page' ); |
| 48 | + $tbl_rev = $dbw->tableName( 'revision' ); |
| 49 | + $res = $dbw->query( "SELECT page_title FROM $tbl_pag WHERE page_namespace = $ns_no" ); |
58 | 50 | |
59 | | - //skip anything that looks modified (i.e. multiple revs) |
60 | | - if (($count == 1)) { |
61 | | - #echo $title->getPrefixedText(), "\t", $count, "\n"; |
62 | | - $this->output( "delete: ", $title->getPrefixedText(), "\n" ); |
| 51 | + $n_deleted = 0; |
| 52 | + |
| 53 | + while( $row = $dbw->fetchObject( $res ) ) { |
| 54 | + //echo "$ns_name:".$row->page_title, "\n"; |
| 55 | + $title = Title::newFromText($row->page_title, $ns_no); |
| 56 | + $id = $title->getArticleID(); |
63 | 57 | |
64 | | - //as much as I hate to cut & paste this, it's a little different, and |
65 | | - //I already have the id & revs |
66 | | - if( $delete ) { |
67 | | - $dbw->query( "DELETE FROM $tbl_pag WHERE page_id = $id" ); |
68 | | - $dbw->commit(); |
69 | | - // Delete revisions as appropriate |
70 | | - $child = $this->spawnChild( 'NukePage', 'NukePage.php' ); |
71 | | - $child->deleteRevisions( $revs ); |
72 | | - $this->purgeRedundantText( true ); |
73 | | - $n_deleted ++; |
74 | | - } |
75 | | - } else { |
76 | | - $this->output( "skip: ", $title->getPrefixedText(), "\n" ); |
77 | | - } |
78 | | - } |
79 | | - $dbw->commit(); |
| 58 | + // Get corresponding revisions |
| 59 | + $res2 = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_page = $id" ); |
| 60 | + $revs = array(); |
| 61 | + |
| 62 | + while( $row2 = $dbw->fetchObject( $res2 ) ) { |
| 63 | + $revs[] = $row2->rev_id; |
| 64 | + } |
| 65 | + $count = count( $revs ); |
80 | 66 | |
81 | | - if ($n_deleted > 0) { |
82 | | - #update statistics - better to decrement existing count, or just count |
83 | | - #the page table? |
84 | | - $pages = $dbw->selectField('site_stats', 'ss_total_pages'); |
85 | | - $pages -= $n_deleted; |
86 | | - $dbw->update( 'site_stats', |
87 | | - array('ss_total_pages' => $pages ), |
88 | | - array( 'ss_row_id' => 1), |
89 | | - __METHOD__ ); |
90 | | - } |
91 | | - |
92 | | - if (!$delete) { |
93 | | - $this->output( "To update the database, run the script with the --delete option.\n" ); |
94 | | - } |
95 | | - } |
| 67 | + //skip anything that looks modified (i.e. multiple revs) |
| 68 | + if (($count == 1)) { |
| 69 | + #echo $title->getPrefixedText(), "\t", $count, "\n"; |
| 70 | + echo "delete: ", $title->getPrefixedText(), "\n"; |
| 71 | + |
| 72 | + //as much as I hate to cut & paste this, it's a little different, and |
| 73 | + //I already have the id & revs |
| 74 | + |
| 75 | + if( $delete ) { |
| 76 | + $dbw->query( "DELETE FROM $tbl_pag WHERE page_id = $id" ); |
| 77 | + $dbw->commit(); |
| 78 | + // Delete revisions as appropriate |
| 79 | + DeleteRevisions( $revs ); |
| 80 | + PurgeRedundantText( true ); |
| 81 | + $n_deleted ++; |
| 82 | + } |
| 83 | + } else { |
| 84 | + echo "skip: ", $title->getPrefixedText(), "\n"; |
| 85 | + } |
| 86 | + |
| 87 | + |
| 88 | + } |
| 89 | + $dbw->commit(); |
| 90 | + |
| 91 | + if ($n_deleted > 0) { |
| 92 | + #update statistics - better to decrement existing count, or just count |
| 93 | + #the page table? |
| 94 | + $pages = $dbw->selectField('site_stats', 'ss_total_pages'); |
| 95 | + $pages -= $n_deleted; |
| 96 | + $dbw->update( 'site_stats', |
| 97 | + array('ss_total_pages' => $pages ), |
| 98 | + array( 'ss_row_id' => 1), |
| 99 | + __METHOD__ ); |
| 100 | + |
| 101 | + } |
| 102 | + |
| 103 | + if (!$delete) { |
| 104 | + echo( "To update the database, run the script with the --delete option.\n" ); |
| 105 | + } |
| 106 | + |
96 | 107 | } |
97 | 108 | |
98 | | -$maintClass = "NukeNS"; |
99 | | -require_once( DO_MAINTENANCE ); |
| 109 | + |
Index: trunk/phase3/maintenance/undelete.php |
— | — | @@ -6,35 +6,34 @@ |
7 | 7 | * @ingroup Maintenance |
8 | 8 | */ |
9 | 9 | |
10 | | -require_once( "Maintenance.php" ); |
| 10 | +$usage = <<<EOT |
| 11 | +Undelete a page |
| 12 | +Usage: php undelete.php [-u <user>] [-r <reason>] <pagename> |
11 | 13 | |
12 | | -class Undelete extends Maintenance { |
13 | | - public function __construct() { |
14 | | - parent::__construct(); |
15 | | - $this->mDescription = "Undelete a page"; |
16 | | - $this->addParam( 'u', 'The user to perform the undeletion', false, true ); |
17 | | - $this->addParam( 'r', 'The reason to undelete', false, true ); |
18 | | - $this->addArgs( array( 'pagename' ) ); |
19 | | - } |
| 14 | +EOT; |
20 | 15 | |
21 | | - public function execute() { |
22 | | - global $wgUser; |
| 16 | +$optionsWithArgs = array( 'u', 'r' ); |
| 17 | +require_once( 'commandLine.inc' ); |
23 | 18 | |
24 | | - $user = $this->getOption( 'u', 'Command line script' ); |
25 | | - $reason = $this->getOption( 'r', '' ); |
26 | | - $pageName = $this->getArg(); |
| 19 | +$user = 'Command line script'; |
| 20 | +$reason = ''; |
27 | 21 | |
28 | | - $title = Title::newFromText( $pageName ); |
29 | | - if ( !$title ) { |
30 | | - $this->error( "Invalid title", true ); |
31 | | - } |
32 | | - $wgUser = User::newFromName( $user ); |
33 | | - $archive = new PageArchive( $title ); |
34 | | - $this->output( "Undeleting " . $title->getPrefixedDBkey() . '...' ); |
35 | | - $archive->undelete( array(), $reason ); |
36 | | - $this->output( "done\n" ); |
37 | | - } |
| 22 | +if ( isset( $options['u'] ) ) { |
| 23 | + $user = $options['u']; |
38 | 24 | } |
| 25 | +if ( isset( $options['r'] ) ) { |
| 26 | + $reason = $options['r']; |
| 27 | +} |
| 28 | +$pageName = @$args[0]; |
| 29 | +$title = Title::newFromText( $pageName ); |
| 30 | +if ( !$title ) { |
| 31 | + echo $usage; |
| 32 | + exit( 1 ); |
| 33 | +} |
| 34 | +$wgUser = User::newFromName( $user ); |
| 35 | +$archive = new PageArchive( $title ); |
| 36 | +echo "Undeleting " . $title->getPrefixedDBkey() . '...'; |
| 37 | +$archive->undelete( array(), $reason ); |
| 38 | +echo "done\n"; |
39 | 39 | |
40 | | -$maintClass = "Undelete"; |
41 | | -require_once( DO_MAINTENANCE ); |
| 40 | + |
Index: trunk/phase3/maintenance/getLagTimes.php |
— | — | @@ -4,37 +4,26 @@ |
5 | 5 | * @ingroup Maintenance |
6 | 6 | */ |
7 | 7 | |
8 | | -require_once( "Maintenance.php" ); |
| 8 | +require 'commandLine.inc'; |
9 | 9 | |
10 | | -class GetLagTimes extends Maintenance { |
11 | | - public function __construct() { |
12 | | - parent::__construct(); |
13 | | - $this->mDescription = "Dump replication lag times"; |
14 | | - } |
| 10 | +$lb = wfGetLB(); |
15 | 11 | |
16 | | - public function execute() { |
17 | | - $lb = wfGetLB(); |
18 | | - |
19 | | - if( $lb->getServerCount() == 1 ) { |
20 | | - $this->error( "This script dumps replication lag times, but you don't seem to have\n" |
21 | | - . "a multi-host db server configuration.\n" ); |
| 12 | +if( $lb->getServerCount() == 1 ) { |
| 13 | + echo "This script dumps replication lag times, but you don't seem to have\n"; |
| 14 | + echo "a multi-host db server configuration.\n"; |
| 15 | +} else { |
| 16 | + $lags = $lb->getLagTimes(); |
| 17 | + foreach( $lags as $n => $lag ) { |
| 18 | + $host = $lb->getServerName( $n ); |
| 19 | + if( IP::isValid( $host ) ) { |
| 20 | + $ip = $host; |
| 21 | + $host = gethostbyaddr( $host ); |
22 | 22 | } else { |
23 | | - $lags = $lb->getLagTimes(); |
24 | | - foreach( $lags as $n => $lag ) { |
25 | | - $host = $lb->getServerName( $n ); |
26 | | - if( IP::isValid( $host ) ) { |
27 | | - $ip = $host; |
28 | | - $host = gethostbyaddr( $host ); |
29 | | - } else { |
30 | | - $ip = gethostbyname( $host ); |
31 | | - } |
32 | | - $starLen = min( intval( $lag ), 40 ); |
33 | | - $stars = str_repeat( '*', $starLen ); |
34 | | - $this->output( sprintf( "%10s %20s %3d %s\n", $ip, $host, $lag, $stars ) ); |
35 | | - } |
| 23 | + $ip = gethostbyname( $host ); |
36 | 24 | } |
| 25 | + $starLen = min( intval( $lag ), 40 ); |
| 26 | + $stars = str_repeat( '*', $starLen ); |
| 27 | + printf( "%10s %20s %3d %s\n", $ip, $host, $lag, $stars ); |
37 | 28 | } |
38 | 29 | } |
39 | 30 | |
40 | | -$maintClass = "GetLagTimes"; |
41 | | -require_once( DO_MAINTENANCE ); |
Index: trunk/phase3/maintenance/rebuildFileCache.php |
— | — | @@ -6,96 +6,87 @@ |
7 | 7 | * @ingroup Maintenance |
8 | 8 | */ |
9 | 9 | |
10 | | -require_once( "Maintenance.php" ); |
| 10 | +/** */ |
| 11 | +require_once( "commandLine.inc" ); |
| 12 | +if( !$wgUseFileCache ) { |
| 13 | + echo "Nothing to do -- \$wgUseFileCache is disabled.\n"; |
| 14 | + exit(0); |
| 15 | +} |
| 16 | +$wgDisableCounters = false; // no real hits here |
11 | 17 | |
12 | | -class RebuildFileCache extends Maintenance { |
13 | | - public function __construct() { |
14 | | - parent::__construct(); |
15 | | - $this->mDescription = "Build file cache for content pages"; |
16 | | - $this->addArgs( array( 'start', 'overwrite' ) ); |
17 | | - } |
| 18 | +$start = isset($args[0]) ? intval($args[0]) : 0; |
| 19 | +$overwrite = isset( $args[1] ) && $args[1] === 'overwrite'; |
| 20 | +echo "Building content page file cache from page {$start}!\n"; |
| 21 | +echo "Format: <start> [overwrite]\n"; |
18 | 22 | |
19 | | - public function execute() { |
20 | | - global $wgUseFileCache, $wgDisableCounters, $wgTitle, $wgArticle, $wgOut; |
21 | | - if( !$wgUseFileCache ) { |
22 | | - $this->error( "Nothing to do -- \$wgUseFileCache is disabled.\n", true ); |
| 23 | +$dbr = wfGetDB( DB_SLAVE ); |
| 24 | +$start = $start > 0 ? $start : $dbr->selectField( 'page', 'MIN(page_id)', false, __FUNCTION__ ); |
| 25 | +$end = $dbr->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ ); |
| 26 | +if( !$start ) { |
| 27 | + die("Nothing to do.\n"); |
| 28 | +} |
| 29 | + |
| 30 | +$_SERVER['HTTP_ACCEPT_ENCODING'] = 'bgzip'; // hack, no real client |
| 31 | +OutputPage::setEncodings(); # Not really used yet |
| 32 | + |
| 33 | +$BATCH_SIZE = 100; |
| 34 | +# Do remaining chunk |
| 35 | +$end += $BATCH_SIZE - 1; |
| 36 | +$blockStart = $start; |
| 37 | +$blockEnd = $start + $BATCH_SIZE - 1; |
| 38 | + |
| 39 | +$dbw = wfGetDB( DB_MASTER ); |
| 40 | +// Go through each page and save the output |
| 41 | +while( $blockEnd <= $end ) { |
| 42 | + // Get the pages |
| 43 | + $res = $dbr->select( 'page', array('page_namespace','page_title','page_id'), |
| 44 | + array('page_namespace' => $wgContentNamespaces, |
| 45 | + "page_id BETWEEN $blockStart AND $blockEnd" ), |
| 46 | + array('ORDER BY' => 'page_id ASC','USE INDEX' => 'PRIMARY') |
| 47 | + ); |
| 48 | + while( $row = $dbr->fetchObject( $res ) ) { |
| 49 | + $rebuilt = false; |
| 50 | + $wgTitle = Title::makeTitleSafe( $row->page_namespace, $row->page_title ); |
| 51 | + if( null == $wgTitle ) { |
| 52 | + echo "Page {$row->page_id} bad title\n"; |
| 53 | + continue; // broken title? |
23 | 54 | } |
24 | | - $wgDisableCounters = false; |
25 | | - $start = intval( $this->getArg( 0, 0 ) ); |
26 | | - $overwrite = $this->hasArg(1) && $this->getArg(1) === 'overwrite'; |
27 | | - $this->output( "Building content page file cache from page {$start}!\n" ); |
28 | | - |
29 | | - $dbr = wfGetDB( DB_SLAVE ); |
30 | | - $start = $start > 0 ? $start : $dbr->selectField( 'page', 'MIN(page_id)', false, __FUNCTION__ ); |
31 | | - $end = $dbr->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ ); |
32 | | - if( !$start ) { |
33 | | - $this->error( "Nothing to do.\n", true ); |
34 | | - } |
35 | | - |
36 | | - $_SERVER['HTTP_ACCEPT_ENCODING'] = 'bgzip'; // hack, no real client |
37 | | - OutputPage::setEncodings(); # Not really used yet |
38 | | - |
39 | | - $BATCH_SIZE = 100; |
40 | | - # Do remaining chunk |
41 | | - $end += $BATCH_SIZE - 1; |
42 | | - $blockStart = $start; |
43 | | - $blockEnd = $start + $BATCH_SIZE - 1; |
44 | | - |
45 | | - $dbw = wfGetDB( DB_MASTER ); |
46 | | - // Go through each page and save the output |
47 | | - while( $blockEnd <= $end ) { |
48 | | - // Get the pages |
49 | | - $res = $dbr->select( 'page', array('page_namespace','page_title','page_id'), |
50 | | - array('page_namespace' => $wgContentNamespaces, |
51 | | - "page_id BETWEEN $blockStart AND $blockEnd" ), |
52 | | - array('ORDER BY' => 'page_id ASC','USE INDEX' => 'PRIMARY') |
53 | | - ); |
54 | | - while( $row = $dbr->fetchObject( $res ) ) { |
55 | | - $rebuilt = false; |
56 | | - $wgTitle = Title::makeTitleSafe( $row->page_namespace, $row->page_title ); |
57 | | - if( null == $wgTitle ) { |
58 | | - $this->output( "Page {$row->page_id} bad title\n" ); |
59 | | - continue; // broken title? |
60 | | - } |
61 | | - $wgArticle = new Article( $wgTitle ); |
62 | | - // If the article is cacheable, then load it |
63 | | - if( $wgArticle->isFileCacheable() ) { |
64 | | - $cache = new HTMLFileCache( $wgTitle ); |
65 | | - if( $cache->isFileCacheGood() ) { |
66 | | - if( $overwrite ) { |
67 | | - $rebuilt = true; |
68 | | - } else { |
69 | | - $this->output( "Page {$row->page_id} already cached\n" ); |
70 | | - continue; // done already! |
71 | | - } |
72 | | - } |
73 | | - ob_start( array(&$cache, 'saveToFileCache' ) ); // save on ob_end_clean() |
74 | | - $wgUseFileCache = false; // hack, we don't want $wgArticle fiddling with filecache |
75 | | - $wgArticle->view(); |
76 | | - @$wgOut->output(); // header notices |
77 | | - $wgUseFileCache = true; |
78 | | - ob_end_clean(); // clear buffer |
79 | | - $wgOut = new OutputPage(); // empty out any output page garbage |
80 | | - if( $rebuilt ) |
81 | | - $this->output( "Re-cached page {$row->page_id}\n" ); |
82 | | - else |
83 | | - $this->output( "Cached page {$row->page_id}\n" ); |
| 55 | + $wgArticle = new Article( $wgTitle ); |
| 56 | + // If the article is cacheable, then load it |
| 57 | + if( $wgArticle->isFileCacheable() ) { |
| 58 | + $cache = new HTMLFileCache( $wgTitle ); |
| 59 | + if( $cache->isFileCacheGood() ) { |
| 60 | + if( $overwrite ) { |
| 61 | + $rebuilt = true; |
84 | 62 | } else { |
85 | | - $this->output( "Page {$row->page_id} not cacheable\n" ); |
| 63 | + echo "Page {$row->page_id} already cached\n"; |
| 64 | + continue; // done already! |
86 | 65 | } |
87 | | - $dbw->commit(); // commit any changes |
88 | 66 | } |
89 | | - $blockStart += $BATCH_SIZE; |
90 | | - $blockEnd += $BATCH_SIZE; |
91 | | - wfWaitForSlaves( 5 ); |
| 67 | + ob_start( array(&$cache, 'saveToFileCache' ) ); // save on ob_end_clean() |
| 68 | + $wgUseFileCache = false; // hack, we don't want $wgArticle fiddling with filecache |
| 69 | + $wgArticle->view(); |
| 70 | + @$wgOut->output(); // header notices |
| 71 | + $wgUseFileCache = true; |
| 72 | + ob_end_clean(); // clear buffer |
| 73 | + $wgOut = new OutputPage(); // empty out any output page garbage |
| 74 | + if( $rebuilt ) |
| 75 | + echo "Re-cached page {$row->page_id}\n"; |
| 76 | + else |
| 77 | + echo "Cached page {$row->page_id}\n"; |
| 78 | + } else { |
| 79 | + echo "Page {$row->page_id} not cacheable\n"; |
92 | 80 | } |
93 | | - $this->output( "Done!\n" ); |
94 | | - |
95 | | - // Remove these to be safe |
96 | | - if( isset($wgTitle) ) |
97 | | - unset($wgTitle); |
98 | | - if( isset($wgArticle) ) |
99 | | - unset($wgArticle); |
| 81 | + $dbw->commit(); // commit any changes |
100 | 82 | } |
| 83 | + $blockStart += $BATCH_SIZE; |
| 84 | + $blockEnd += $BATCH_SIZE; |
| 85 | + wfWaitForSlaves( 5 ); |
101 | 86 | } |
102 | | -require_once( "commandLine.inc" ); |
| 87 | +echo "Done!\n"; |
| 88 | + |
| 89 | +// Remove these to be safe |
| 90 | +if( isset($wgTitle) ) |
| 91 | + unset($wgTitle); |
| 92 | +if( isset($wgArticle) ) |
| 93 | + unset($wgArticle); |
Index: trunk/phase3/maintenance/nextJobDB.php |
— | — | @@ -6,71 +6,55 @@ |
7 | 7 | * @ingroup Maintenance |
8 | 8 | */ |
9 | 9 | |
10 | | -require_once( "Maintenance.php" ); |
| 10 | +$options = array( 'type' ); |
11 | 11 | |
12 | | -class nextJobDB extends Maintenance { |
13 | | - public function __construct() { |
14 | | - parent::__construct(); |
15 | | - $this->mDescription = "Pick a database that has pending jobs"; |
16 | | - $this->addParam( 'type', "The type of job to search for", false, true ); |
| 12 | +require_once( 'commandLine.inc' ); |
| 13 | + |
| 14 | +$type = isset($options['type']) |
| 15 | + ? $options['type'] |
| 16 | + : false; |
| 17 | + |
| 18 | +$mckey = $type === false |
| 19 | + ? "jobqueue:dbs" |
| 20 | + : "jobqueue:dbs:$type"; |
| 21 | + |
| 22 | +$pendingDBs = $wgMemc->get( $mckey ); |
| 23 | +if ( !$pendingDBs ) { |
| 24 | + $pendingDBs = array(); |
| 25 | + # Cross-reference DBs by master DB server |
| 26 | + $dbsByMaster = array(); |
| 27 | + foreach ( $wgLocalDatabases as $db ) { |
| 28 | + $lb = wfGetLB( $db ); |
| 29 | + $dbsByMaster[$lb->getServerName(0)][] = $db; |
17 | 30 | } |
18 | | - public function execute() { |
19 | | - global $wgMemc; |
20 | | - $type = $this->getParam( 'type', false ); |
21 | | - $mckey = $type === false |
22 | | - ? "jobqueue:dbs" |
23 | | - : "jobqueue:dbs:$type"; |
24 | | - $pendingDBs = $wgMemcKey->get( $mckey ); |
25 | | - |
26 | | - # If we didn't get it from the cache |
27 | | - if( !$pendingDBs ) { |
28 | | - $pendingDBs = $this->getPendingDbs( $type ); |
29 | | - $wgMemc->get( $mckey, $pendingDBs, 300 ) |
| 31 | + |
| 32 | + foreach ( $dbsByMaster as $master => $dbs ) { |
| 33 | + $dbConn = wfGetDB( DB_MASTER, array(), $dbs[0] ); |
| 34 | + $stype = $dbConn->addQuotes($type); |
| 35 | + |
| 36 | + # Padding row for MySQL bug |
| 37 | + $sql = "(SELECT '-------------------------------------------')"; |
| 38 | + foreach ( $dbs as $dbName ) { |
| 39 | + if ( $sql != '' ) { |
| 40 | + $sql .= ' UNION '; |
| 41 | + } |
| 42 | + if ($type === false) |
| 43 | + $sql .= "(SELECT '$dbName' FROM `$dbName`.job LIMIT 1)"; |
| 44 | + else |
| 45 | + $sql .= "(SELECT '$dbName' FROM `$dbName`.job WHERE job_cmd=$stype LIMIT 1)"; |
30 | 46 | } |
31 | | - # If we've got a pending job in a db, display it. |
32 | | - if ( $pendingDBs ) { |
33 | | - $this->output( $pendingDBs[mt_rand(0, count( $pendingDBs ) - 1)] ); |
| 47 | + $res = $dbConn->query( $sql, 'nextJobDB.php' ); |
| 48 | + $row = $dbConn->fetchRow( $res ); // discard padding row |
| 49 | + while ( $row = $dbConn->fetchRow( $res ) ) { |
| 50 | + $pendingDBs[] = $row[0]; |
34 | 51 | } |
35 | 52 | } |
36 | | - |
37 | | - /** |
38 | | - * Get all databases that have a pending job |
39 | | - * @param $type String Job type |
40 | | - * @return array |
41 | | - */ |
42 | | - private function getPendingDbs( $type ) { |
43 | | - $pendingDBs = array(); |
44 | | - # Cross-reference DBs by master DB server |
45 | | - $dbsByMaster = array(); |
46 | | - foreach ( $wgLocalDatabases as $db ) { |
47 | | - $lb = wfGetLB( $db ); |
48 | | - $dbsByMaster[$lb->getServerName(0)][] = $db; |
49 | | - } |
50 | | - |
51 | | - foreach ( $dbsByMaster as $master => $dbs ) { |
52 | | - $dbConn = wfGetDB( DB_MASTER, array(), $dbs[0] ); |
53 | | - $stype = $dbConn->addQuotes($type); |
54 | | - $jobTable = $dbConn->getTable( 'job' ); |
55 | | - |
56 | | - # Padding row for MySQL bug |
57 | | - $sql = "(SELECT '-------------------------------------------')"; |
58 | | - foreach ( $dbs as $dbName ) { |
59 | | - if ( $sql != '' ) { |
60 | | - $sql .= ' UNION '; |
61 | | - } |
62 | | - if ($type === false) |
63 | | - $sql .= "(SELECT '$dbName' FROM `$dbName`.$jobTable LIMIT 1)"; |
64 | | - else |
65 | | - $sql .= "(SELECT '$dbName' FROM `$dbName`.$jobTable WHERE job_cmd=$stype LIMIT 1)"; |
66 | | - } |
67 | | - $res = $dbConn->query( $sql, __METHOD__ ); |
68 | | - $row = $dbConn->fetchRow( $res ); // discard padding row |
69 | | - while ( $row = $dbConn->fetchRow( $res ) ) { |
70 | | - $pendingDBs[] = $row[0]; |
71 | | - } |
72 | | - } |
73 | | - } |
| 53 | + |
| 54 | + $wgMemc->set( $mckey, $pendingDBs, 300 ); |
74 | 55 | } |
75 | 56 | |
76 | | -$maintClass = "nextJobDb"; |
77 | | -require_once( DO_MAINTENANCE ); |
| 57 | +if ( $pendingDBs ) { |
| 58 | + echo $pendingDBs[mt_rand(0, count( $pendingDBs ) - 1)]; |
| 59 | +} |
| 60 | + |
| 61 | + |
Index: trunk/phase3/UPGRADE |
— | — | @@ -42,7 +42,8 @@ |
43 | 43 | repository, via a checkout or export operation. |
44 | 44 | |
45 | 45 | Replace the existing MediaWiki files with the new. You should preserve the |
46 | | -LocalSettings.php file and the "extensions" and "images" directories. |
| 46 | +LocalSettings.php file, AdminSettings.php file (if present), and the |
| 47 | +"extensions" and "images" directories. |
47 | 48 | |
48 | 49 | Depending upon your configuration, you may also need to preserve additional |
49 | 50 | directories, including a custom upload directory ($wgUploadDirectory), |
— | — | @@ -50,8 +51,8 @@ |
51 | 52 | |
52 | 53 | === Perform the database upgrade === |
53 | 54 | |
54 | | -You will need to have $wgDBadminuser and $wgDBadminpass set in your |
55 | | -LocalSettings.php, see there for more info. |
| 55 | +You will need an AdminSettings.php file set up in the correct format; see |
| 56 | +AdminSettings.sample in the wiki root for more information and examples. |
56 | 57 | |
57 | 58 | From the command line, browse to the "maintenance" directory and run the |
58 | 59 | update.php script to check and update the schema. This will insert missing |
— | — | @@ -171,10 +172,10 @@ |
172 | 173 | === Web installer === |
173 | 174 | |
174 | 175 | You can use the web-based installer wizard if you first remove the |
175 | | -LocalSettings.php file; be sure to give the installer the same |
176 | | -information as you did on the original install (language/encoding, |
177 | | -database name, password, etc). This will also generate a fresh |
178 | | -LocalSettings.php, which you may need to customize. |
| 176 | +LocalSettings.php (and AdminSettings.php, if any) files; be sure to |
| 177 | +give the installer the same information as you did on the original |
| 178 | +install (language/encoding, database name, password, etc). This will |
| 179 | +also generate a fresh LocalSettings.php, which you may need to customize. |
179 | 180 | |
180 | 181 | You may change some settings during the install, but be very careful! |
181 | 182 | Changing the encoding in particular will generally leave you with a |
— | — | @@ -184,8 +185,8 @@ |
185 | 186 | |
186 | 187 | Additionally, as of 1.4.0 you can run an in-place upgrade script from |
187 | 188 | the command line, keeping your existing LocalSettings.php. This requires |
188 | | -that you set $wgDBadminuser and $wgDBadminpassword with an appropriate |
189 | | -database user and password with privileges to modify the database structure. |
| 189 | +that you create an AdminSettings.php giving an appropriate database user |
| 190 | +and password with privileges to modify the database structure. |
190 | 191 | |
191 | 192 | Once the new files are in place, go into the maintenance subdirectory and |
192 | 193 | run the script: |
Index: trunk/phase3/docs/maintenance.txt |
— | — | @@ -1,54 +0,0 @@ |
2 | | -Prior to version 1.16, maintenance scripts were a hodgepodge of code that |
3 | | -had no cohesion or formal method of action. Beginning in 1.16, maintenance |
4 | | -scripts have been cleaned up to use a unified class. |
5 | | - |
6 | | -1. Directory structure |
7 | | -2. How to run a script |
8 | | -3. How to write your own |
9 | | - |
10 | | -1. DIRECTORY STRUCTURE |
11 | | - The /maintenance directory of a MediaWiki installation contains several |
12 | | -subdirectories, all of which have unique purposes. |
13 | | - |
14 | | -2. HOW TO RUN A SCRIPT |
15 | | - Ridiculously simple, just call 'php someScript.php' that's in the top- |
16 | | -level /maintenance directory. |
17 | | - |
18 | | -Example: |
19 | | - php clear_stats.php |
20 | | - |
21 | | -The following parameters are available to all maintenance scripts |
22 | | - |
23 | | -3. HOW TO WRITE YOUR OWN |
24 | | -Make a file in the maintenance directory called myScript.php or something. |
25 | | -In it, write the following: |
26 | | - |
27 | | -==BEGIN== |
28 | | - |
29 | | -<?php |
30 | | - |
31 | | -require_once( "Maintenance.php" ); |
32 | | - |
33 | | -class DemoMaint extends Maintenance { |
34 | | - |
35 | | - public function __construct() { |
36 | | - parent::__construct(); |
37 | | - } |
38 | | - |
39 | | - protected function execute() { |
40 | | - } |
41 | | -} |
42 | | - |
43 | | -$maintClass = "DemoMaint"; |
44 | | -require_once( DO_MAINTENANCE ); |
45 | | - |
46 | | -==END== |
47 | | - |
48 | | -That's it. In the execute() method, you have access to all of the normal |
49 | | -MediaWiki functions, so you can get a DB connection, use the cache, etc. |
50 | | -For full docs on the Maintenance class, see the auto-generated docs at |
51 | | -http://svn.wikimedia.org/doc/classMaintenance.html |
\ No newline at end of file |
Index: trunk/phase3/docs/scripts.txt |
— | — | @@ -35,9 +35,10 @@ |
36 | 36 | to force the profiler to save the informations in the database and apply the |
37 | 37 | maintenance/archives/patch-profiling.sql patch to the database. |
38 | 38 | |
39 | | - To enable the profileinfo.php itself, you'll need to set $wgDBadminuser |
40 | | - and $wgDBadminpassword in your LocalSettings.php, as well as $wgEnableProfileInfo |
41 | | - See also http://www.mediawiki.org/wiki/How_to_debug#Profiling. |
| 39 | + To enable the profileinfo.php itself, you'll need to create the |
| 40 | + AdminSettings.php file (see AdminSettings.sample for more information) and |
| 41 | + set $wgEnableProfileInfo to true in that file. See also |
| 42 | + http://www.mediawiki.org/wiki/How_to_debug#Profiling. |
42 | 43 | |
43 | 44 | redirect.php |
44 | 45 | Script that only redirect to the article passed in the wpDropdown parameter |
Index: trunk/phase3/includes/SiteStats.php |
— | — | @@ -49,8 +49,11 @@ |
50 | 50 | // clean schema with mwdumper. |
51 | 51 | wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" ); |
52 | 52 | |
| 53 | + global $IP; |
| 54 | + require_once "$IP/maintenance/initStats.inc"; |
| 55 | + |
53 | 56 | ob_start(); |
54 | | - self::init( false ); |
| 57 | + wfInitStats(); |
55 | 58 | ob_end_clean(); |
56 | 59 | |
57 | 60 | $row = self::doLoad( wfGetDB( DB_MASTER ) ); |
— | — | @@ -174,63 +177,6 @@ |
175 | 178 | } |
176 | 179 | return true; |
177 | 180 | } |
178 | | - |
179 | | - /** |
180 | | - * Ported from initStats.inc. |
181 | | - * @param $update bool Whether to update the current stats write fresh |
182 | | - * @param $noViews bool When true, do not update the number of page views |
183 | | - */ |
184 | | - function init( $update, $noViews = false ) { |
185 | | - $dbr = wfGetDB( DB_SLAVE ); |
186 | | - |
187 | | - wfOut( "Counting total edits..." ); |
188 | | - $edits = $dbr->selectField( 'revision', 'COUNT(*)', '', __METHOD__ ); |
189 | | - $edits += $dbr->selectField( 'archive', 'COUNT(*)', '', __METHOD__ ); |
190 | | - wfOut( "{$edits}\nCounting number of articles..." ); |
191 | | - |
192 | | - global $wgContentNamespaces; |
193 | | - $good = $dbr->selectField( 'page', 'COUNT(*)', array( 'page_namespace' => $wgContentNamespaces, 'page_is_redirect' => 0, 'page_len > 0' ), __METHOD__ ); |
194 | | - wfOut( "{$good}\nCounting total pages..." ); |
195 | | - |
196 | | - $pages = $dbr->selectField( 'page', 'COUNT(*)', '', __METHOD__ ); |
197 | | - wfOut( "{$pages}\nCounting number of users..." ); |
198 | | - |
199 | | - $users = $dbr->selectField( 'user', 'COUNT(*)', '', __METHOD__ ); |
200 | | - wfOut( "{$users}\nCounting number of admins..." ); |
201 | | - |
202 | | - $admin = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), __METHOD__ ); |
203 | | - wfOut( "{$admin}\nCounting number of images..." ); |
204 | | - |
205 | | - $image = $dbr->selectField( 'image', 'COUNT(*)', '', __METHOD__ ); |
206 | | - wfOut( "{$image}\n" ); |
207 | | - |
208 | | - if( !$noViews ) { |
209 | | - wfOut( "Counting total page views..." ); |
210 | | - $views = $dbr->selectField( 'page', 'SUM(page_counter)', '', __METHOD__ ); |
211 | | - wfOut( "{$views}\n" ); |
212 | | - } |
213 | | - |
214 | | - wfOut( "\nUpdating site statistics..." ); |
215 | | - |
216 | | - $dbw = wfGetDB( DB_MASTER ); |
217 | | - $values = array( 'ss_total_edits' => $edits, |
218 | | - 'ss_good_articles' => $good, |
219 | | - 'ss_total_pages' => $pages, |
220 | | - 'ss_users' => $users, |
221 | | - 'ss_admins' => $admin, |
222 | | - 'ss_images' => $image ); |
223 | | - $conds = array( 'ss_row_id' => 1 ); |
224 | | - $views = array( 'ss_total_views' => isset( $views ) ? $views : 0 ); |
225 | | - |
226 | | - if( $update ) { |
227 | | - $dbw->update( 'site_stats', $values, $conds, __METHOD__ ); |
228 | | - } else { |
229 | | - $dbw->delete( 'site_stats', $conds, __METHOD__ ); |
230 | | - $dbw->insert( 'site_stats', array_merge( $values, $conds, $views ), __METHOD__ ); |
231 | | - } |
232 | | - |
233 | | - wfOut( "done.\n" ); |
234 | | - } |
235 | 181 | } |
236 | 182 | |
237 | 183 | |
Index: trunk/phase3/AdminSettings.sample |
— | — | @@ -0,0 +1,32 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * This file should be copied to AdminSettings.php, and modified |
| 5 | + * to reflect local settings. It is required for the maintenance |
| 6 | + * scripts which run on the command line, as an extra security |
| 7 | + * measure to allow using a separate user account with higher |
| 8 | + * privileges to do maintenance work. |
| 9 | + * |
| 10 | + * Developers: Do not check AdminSettings.php into Subversion |
| 11 | + */ |
| 12 | + |
| 13 | +/* |
| 14 | + * This data is used by all database maintenance scripts |
| 15 | + * (see directory maintenance/). The SQL user MUST BE |
| 16 | + * MANUALLY CREATED or set to an existing user with |
| 17 | + * necessary permissions. |
| 18 | + * |
| 19 | + * This is not to be confused with sysop accounts for the |
| 20 | + * wiki. |
| 21 | + * |
| 22 | + * NOTE: for PostgreSQL this should be set to the same user and |
| 23 | + * password as the web user, that is, the same as $wgDBuser and |
| 24 | + * $wgDBpassword in LocalSettings.php. This is necessary to |
| 25 | + * ensure that the owner for new tables is set correctly. |
| 26 | + */ |
| 27 | +$wgDBadminuser = 'wikiadmin'; |
| 28 | +$wgDBadminpassword = 'adminpass'; |
| 29 | + |
| 30 | +/* |
| 31 | + * Whether to enable the profileinfo.php script. |
| 32 | + */ |
| 33 | +$wgEnableProfileInfo = false; |
Property changes on: trunk/phase3/AdminSettings.sample |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 34 | + native |
Added: svn:keywords |
2 | 35 | + Author Date Id Revision |
Index: trunk/phase3/profileinfo.php |
— | — | @@ -4,6 +4,7 @@ |
5 | 5 | $wgEnableProfileInfo = $wgProfileToDatabase = false; |
6 | 6 | |
7 | 7 | require_once( './includes/WebStart.php' ); |
| 8 | +@include_once( './AdminSettings.php' ); |
8 | 9 | |
9 | 10 | ?> |
10 | 11 | <!-- |
Index: trunk/phase3/t/Search.inc |
— | — | @@ -7,10 +7,11 @@ |
8 | 8 | require 'includes/Defines.php'; |
9 | 9 | require 'includes/ProfilerStub.php'; |
10 | 10 | require 'LocalSettings.php'; |
| 11 | +require 'AdminSettings.php'; |
11 | 12 | require 'includes/Setup.php'; |
12 | 13 | |
13 | 14 | function buildTestDatabase( $tables ) { |
14 | | - global $wgDBprefix, $wgDBserver, $wgDBname, $wgDBtype; |
| 15 | + global $wgDBprefix, $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname, $wgDBtype; |
15 | 16 | $oldPrefix = $wgDBprefix; |
16 | 17 | $wgDBprefix = 'parsertest'; |
17 | 18 | |
Index: trunk/phase3/config/index.php |
— | — | @@ -615,7 +615,6 @@ |
616 | 616 | $conf->RootUser = importPost( "RootUser", "root" ); |
617 | 617 | $conf->RootPW = importPost( "RootPW", "" ); |
618 | 618 | $useRoot = importCheck( 'useroot', false ); |
619 | | - $conf->populateadmin = importCheck( 'populateadmin', false ); |
620 | 619 | $conf->LanguageCode = importPost( "LanguageCode", "en" ); |
621 | 620 | ## MySQL specific: |
622 | 621 | $conf->DBprefix = importPost( "DBprefix" ); |
— | — | @@ -1528,8 +1527,6 @@ |
1529 | 1528 | <label class="column">Superuser account:</label> |
1530 | 1529 | <input type="checkbox" name="useroot" id="useroot" <?php if( $useRoot ) { ?>checked="checked" <?php } ?> /> |
1531 | 1530 | <label for="useroot">Use superuser account</label> |
1532 | | - <input type="checkbox" name="populateadmin" id="populateadmin" <?php if( $conf->populateadmin ) { ?>checked="checked" <?php } ?> /> |
1533 | | - <label for="populateadmin">Set as admin user for maintenance</label> |
1534 | 1531 | </div> |
1535 | 1532 | <div class="config-input"><?php aField( $conf, "RootUser", "Superuser name:", "text" ); ?></div> |
1536 | 1533 | <div class="config-input"><?php aField( $conf, "RootPW", "Superuser password:", "password" ); ?></div> |
— | — | @@ -1795,11 +1792,6 @@ |
1796 | 1793 | # Needs literal string interpolation for the current style path |
1797 | 1794 | $slconf['RightsIcon'] = $conf->RightsIcon; |
1798 | 1795 | } |
1799 | | - |
1800 | | - if( $conf->populateadmin ) { |
1801 | | - $slconf['DBadminuser'] = $conf->RootUser; |
1802 | | - $slconf['DBadminpassword'] = $conf->RootPW; |
1803 | | - } |
1804 | 1796 | |
1805 | 1797 | if( $conf->DBtype == 'mysql' ) { |
1806 | 1798 | $dbsettings = |
— | — | @@ -1907,10 +1899,6 @@ |
1908 | 1900 | |
1909 | 1901 | {$dbsettings} |
1910 | 1902 | |
1911 | | -## Database admin settings, used for maintenance scripts |
1912 | | -\$wgDBadminuser = \"{$slconf['DBadminuser']}\"; |
1913 | | -\$wgDBadminpassword = \"{$slconf['DBadminpassword']}\"; |
1914 | | - |
1915 | 1903 | ## Shared memory settings |
1916 | 1904 | \$wgMainCacheType = $cacheType; |
1917 | 1905 | \$wgMemCachedServers = $mcservers; |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -41,7 +41,6 @@ |
42 | 42 | appropriate privileges. Creating this user with web-install page requires |
43 | 43 | oci8.privileged_connect set to On in php.ini. |
44 | 44 | * Removed UserrightsChangeableGroups hook introduced in 1.14 |
45 | | -* AdminSettings.php has been removed completely |
46 | 45 | |
47 | 46 | === New features in 1.16 === |
48 | 47 | |
— | — | @@ -92,11 +91,8 @@ |
93 | 92 | stripped from them. |
94 | 93 | * Added a PHP port of CDB (constant database), for improved local caching when |
95 | 94 | the DBA extension is not available. |
96 | | -* (bug 14201) Create AdminSettings.php during wiki installation, in the same |
97 | | - way as LocalSettings.php |
98 | | -* (bug 16322) Allow maint scripts to accept DB user/pass over input or params |
99 | | - if no AdminSettings.php |
100 | 95 | |
| 96 | + |
101 | 97 | === Bug fixes in 1.16 === |
102 | 98 | |
103 | 99 | * (bug 18031) Make namespace selector on Special:Export remember the previous |
— | — | @@ -204,8 +200,6 @@ |
205 | 201 | * (bug 19294) Always show Sp-contributions-footer(-anon) |
206 | 202 | * Attempts to restrict reading of pages while anonymous viewing is allowed |
207 | 203 | via extensions not using the userCan hook and via $wgRevokePermissions now work. |
208 | | -* (bug 19157) createAndPromote error on bad password |
209 | | -* (bug 18768) Remove AdminSettings.php from MediaWiki core |
210 | 204 | * (bug 8445) Multiple-character search terms are now handled properly for Chinese |
211 | 205 | |
212 | 206 | == API changes in 1.16 == |
Property changes on: trunk/phase3 |
___________________________________________________________________ |
Modified: svn:mergeinfo |
213 | 207 | Reverse-merged /trunk/phase3:r52328-52330 |
214 | 208 | Reverse-merged /branches/maintenance-work:r51675-52335 |