Index: branches/maintenance-work/maintenance/doMaintenance.php |
— | — | @@ -1,47 +1,47 @@ |
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 | | -// Get an object to start us off
|
12 | | -$maintenance = new $maintClass();
|
13 | | -
|
14 | | -// Basic sanity checks and such
|
15 | | -$maintenance->setup();
|
16 | | -
|
17 | | -# Setup the profiler
|
18 | | -if ( file_exists( "$IP/StartProfiler.php" ) ) {
|
19 | | - require_once( "$IP/StartProfiler.php" );
|
20 | | -} else {
|
21 | | - require_once( "$IP/includes/ProfilerStub.php" );
|
22 | | -}
|
23 | | -
|
24 | | -// Load settings, using wikimedia-mode if needed
|
25 | | -if( file_exists( dirname(__FILE__).'/wikimedia-mode' ) ) {
|
26 | | - # TODO FIXME! Wikimedia-specific stuff needs to go away to an ext
|
27 | | - # Maybe a hook?
|
28 | | - global $cluster;
|
29 | | - $wgWikiFarm = true;
|
30 | | - $cluster = 'pmtma';
|
31 | | - require_once( "$IP/includes/AutoLoader.php" );
|
32 | | - require_once( "$IP/includes/SiteConfiguration.php" );
|
33 | | - require( "$IP/wgConf.php" );
|
34 | | - $maintenance->loadWikimediaSettings();
|
35 | | - require( $IP.'/includes/Defines.php' );
|
36 | | - require( $IP.'/CommonSettings.php' );
|
37 | | -} else {
|
38 | | - require_once( "$IP/includes/AutoLoader.php" );
|
39 | | - require_once( "$IP/includes/Defines.php" );
|
40 | | - require_once( $maintenance->loadSettings() );
|
41 | | -}
|
42 | | -// Some last includes
|
43 | | -require_once( "$IP/includes/Setup.php" );
|
44 | | -require_once( "$IP/install-utils.inc" );
|
45 | | -
|
46 | | -$wgTitle = null; # Much much faster startup than creating a title object
|
47 | | -
|
48 | | -$maintenance->execute();
|
| 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 | +// Get an object to start us off |
| 12 | +$maintenance = new $maintClass(); |
| 13 | + |
| 14 | +// Basic sanity checks and such |
| 15 | +$maintenance->setup(); |
| 16 | + |
| 17 | +# Setup the profiler |
| 18 | +if ( file_exists( "$IP/StartProfiler.php" ) ) { |
| 19 | + require_once( "$IP/StartProfiler.php" ); |
| 20 | +} else { |
| 21 | + require_once( "$IP/includes/ProfilerStub.php" ); |
| 22 | +} |
| 23 | + |
| 24 | +// Load settings, using wikimedia-mode if needed |
| 25 | +if( file_exists( dirname(__FILE__).'/wikimedia-mode' ) ) { |
| 26 | + # TODO FIXME! Wikimedia-specific stuff needs to go away to an ext |
| 27 | + # Maybe a hook? |
| 28 | + global $cluster; |
| 29 | + $wgWikiFarm = true; |
| 30 | + $cluster = 'pmtma'; |
| 31 | + require_once( "$IP/includes/AutoLoader.php" ); |
| 32 | + require_once( "$IP/includes/SiteConfiguration.php" ); |
| 33 | + require( "$IP/wgConf.php" ); |
| 34 | + $maintenance->loadWikimediaSettings(); |
| 35 | + require( $IP.'/includes/Defines.php' ); |
| 36 | + require( $IP.'/CommonSettings.php' ); |
| 37 | +} else { |
| 38 | + require_once( "$IP/includes/AutoLoader.php" ); |
| 39 | + require_once( "$IP/includes/Defines.php" ); |
| 40 | + require_once( $maintenance->loadSettings() ); |
| 41 | +} |
| 42 | +// Some last includes |
| 43 | +require_once( "$IP/includes/Setup.php" ); |
| 44 | +require_once( "$IP/install-utils.inc" ); |
| 45 | + |
| 46 | +$wgTitle = null; # Much much faster startup than creating a title object |
| 47 | + |
| 48 | +$maintenance->execute(); |
Property changes on: branches/maintenance-work/maintenance/doMaintenance.php |
___________________________________________________________________ |
Name: svn:eol-style |
49 | 49 | + native |
Index: branches/maintenance-work/maintenance/Maintenance.php |
— | — | @@ -1,410 +1,410 @@ |
2 | | -<?php
|
3 | | -
|
4 | | -/**
|
5 | | - * Abstract maintenance class for quickly writing and churning out
|
6 | | - * maintenance scripts with minimal effort. All that _must_ be defined
|
7 | | - * is the execute() method. See docs/maintenance.txt for more info
|
8 | | - * and a quick demo of how to use it.
|
9 | | - *
|
10 | | - * @author Chad Horohoe <chad@anyonecanedit.org>
|
11 | | - * @since 1.16
|
12 | | - * @ingroup Maintenance
|
13 | | - */
|
14 | | -abstract class Maintenance {
|
15 | | -
|
16 | | - // This is the desired params
|
17 | | - protected $mParams = array();
|
18 | | -
|
19 | | - // This is the list of options that were actually passed
|
20 | | - protected $mOptions = array();
|
21 | | -
|
22 | | - // This is the list of arguments that were actually passed
|
23 | | - protected $mArgs = array();
|
24 | | -
|
25 | | - // Name of the script currently running
|
26 | | - protected $mSelf;
|
27 | | -
|
28 | | - // Special vars for params that are always used
|
29 | | - private $mQuiet = false;
|
30 | | - private $mDbUser, $mDbPass;
|
31 | | -
|
32 | | - // A description of the script, children should change this
|
33 | | - protected $mDescription = '';
|
34 | | -
|
35 | | - /**
|
36 | | - * Default constructor. Children should call this if implementing
|
37 | | - * their own constructors
|
38 | | - */
|
39 | | - public function __construct() {
|
40 | | - $this->addDefaultParams();
|
41 | | - }
|
42 | | -
|
43 | | - /**
|
44 | | - * Do the actual work. All child classes will need to implement this
|
45 | | - */
|
46 | | - abstract protected function execute();
|
47 | | -
|
48 | | - /**
|
49 | | - * Add a parameter to the script. Will be displayed on --help
|
50 | | - * with the associated description
|
51 | | - *
|
52 | | - * @param $name String The name of the param (help, version, etc)
|
53 | | - * @param $description String The description of the param to show on --help
|
54 | | - * @param $required boolean Is the param required?
|
55 | | - */
|
56 | | - protected function addParam( $name, $description, $required = false ) {
|
57 | | - $this->mParams[ $name ] = array( 'desc' => $description, 'require' => $required );
|
58 | | - }
|
59 | | -
|
60 | | - /**
|
61 | | - * Return input from stdin.
|
62 | | - * @param $length int The number of bytes to read
|
63 | | - * @return mixed
|
64 | | - */
|
65 | | - protected function getStdin( $len = 255 ) {
|
66 | | - $f = fopen( 'php://stdin', 'r' );
|
67 | | - $input = fgets( $fr, $len );
|
68 | | - fclose ( $fr );
|
69 | | - return rtrim( $input );
|
70 | | - }
|
71 | | -
|
72 | | - /**
|
73 | | - * Throw some output to the user. Scripts can call this with no fears,
|
74 | | - * as we handle all --quiet stuff here
|
75 | | - * @param $out String The text to show to the user
|
76 | | - */
|
77 | | - protected function output( $out ) {
|
78 | | - if( $this->mQuiet ) {
|
79 | | - return;
|
80 | | - }
|
81 | | - $f = fopen( 'php://stdout', 'w' );
|
82 | | - fwrite( $f, $out );
|
83 | | - fclose( $f );
|
84 | | - }
|
85 | | -
|
86 | | - /**
|
87 | | - * Throw an error to the user. Doesn't respect --quiet, so don't use
|
88 | | - * this for non-error output
|
89 | | - * @param $err String The error to display
|
90 | | - * @param $die boolean If true, go ahead and die out.
|
91 | | - */
|
92 | | - protected function error( $err, $die = false ) {
|
93 | | - $f = fopen( 'php://stderr', 'w' );
|
94 | | - fwrite( $f, $err );
|
95 | | - fclose( $f );
|
96 | | - if( $die ) die();
|
97 | | - }
|
98 | | -
|
99 | | - /**
|
100 | | - * Does the script need DB access? Override this and return true,
|
101 | | - * if needed
|
102 | | - * @return boolean
|
103 | | - */
|
104 | | - protected function needsDB() {
|
105 | | - return false;
|
106 | | - }
|
107 | | -
|
108 | | - /**
|
109 | | - * Add the default parameters to the scripts
|
110 | | - */
|
111 | | - private function addDefaultParams() {
|
112 | | - $this->addParam( 'help', "Display this help message" );
|
113 | | - $this->addParam( 'quiet', "Whether to supress non-error output" );
|
114 | | - $this->addParam( 'conf', "Location of LocalSettings.php, if not default" );
|
115 | | - $this->addParam( 'wiki', "For specifying the wiki ID" );
|
116 | | - if( $this->needsDB() ) {
|
117 | | - $this->addParam( 'dbuser', "The DB user to use for this script" );
|
118 | | - $this->addParam( 'dbpass', "The password to use for this script" );
|
119 | | - }
|
120 | | - }
|
121 | | -
|
122 | | - /**
|
123 | | - * Do some sanity checking
|
124 | | - */
|
125 | | - public function setup() {
|
126 | | - global $IP, $wgCommandLineMode, $wgUseNormalUser, $wgRequestTime;
|
127 | | -
|
128 | | - # Abort if called from a web server
|
129 | | - if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) {
|
130 | | - $this->error( "This script must be run from the command line\n", true );
|
131 | | - }
|
132 | | -
|
133 | | - # Make sure we can handle script parameters
|
134 | | - if( !ini_get( 'register_argc_argv' ) ) {
|
135 | | - $this->error( "Cannot get command line arguments, register_argc_argv is set to false", true );
|
136 | | - }
|
137 | | -
|
138 | | - # Make sure we're on PHP5 or better
|
139 | | - if( version_compare( PHP_VERSION, '5.0.0' ) < 0 ) {
|
140 | | - $this->error( "Sorry! This version of MediaWiki requires PHP 5; you are running " .
|
141 | | - PHP_VERSION . ".\n\n" .
|
142 | | - "If you are sure you already have PHP 5 installed, it may be installed\n" .
|
143 | | - "in a different path from PHP 4. Check with your system administrator.\n", true );
|
144 | | - }
|
145 | | -
|
146 | | - if( version_compare( phpversion(), '5.2.4' ) >= 0 ) {
|
147 | | - // Send PHP warnings and errors to stderr instead of stdout.
|
148 | | - // This aids in diagnosing problems, while keeping messages
|
149 | | - // out of redirected output.
|
150 | | - if( ini_get( 'display_errors' ) ) {
|
151 | | - ini_set( 'display_errors', 'stderr' );
|
152 | | - }
|
153 | | -
|
154 | | - // Don't touch the setting on earlier versions of PHP,
|
155 | | - // as setting it would disable output if you'd wanted it.
|
156 | | -
|
157 | | - // Note that exceptions are also sent to stderr when
|
158 | | - // command-line mode is on, regardless of PHP version.
|
159 | | - }
|
160 | | -
|
161 | | - # Set the memory limit
|
162 | | - ini_set( 'memory_limit', -1 );
|
163 | | -
|
164 | | - $wgRequestTime = microtime(true);
|
165 | | -
|
166 | | - # Define us as being in Mediawiki
|
167 | | - define( 'MEDIAWIKI', true );
|
168 | | -
|
169 | | - # Setup $IP, using MW_INSTALL_PATH if it exists
|
170 | | - $IP = strval( getenv('MW_INSTALL_PATH') ) !== ''
|
171 | | - ? getenv('MW_INSTALL_PATH')
|
172 | | - : realpath( dirname( __FILE__ ) . '/..' );
|
173 | | -
|
174 | | - $wgCommandLineMode = true;
|
175 | | - # Turn off output buffering if it's on
|
176 | | - @ob_end_flush();
|
177 | | -
|
178 | | - if (!isset( $wgUseNormalUser ) ) {
|
179 | | - $wgUseNormalUser = false;
|
180 | | - }
|
181 | | -
|
182 | | - $this->loadArgs();
|
183 | | - $this->maybeHelp();
|
184 | | - }
|
185 | | -
|
186 | | - /**
|
187 | | - * Process command line arguments
|
188 | | - * $mOptions becomes an array with keys set to the option names
|
189 | | - * $mArgs becomes a zero-based array containing the non-option arguments
|
190 | | - */
|
191 | | - private function loadArgs() {
|
192 | | - global $argv;
|
193 | | - $this->mSelf = array_shift( $argv );
|
194 | | -
|
195 | | - $options = array();
|
196 | | - $args = array();
|
197 | | -
|
198 | | - # Parse arguments
|
199 | | - for( $arg = reset( $argv ); $arg !== false; $arg = next( $argv ) ) {
|
200 | | - if ( $arg == '--' ) {
|
201 | | - # End of options, remainder should be considered arguments
|
202 | | - $arg = next( $argv );
|
203 | | - while( $arg !== false ) {
|
204 | | - $args[] = $arg;
|
205 | | - $arg = next( $argv );
|
206 | | - }
|
207 | | - break;
|
208 | | - } elseif ( substr( $arg, 0, 2 ) == '--' ) {
|
209 | | - # Long options
|
210 | | - $option = substr( $arg, 2 );
|
211 | | - if ( isset( $this->mParams[$option] ) ) {
|
212 | | - $param = next( $argv );
|
213 | | - if ( $param === false ) {
|
214 | | - $this->error( "$arg needs a value after it\n", true );
|
215 | | - }
|
216 | | - $options[$option] = $param;
|
217 | | - } else {
|
218 | | - $bits = explode( '=', $option, 2 );
|
219 | | - if( count( $bits ) > 1 ) {
|
220 | | - $option = $bits[0];
|
221 | | - $param = $bits[1];
|
222 | | - } else {
|
223 | | - $param = 1;
|
224 | | - }
|
225 | | - $options[$option] = $param;
|
226 | | - }
|
227 | | - } elseif ( substr( $arg, 0, 1 ) == '-' ) {
|
228 | | - # Short options
|
229 | | - for ( $p=1; $p<strlen( $arg ); $p++ ) {
|
230 | | - $option = $arg{$p};
|
231 | | - if ( isset( $this->mParams[$option] ) ) {
|
232 | | - $param = next( $argv );
|
233 | | - if ( $param === false ) {
|
234 | | - $this->error( "$arg needs a value after it\n", true );
|
235 | | - }
|
236 | | - $options[$option] = $param;
|
237 | | - } else {
|
238 | | - $options[$option] = 1;
|
239 | | - }
|
240 | | - }
|
241 | | - } else {
|
242 | | - $args[] = $arg;
|
243 | | - }
|
244 | | - }
|
245 | | -
|
246 | | - # These vars get special treatment
|
247 | | - if( isset( $options['dbuser'] ) )
|
248 | | - $this->mDbUser = $options['dbuser'];
|
249 | | - if( isset( $options['dbpass'] ) )
|
250 | | - $this->mDbPass = $options['dbpass'];
|
251 | | - if( isset( $options['quiet'] ) )
|
252 | | - $this->mQuiet = true;
|
253 | | -
|
254 | | - # Check to make sure we've got all the required ones
|
255 | | - foreach( $this->mParams as $opt => $info ) {
|
256 | | - if( $info['required'] && !isset( $this->mOptions[$opt] ) ) {
|
257 | | - $this->error( "Param $opt required.\n", true );
|
258 | | - }
|
259 | | - }
|
260 | | -
|
261 | | - $this->mOptions = $options;
|
262 | | - $this->mArgs = $args;
|
263 | | - }
|
264 | | -
|
265 | | - /**
|
266 | | - * Maybe show the help.
|
267 | | - */
|
268 | | - private function maybeHelp() {
|
269 | | - if( isset( $this->mOptions['help'] ) ) {
|
270 | | - $this->mQuiet = false;
|
271 | | - if( $this->mDescription ) {
|
272 | | - $this->output( $this->mDescription . "\n" );
|
273 | | - }
|
274 | | - $this->output( "\nUsage: php " . $this->mSelf . " [--" .
|
275 | | - implode( array_keys( $this->mParams ), "|--" ) . "]\n" );
|
276 | | - foreach( $params as $par => $desc ) {
|
277 | | - $this->output( "\t$par : $desc\n" );
|
278 | | - }
|
279 | | - }
|
280 | | - }
|
281 | | -
|
282 | | - /**
|
283 | | - * Handle some last-minute setup here.
|
284 | | - */
|
285 | | - private function finalSetup() {
|
286 | | - global $wgCommandLineMode, $wgUseNormalUser, $wgShowSQLErrors;
|
287 | | - global $wgTitle, $wgProfiling, $IP, $wgDBadminuser, $wgDBadminpassword;
|
288 | | - global $wgDBuser, $wgDBpassword, $wgDBservers, $wgLBFactoryConf;
|
289 | | -
|
290 | | - # Turn off output buffering again, it might have been turned on in the settings files
|
291 | | - if( ob_get_level() ) {
|
292 | | - ob_end_flush();
|
293 | | - }
|
294 | | - # Same with these
|
295 | | - $wgCommandLineMode = true;
|
296 | | -
|
297 | | - # If these were passed, use them
|
298 | | - if( $this->mDbUser )
|
299 | | - $wgDBadminuser = $this->mDbUser;
|
300 | | - if( $this->mDbPass )
|
301 | | - $wgDBadminpass = $this->mDbPass;
|
302 | | -
|
303 | | - if ( empty( $wgUseNormalUser ) && isset( $wgDBadminuser ) ) {
|
304 | | - $wgDBuser = $wgDBadminuser;
|
305 | | - $wgDBpassword = $wgDBadminpassword;
|
306 | | -
|
307 | | - if( $wgDBservers ) {
|
308 | | - foreach ( $wgDBservers as $i => $server ) {
|
309 | | - $wgDBservers[$i]['user'] = $wgDBuser;
|
310 | | - $wgDBservers[$i]['password'] = $wgDBpassword;
|
311 | | - }
|
312 | | - }
|
313 | | - if( isset( $wgLBFactoryConf['serverTemplate'] ) ) {
|
314 | | - $wgLBFactoryConf['serverTemplate']['user'] = $wgDBuser;
|
315 | | - $wgLBFactoryConf['serverTemplate']['password'] = $wgDBpassword;
|
316 | | - }
|
317 | | - }
|
318 | | -
|
319 | | - if ( defined( 'MW_CMDLINE_CALLBACK' ) ) {
|
320 | | - $fn = MW_CMDLINE_CALLBACK;
|
321 | | - $fn();
|
322 | | - }
|
323 | | -
|
324 | | - $wgShowSQLErrors = true;
|
325 | | - @set_time_limit(0);
|
326 | | -
|
327 | | - $wgProfiling = false; // only for Profiler.php mode; avoids OOM errors
|
328 | | - }
|
329 | | -
|
330 | | - /**
|
331 | | - * Do setup specific to WMF
|
332 | | - */
|
333 | | - public function loadWikimediaSettings() {
|
334 | | - global $IP, $wgNoDBParam, $wgUseNormalUser, $wgConf;
|
335 | | -
|
336 | | - if ( empty( $wgNoDBParam ) ) {
|
337 | | - # Check if we were passed a db name
|
338 | | - if ( isset( $this->mOptions['wiki'] ) ) {
|
339 | | - $db = $this->mOptions['wiki'];
|
340 | | - } else {
|
341 | | - $db = array_shift( $this->mArgs );
|
342 | | - }
|
343 | | - list( $site, $lang ) = $wgConf->siteFromDB( $db );
|
344 | | -
|
345 | | - # If not, work out the language and site the old way
|
346 | | - if ( is_null( $site ) || is_null( $lang ) ) {
|
347 | | - if ( !$db ) {
|
348 | | - $lang = 'aa';
|
349 | | - } else {
|
350 | | - $lang = $db;
|
351 | | - }
|
352 | | - if ( isset( $this->mArgs[0] ) ) {
|
353 | | - $site = array_shift( $this->mArgs );
|
354 | | - } else {
|
355 | | - $site = 'wikipedia';
|
356 | | - }
|
357 | | - }
|
358 | | - } else {
|
359 | | - $lang = 'aa';
|
360 | | - $site = 'wikipedia';
|
361 | | - }
|
362 | | -
|
363 | | - # This is for the IRC scripts, which now run as the apache user
|
364 | | - # The apache user doesn't have access to the wikiadmin_pass command
|
365 | | - if ( $_ENV['USER'] == 'apache' ) {
|
366 | | - #if ( posix_geteuid() == 48 ) {
|
367 | | - $wgUseNormalUser = true;
|
368 | | - }
|
369 | | -
|
370 | | - putenv( 'wikilang='.$lang);
|
371 | | -
|
372 | | - $DP = $IP;
|
373 | | - ini_set( 'include_path', ".:$IP:$IP/includes:$IP/languages:$IP/maintenance" );
|
374 | | -
|
375 | | - if ( $lang == 'test' && $site == 'wikipedia' ) {
|
376 | | - define( 'TESTWIKI', 1 );
|
377 | | - }
|
378 | | - }
|
379 | | -
|
380 | | - /**
|
381 | | - * Generic setup for most installs. Returns the location of LocalSettings
|
382 | | - * @return String
|
383 | | - */
|
384 | | - public function loadSettings() {
|
385 | | - global $wgWikiFarm, $wgCommandLineMode, $IP, $DP;
|
386 | | -
|
387 | | - $wgWikiFarm = false;
|
388 | | - if ( isset( $this->mOptions['conf'] ) ) {
|
389 | | - $settingsFile = $this->mOptions['conf'];
|
390 | | - } else {
|
391 | | - $settingsFile = "$IP/LocalSettings.php";
|
392 | | - }
|
393 | | - if ( isset( $this->mOptions['wiki'] ) ) {
|
394 | | - $bits = explode( '-', $this->mOptions['wiki'] );
|
395 | | - if ( count( $bits ) == 1 ) {
|
396 | | - $bits[] = '';
|
397 | | - }
|
398 | | - define( 'MW_DB', $bits[0] );
|
399 | | - define( 'MW_PREFIX', $bits[1] );
|
400 | | - }
|
401 | | -
|
402 | | - if ( ! is_readable( $settingsFile ) ) {
|
403 | | - $this->error( "A copy of your installation's LocalSettings.php\n" .
|
404 | | - "must exist and be readable in the source directory.\n", true );
|
405 | | - }
|
406 | | - $wgCommandLineMode = true;
|
407 | | - $DP = $IP;
|
408 | | - $this->finalSetup();
|
409 | | - return $settingsFile;
|
410 | | - }
|
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Abstract maintenance class for quickly writing and churning out |
| 6 | + * maintenance scripts with minimal effort. All that _must_ be defined |
| 7 | + * is the execute() method. See docs/maintenance.txt for more info |
| 8 | + * and a quick demo of how to use it. |
| 9 | + * |
| 10 | + * @author Chad Horohoe <chad@anyonecanedit.org> |
| 11 | + * @since 1.16 |
| 12 | + * @ingroup Maintenance |
| 13 | + */ |
| 14 | +abstract class Maintenance { |
| 15 | + |
| 16 | + // This is the desired params |
| 17 | + protected $mParams = array(); |
| 18 | + |
| 19 | + // This is the list of options that were actually passed |
| 20 | + protected $mOptions = array(); |
| 21 | + |
| 22 | + // This is the list of arguments that were actually passed |
| 23 | + protected $mArgs = array(); |
| 24 | + |
| 25 | + // Name of the script currently running |
| 26 | + protected $mSelf; |
| 27 | + |
| 28 | + // Special vars for params that are always used |
| 29 | + private $mQuiet = false; |
| 30 | + private $mDbUser, $mDbPass; |
| 31 | + |
| 32 | + // A description of the script, children should change this |
| 33 | + protected $mDescription = ''; |
| 34 | + |
| 35 | + /** |
| 36 | + * Default constructor. Children should call this if implementing |
| 37 | + * their own constructors |
| 38 | + */ |
| 39 | + public function __construct() { |
| 40 | + $this->addDefaultParams(); |
| 41 | + } |
| 42 | + |
| 43 | + /** |
| 44 | + * Do the actual work. All child classes will need to implement this |
| 45 | + */ |
| 46 | + abstract protected function execute(); |
| 47 | + |
| 48 | + /** |
| 49 | + * Add a parameter to the script. Will be displayed on --help |
| 50 | + * with the associated description |
| 51 | + * |
| 52 | + * @param $name String The name of the param (help, version, etc) |
| 53 | + * @param $description String The description of the param to show on --help |
| 54 | + * @param $required boolean Is the param required? |
| 55 | + */ |
| 56 | + protected function addParam( $name, $description, $required = false ) { |
| 57 | + $this->mParams[ $name ] = array( 'desc' => $description, 'require' => $required ); |
| 58 | + } |
| 59 | + |
| 60 | + /** |
| 61 | + * Return input from stdin. |
| 62 | + * @param $length int The number of bytes to read |
| 63 | + * @return mixed |
| 64 | + */ |
| 65 | + protected function getStdin( $len = 255 ) { |
| 66 | + $f = fopen( 'php://stdin', 'r' ); |
| 67 | + $input = fgets( $fr, $len ); |
| 68 | + fclose ( $fr ); |
| 69 | + return rtrim( $input ); |
| 70 | + } |
| 71 | + |
| 72 | + /** |
| 73 | + * Throw some output to the user. Scripts can call this with no fears, |
| 74 | + * as we handle all --quiet stuff here |
| 75 | + * @param $out String The text to show to the user |
| 76 | + */ |
| 77 | + protected function output( $out ) { |
| 78 | + if( $this->mQuiet ) { |
| 79 | + return; |
| 80 | + } |
| 81 | + $f = fopen( 'php://stdout', 'w' ); |
| 82 | + fwrite( $f, $out ); |
| 83 | + fclose( $f ); |
| 84 | + } |
| 85 | + |
| 86 | + /** |
| 87 | + * Throw an error to the user. Doesn't respect --quiet, so don't use |
| 88 | + * this for non-error output |
| 89 | + * @param $err String The error to display |
| 90 | + * @param $die boolean If true, go ahead and die out. |
| 91 | + */ |
| 92 | + protected function error( $err, $die = false ) { |
| 93 | + $f = fopen( 'php://stderr', 'w' ); |
| 94 | + fwrite( $f, $err ); |
| 95 | + fclose( $f ); |
| 96 | + if( $die ) die(); |
| 97 | + } |
| 98 | + |
| 99 | + /** |
| 100 | + * Does the script need DB access? Override this and return true, |
| 101 | + * if needed |
| 102 | + * @return boolean |
| 103 | + */ |
| 104 | + protected function needsDB() { |
| 105 | + return false; |
| 106 | + } |
| 107 | + |
| 108 | + /** |
| 109 | + * Add the default parameters to the scripts |
| 110 | + */ |
| 111 | + private function addDefaultParams() { |
| 112 | + $this->addParam( 'help', "Display this help message" ); |
| 113 | + $this->addParam( 'quiet', "Whether to supress non-error output" ); |
| 114 | + $this->addParam( 'conf', "Location of LocalSettings.php, if not default" ); |
| 115 | + $this->addParam( 'wiki', "For specifying the wiki ID" ); |
| 116 | + if( $this->needsDB() ) { |
| 117 | + $this->addParam( 'dbuser', "The DB user to use for this script" ); |
| 118 | + $this->addParam( 'dbpass', "The password to use for this script" ); |
| 119 | + } |
| 120 | + } |
| 121 | + |
| 122 | + /** |
| 123 | + * Do some sanity checking |
| 124 | + */ |
| 125 | + public function setup() { |
| 126 | + global $IP, $wgCommandLineMode, $wgUseNormalUser, $wgRequestTime; |
| 127 | + |
| 128 | + # Abort if called from a web server |
| 129 | + if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) { |
| 130 | + $this->error( "This script must be run from the command line\n", true ); |
| 131 | + } |
| 132 | + |
| 133 | + # Make sure we can handle script parameters |
| 134 | + if( !ini_get( 'register_argc_argv' ) ) { |
| 135 | + $this->error( "Cannot get command line arguments, register_argc_argv is set to false", true ); |
| 136 | + } |
| 137 | + |
| 138 | + # Make sure we're on PHP5 or better |
| 139 | + if( version_compare( PHP_VERSION, '5.0.0' ) < 0 ) { |
| 140 | + $this->error( "Sorry! This version of MediaWiki requires PHP 5; you are running " . |
| 141 | + PHP_VERSION . ".\n\n" . |
| 142 | + "If you are sure you already have PHP 5 installed, it may be installed\n" . |
| 143 | + "in a different path from PHP 4. Check with your system administrator.\n", true ); |
| 144 | + } |
| 145 | + |
| 146 | + if( version_compare( phpversion(), '5.2.4' ) >= 0 ) { |
| 147 | + // Send PHP warnings and errors to stderr instead of stdout. |
| 148 | + // This aids in diagnosing problems, while keeping messages |
| 149 | + // out of redirected output. |
| 150 | + if( ini_get( 'display_errors' ) ) { |
| 151 | + ini_set( 'display_errors', 'stderr' ); |
| 152 | + } |
| 153 | + |
| 154 | + // Don't touch the setting on earlier versions of PHP, |
| 155 | + // as setting it would disable output if you'd wanted it. |
| 156 | + |
| 157 | + // Note that exceptions are also sent to stderr when |
| 158 | + // command-line mode is on, regardless of PHP version. |
| 159 | + } |
| 160 | + |
| 161 | + # Set the memory limit |
| 162 | + ini_set( 'memory_limit', -1 ); |
| 163 | + |
| 164 | + $wgRequestTime = microtime(true); |
| 165 | + |
| 166 | + # Define us as being in Mediawiki |
| 167 | + define( 'MEDIAWIKI', true ); |
| 168 | + |
| 169 | + # Setup $IP, using MW_INSTALL_PATH if it exists |
| 170 | + $IP = strval( getenv('MW_INSTALL_PATH') ) !== '' |
| 171 | + ? getenv('MW_INSTALL_PATH') |
| 172 | + : realpath( dirname( __FILE__ ) . '/..' ); |
| 173 | + |
| 174 | + $wgCommandLineMode = true; |
| 175 | + # Turn off output buffering if it's on |
| 176 | + @ob_end_flush(); |
| 177 | + |
| 178 | + if (!isset( $wgUseNormalUser ) ) { |
| 179 | + $wgUseNormalUser = false; |
| 180 | + } |
| 181 | + |
| 182 | + $this->loadArgs(); |
| 183 | + $this->maybeHelp(); |
| 184 | + } |
| 185 | + |
| 186 | + /** |
| 187 | + * Process command line arguments |
| 188 | + * $mOptions becomes an array with keys set to the option names |
| 189 | + * $mArgs becomes a zero-based array containing the non-option arguments |
| 190 | + */ |
| 191 | + private function loadArgs() { |
| 192 | + global $argv; |
| 193 | + $this->mSelf = array_shift( $argv ); |
| 194 | + |
| 195 | + $options = array(); |
| 196 | + $args = array(); |
| 197 | + |
| 198 | + # Parse arguments |
| 199 | + for( $arg = reset( $argv ); $arg !== false; $arg = next( $argv ) ) { |
| 200 | + if ( $arg == '--' ) { |
| 201 | + # End of options, remainder should be considered arguments |
| 202 | + $arg = next( $argv ); |
| 203 | + while( $arg !== false ) { |
| 204 | + $args[] = $arg; |
| 205 | + $arg = next( $argv ); |
| 206 | + } |
| 207 | + break; |
| 208 | + } elseif ( substr( $arg, 0, 2 ) == '--' ) { |
| 209 | + # Long options |
| 210 | + $option = substr( $arg, 2 ); |
| 211 | + if ( isset( $this->mParams[$option] ) ) { |
| 212 | + $param = next( $argv ); |
| 213 | + if ( $param === false ) { |
| 214 | + $this->error( "$arg needs a value after it\n", true ); |
| 215 | + } |
| 216 | + $options[$option] = $param; |
| 217 | + } else { |
| 218 | + $bits = explode( '=', $option, 2 ); |
| 219 | + if( count( $bits ) > 1 ) { |
| 220 | + $option = $bits[0]; |
| 221 | + $param = $bits[1]; |
| 222 | + } else { |
| 223 | + $param = 1; |
| 224 | + } |
| 225 | + $options[$option] = $param; |
| 226 | + } |
| 227 | + } elseif ( substr( $arg, 0, 1 ) == '-' ) { |
| 228 | + # Short options |
| 229 | + for ( $p=1; $p<strlen( $arg ); $p++ ) { |
| 230 | + $option = $arg{$p}; |
| 231 | + if ( isset( $this->mParams[$option] ) ) { |
| 232 | + $param = next( $argv ); |
| 233 | + if ( $param === false ) { |
| 234 | + $this->error( "$arg needs a value after it\n", true ); |
| 235 | + } |
| 236 | + $options[$option] = $param; |
| 237 | + } else { |
| 238 | + $options[$option] = 1; |
| 239 | + } |
| 240 | + } |
| 241 | + } else { |
| 242 | + $args[] = $arg; |
| 243 | + } |
| 244 | + } |
| 245 | + |
| 246 | + # These vars get special treatment |
| 247 | + if( isset( $options['dbuser'] ) ) |
| 248 | + $this->mDbUser = $options['dbuser']; |
| 249 | + if( isset( $options['dbpass'] ) ) |
| 250 | + $this->mDbPass = $options['dbpass']; |
| 251 | + if( isset( $options['quiet'] ) ) |
| 252 | + $this->mQuiet = true; |
| 253 | + |
| 254 | + # Check to make sure we've got all the required ones |
| 255 | + foreach( $this->mParams as $opt => $info ) { |
| 256 | + if( $info['required'] && !isset( $this->mOptions[$opt] ) ) { |
| 257 | + $this->error( "Param $opt required.\n", true ); |
| 258 | + } |
| 259 | + } |
| 260 | + |
| 261 | + $this->mOptions = $options; |
| 262 | + $this->mArgs = $args; |
| 263 | + } |
| 264 | + |
| 265 | + /** |
| 266 | + * Maybe show the help. |
| 267 | + */ |
| 268 | + private function maybeHelp() { |
| 269 | + if( isset( $this->mOptions['help'] ) ) { |
| 270 | + $this->mQuiet = false; |
| 271 | + if( $this->mDescription ) { |
| 272 | + $this->output( $this->mDescription . "\n" ); |
| 273 | + } |
| 274 | + $this->output( "\nUsage: php " . $this->mSelf . " [--" . |
| 275 | + implode( array_keys( $this->mParams ), "|--" ) . "]\n" ); |
| 276 | + foreach( $params as $par => $desc ) { |
| 277 | + $this->output( "\t$par : $desc\n" ); |
| 278 | + } |
| 279 | + } |
| 280 | + } |
| 281 | + |
| 282 | + /** |
| 283 | + * Handle some last-minute setup here. |
| 284 | + */ |
| 285 | + private function finalSetup() { |
| 286 | + global $wgCommandLineMode, $wgUseNormalUser, $wgShowSQLErrors; |
| 287 | + global $wgTitle, $wgProfiling, $IP, $wgDBadminuser, $wgDBadminpassword; |
| 288 | + global $wgDBuser, $wgDBpassword, $wgDBservers, $wgLBFactoryConf; |
| 289 | + |
| 290 | + # Turn off output buffering again, it might have been turned on in the settings files |
| 291 | + if( ob_get_level() ) { |
| 292 | + ob_end_flush(); |
| 293 | + } |
| 294 | + # Same with these |
| 295 | + $wgCommandLineMode = true; |
| 296 | + |
| 297 | + # If these were passed, use them |
| 298 | + if( $this->mDbUser ) |
| 299 | + $wgDBadminuser = $this->mDbUser; |
| 300 | + if( $this->mDbPass ) |
| 301 | + $wgDBadminpass = $this->mDbPass; |
| 302 | + |
| 303 | + if ( empty( $wgUseNormalUser ) && isset( $wgDBadminuser ) ) { |
| 304 | + $wgDBuser = $wgDBadminuser; |
| 305 | + $wgDBpassword = $wgDBadminpassword; |
| 306 | + |
| 307 | + if( $wgDBservers ) { |
| 308 | + foreach ( $wgDBservers as $i => $server ) { |
| 309 | + $wgDBservers[$i]['user'] = $wgDBuser; |
| 310 | + $wgDBservers[$i]['password'] = $wgDBpassword; |
| 311 | + } |
| 312 | + } |
| 313 | + if( isset( $wgLBFactoryConf['serverTemplate'] ) ) { |
| 314 | + $wgLBFactoryConf['serverTemplate']['user'] = $wgDBuser; |
| 315 | + $wgLBFactoryConf['serverTemplate']['password'] = $wgDBpassword; |
| 316 | + } |
| 317 | + } |
| 318 | + |
| 319 | + if ( defined( 'MW_CMDLINE_CALLBACK' ) ) { |
| 320 | + $fn = MW_CMDLINE_CALLBACK; |
| 321 | + $fn(); |
| 322 | + } |
| 323 | + |
| 324 | + $wgShowSQLErrors = true; |
| 325 | + @set_time_limit(0); |
| 326 | + |
| 327 | + $wgProfiling = false; // only for Profiler.php mode; avoids OOM errors |
| 328 | + } |
| 329 | + |
| 330 | + /** |
| 331 | + * Do setup specific to WMF |
| 332 | + */ |
| 333 | + public function loadWikimediaSettings() { |
| 334 | + global $IP, $wgNoDBParam, $wgUseNormalUser, $wgConf; |
| 335 | + |
| 336 | + if ( empty( $wgNoDBParam ) ) { |
| 337 | + # Check if we were passed a db name |
| 338 | + if ( isset( $this->mOptions['wiki'] ) ) { |
| 339 | + $db = $this->mOptions['wiki']; |
| 340 | + } else { |
| 341 | + $db = array_shift( $this->mArgs ); |
| 342 | + } |
| 343 | + list( $site, $lang ) = $wgConf->siteFromDB( $db ); |
| 344 | + |
| 345 | + # If not, work out the language and site the old way |
| 346 | + if ( is_null( $site ) || is_null( $lang ) ) { |
| 347 | + if ( !$db ) { |
| 348 | + $lang = 'aa'; |
| 349 | + } else { |
| 350 | + $lang = $db; |
| 351 | + } |
| 352 | + if ( isset( $this->mArgs[0] ) ) { |
| 353 | + $site = array_shift( $this->mArgs ); |
| 354 | + } else { |
| 355 | + $site = 'wikipedia'; |
| 356 | + } |
| 357 | + } |
| 358 | + } else { |
| 359 | + $lang = 'aa'; |
| 360 | + $site = 'wikipedia'; |
| 361 | + } |
| 362 | + |
| 363 | + # This is for the IRC scripts, which now run as the apache user |
| 364 | + # The apache user doesn't have access to the wikiadmin_pass command |
| 365 | + if ( $_ENV['USER'] == 'apache' ) { |
| 366 | + #if ( posix_geteuid() == 48 ) { |
| 367 | + $wgUseNormalUser = true; |
| 368 | + } |
| 369 | + |
| 370 | + putenv( 'wikilang='.$lang); |
| 371 | + |
| 372 | + $DP = $IP; |
| 373 | + ini_set( 'include_path', ".:$IP:$IP/includes:$IP/languages:$IP/maintenance" ); |
| 374 | + |
| 375 | + if ( $lang == 'test' && $site == 'wikipedia' ) { |
| 376 | + define( 'TESTWIKI', 1 ); |
| 377 | + } |
| 378 | + } |
| 379 | + |
| 380 | + /** |
| 381 | + * Generic setup for most installs. Returns the location of LocalSettings |
| 382 | + * @return String |
| 383 | + */ |
| 384 | + public function loadSettings() { |
| 385 | + global $wgWikiFarm, $wgCommandLineMode, $IP, $DP; |
| 386 | + |
| 387 | + $wgWikiFarm = false; |
| 388 | + if ( isset( $this->mOptions['conf'] ) ) { |
| 389 | + $settingsFile = $this->mOptions['conf']; |
| 390 | + } else { |
| 391 | + $settingsFile = "$IP/LocalSettings.php"; |
| 392 | + } |
| 393 | + if ( isset( $this->mOptions['wiki'] ) ) { |
| 394 | + $bits = explode( '-', $this->mOptions['wiki'] ); |
| 395 | + if ( count( $bits ) == 1 ) { |
| 396 | + $bits[] = ''; |
| 397 | + } |
| 398 | + define( 'MW_DB', $bits[0] ); |
| 399 | + define( 'MW_PREFIX', $bits[1] ); |
| 400 | + } |
| 401 | + |
| 402 | + if ( ! is_readable( $settingsFile ) ) { |
| 403 | + $this->error( "A copy of your installation's LocalSettings.php\n" . |
| 404 | + "must exist and be readable in the source directory.\n", true ); |
| 405 | + } |
| 406 | + $wgCommandLineMode = true; |
| 407 | + $DP = $IP; |
| 408 | + $this->finalSetup(); |
| 409 | + return $settingsFile; |
| 410 | + } |
411 | 411 | } |
\ No newline at end of file |
Property changes on: branches/maintenance-work/maintenance/Maintenance.php |
___________________________________________________________________ |
Name: svn:eol-style |
412 | 412 | + native |
Index: branches/maintenance-work/docs/maintenance.txt |
— | — | @@ -1,54 +1,54 @@ |
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( "doMaintenance.php" );
|
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
|
| 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 | +--help : Print a help message |
| 23 | +--quiet : Quiet non-error output |
| 24 | +--dbuser : The database user to use for the script (if needed) |
| 25 | +--dbpass : Same as above (if needed) |
| 26 | + |
| 27 | +3. HOW TO WRITE YOUR OWN |
| 28 | +Make a file in the maintenance directory called myScript.php or something. |
| 29 | +In it, write the following: |
| 30 | + |
| 31 | +==BEGIN== |
| 32 | + |
| 33 | +<?php |
| 34 | + |
| 35 | +require_once( "Maintenance.php" ); |
| 36 | + |
| 37 | +class DemoMaint extends Maintenance { |
| 38 | + |
| 39 | + public function __construct() { |
| 40 | + parent::__construct(); |
| 41 | + } |
| 42 | + |
| 43 | + protected function execute() { |
| 44 | + } |
| 45 | +} |
| 46 | + |
| 47 | +$maintClass = "DemoMaint"; |
| 48 | +require_once( "doMaintenance.php" ); |
| 49 | + |
| 50 | +==END== |
| 51 | + |
| 52 | +That's it. In the execute() method, you have access to all of the normal |
| 53 | +MediaWiki functions, so you can get a DB connection, use the cache, etc. |
| 54 | +For full docs on the Maintenance class, see the auto-generated docs at |
51 | 55 | http://svn.wikimedia.org/doc/classMaintenance.html |
\ No newline at end of file |
Property changes on: branches/maintenance-work/docs/maintenance.txt |
___________________________________________________________________ |
Name: svn:eol-style |
52 | 56 | + native |