Revert r52336 "Merge maintenance-work branch:"
Seems to have broken a bunch of stuff. Don't commit giant non-critical changes that break Setup.php and all maint scripts. Thanks!
This commit is contained in:
parent
ceedb37941
commit
1c9773bd01
57 changed files with 1681 additions and 3125 deletions
32
AdminSettings.sample
Normal file
32
AdminSettings.sample
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* This file should be copied to AdminSettings.php, and modified
|
||||
* to reflect local settings. It is required for the maintenance
|
||||
* scripts which run on the command line, as an extra security
|
||||
* measure to allow using a separate user account with higher
|
||||
* privileges to do maintenance work.
|
||||
*
|
||||
* Developers: Do not check AdminSettings.php into Subversion
|
||||
*/
|
||||
|
||||
/*
|
||||
* This data is used by all database maintenance scripts
|
||||
* (see directory maintenance/). The SQL user MUST BE
|
||||
* MANUALLY CREATED or set to an existing user with
|
||||
* necessary permissions.
|
||||
*
|
||||
* This is not to be confused with sysop accounts for the
|
||||
* wiki.
|
||||
*
|
||||
* NOTE: for PostgreSQL this should be set to the same user and
|
||||
* password as the web user, that is, the same as $wgDBuser and
|
||||
* $wgDBpassword in LocalSettings.php. This is necessary to
|
||||
* ensure that the owner for new tables is set correctly.
|
||||
*/
|
||||
$wgDBadminuser = 'wikiadmin';
|
||||
$wgDBadminpassword = 'adminpass';
|
||||
|
||||
/*
|
||||
* Whether to enable the profileinfo.php script.
|
||||
*/
|
||||
$wgEnableProfileInfo = false;
|
||||
|
|
@ -41,7 +41,6 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
|
|||
appropriate privileges. Creating this user with web-install page requires
|
||||
oci8.privileged_connect set to On in php.ini.
|
||||
* Removed UserrightsChangeableGroups hook introduced in 1.14
|
||||
* AdminSettings.php has been removed completely
|
||||
|
||||
=== New features in 1.16 ===
|
||||
|
||||
|
|
@ -92,10 +91,7 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
|
|||
stripped from them.
|
||||
* Added a PHP port of CDB (constant database), for improved local caching when
|
||||
the DBA extension is not available.
|
||||
* (bug 14201) Create AdminSettings.php during wiki installation, in the same
|
||||
way as LocalSettings.php
|
||||
* (bug 16322) Allow maint scripts to accept DB user/pass over input or params
|
||||
if no AdminSettings.php
|
||||
|
||||
|
||||
=== Bug fixes in 1.16 ===
|
||||
|
||||
|
|
@ -204,8 +200,6 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
|
|||
* (bug 19294) Always show Sp-contributions-footer(-anon)
|
||||
* Attempts to restrict reading of pages while anonymous viewing is allowed
|
||||
via extensions not using the userCan hook and via $wgRevokePermissions now work.
|
||||
* (bug 19157) createAndPromote error on bad password
|
||||
* (bug 18768) Remove AdminSettings.php from MediaWiki core
|
||||
* (bug 8445) Multiple-character search terms are now handled properly for Chinese
|
||||
|
||||
== API changes in 1.16 ==
|
||||
|
|
|
|||
19
UPGRADE
19
UPGRADE
|
|
@ -42,7 +42,8 @@ You can also obtain the new files directly from our Subversion source code
|
|||
repository, via a checkout or export operation.
|
||||
|
||||
Replace the existing MediaWiki files with the new. You should preserve the
|
||||
LocalSettings.php file and the "extensions" and "images" directories.
|
||||
LocalSettings.php file, AdminSettings.php file (if present), and the
|
||||
"extensions" and "images" directories.
|
||||
|
||||
Depending upon your configuration, you may also need to preserve additional
|
||||
directories, including a custom upload directory ($wgUploadDirectory),
|
||||
|
|
@ -50,8 +51,8 @@ deleted file archives, and any custom skins.
|
|||
|
||||
=== Perform the database upgrade ===
|
||||
|
||||
You will need to have $wgDBadminuser and $wgDBadminpass set in your
|
||||
LocalSettings.php, see there for more info.
|
||||
You will need an AdminSettings.php file set up in the correct format; see
|
||||
AdminSettings.sample in the wiki root for more information and examples.
|
||||
|
||||
From the command line, browse to the "maintenance" directory and run the
|
||||
update.php script to check and update the schema. This will insert missing
|
||||
|
|
@ -171,10 +172,10 @@ should be replaced with:
|
|||
=== Web installer ===
|
||||
|
||||
You can use the web-based installer wizard if you first remove the
|
||||
LocalSettings.php file; be sure to give the installer the same
|
||||
information as you did on the original install (language/encoding,
|
||||
database name, password, etc). This will also generate a fresh
|
||||
LocalSettings.php, which you may need to customize.
|
||||
LocalSettings.php (and AdminSettings.php, if any) files; be sure to
|
||||
give the installer the same information as you did on the original
|
||||
install (language/encoding, database name, password, etc). This will
|
||||
also generate a fresh LocalSettings.php, which you may need to customize.
|
||||
|
||||
You may change some settings during the install, but be very careful!
|
||||
Changing the encoding in particular will generally leave you with a
|
||||
|
|
@ -184,8 +185,8 @@ lot of corrupt pages, particularly if your wiki is not in English.
|
|||
|
||||
Additionally, as of 1.4.0 you can run an in-place upgrade script from
|
||||
the command line, keeping your existing LocalSettings.php. This requires
|
||||
that you set $wgDBadminuser and $wgDBadminpassword with an appropriate
|
||||
database user and password with privileges to modify the database structure.
|
||||
that you create an AdminSettings.php giving an appropriate database user
|
||||
and password with privileges to modify the database structure.
|
||||
|
||||
Once the new files are in place, go into the maintenance subdirectory and
|
||||
run the script:
|
||||
|
|
|
|||
|
|
@ -615,7 +615,6 @@ print "<li style='font-weight:bold;color:green;font-size:110%'>Environment check
|
|||
$conf->RootUser = importPost( "RootUser", "root" );
|
||||
$conf->RootPW = importPost( "RootPW", "" );
|
||||
$useRoot = importCheck( 'useroot', false );
|
||||
$conf->populateadmin = importCheck( 'populateadmin', false );
|
||||
$conf->LanguageCode = importPost( "LanguageCode", "en" );
|
||||
## MySQL specific:
|
||||
$conf->DBprefix = importPost( "DBprefix" );
|
||||
|
|
@ -1528,8 +1527,6 @@ if( count( $errs ) ) {
|
|||
<label class="column">Superuser account:</label>
|
||||
<input type="checkbox" name="useroot" id="useroot" <?php if( $useRoot ) { ?>checked="checked" <?php } ?> />
|
||||
<label for="useroot">Use superuser account</label>
|
||||
<input type="checkbox" name="populateadmin" id="populateadmin" <?php if( $conf->populateadmin ) { ?>checked="checked" <?php } ?> />
|
||||
<label for="populateadmin">Set as admin user for maintenance</label>
|
||||
</div>
|
||||
<div class="config-input"><?php aField( $conf, "RootUser", "Superuser name:", "text" ); ?></div>
|
||||
<div class="config-input"><?php aField( $conf, "RootPW", "Superuser password:", "password" ); ?></div>
|
||||
|
|
@ -1795,11 +1792,6 @@ function writeLocalSettings( $conf ) {
|
|||
# Needs literal string interpolation for the current style path
|
||||
$slconf['RightsIcon'] = $conf->RightsIcon;
|
||||
}
|
||||
|
||||
if( $conf->populateadmin ) {
|
||||
$slconf['DBadminuser'] = $conf->RootUser;
|
||||
$slconf['DBadminpassword'] = $conf->RootPW;
|
||||
}
|
||||
|
||||
if( $conf->DBtype == 'mysql' ) {
|
||||
$dbsettings =
|
||||
|
|
@ -1907,10 +1899,6 @@ if ( \$wgCommandLineMode ) {
|
|||
|
||||
{$dbsettings}
|
||||
|
||||
## Database admin settings, used for maintenance scripts
|
||||
\$wgDBadminuser = \"{$slconf['DBadminuser']}\";
|
||||
\$wgDBadminpassword = \"{$slconf['DBadminpassword']}\";
|
||||
|
||||
## Shared memory settings
|
||||
\$wgMainCacheType = $cacheType;
|
||||
\$wgMemCachedServers = $mcservers;
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
Prior to version 1.16, maintenance scripts were a hodgepodge of code that
|
||||
had no cohesion or formal method of action. Beginning in 1.16, maintenance
|
||||
scripts have been cleaned up to use a unified class.
|
||||
|
||||
1. Directory structure
|
||||
2. How to run a script
|
||||
3. How to write your own
|
||||
|
||||
1. DIRECTORY STRUCTURE
|
||||
The /maintenance directory of a MediaWiki installation contains several
|
||||
subdirectories, all of which have unique purposes.
|
||||
|
||||
2. HOW TO RUN A SCRIPT
|
||||
Ridiculously simple, just call 'php someScript.php' that's in the top-
|
||||
level /maintenance directory.
|
||||
|
||||
Example:
|
||||
php clear_stats.php
|
||||
|
||||
The following parameters are available to all maintenance scripts
|
||||
--help : Print a help message
|
||||
--quiet : Quiet non-error output
|
||||
--dbuser : The database user to use for the script (if needed)
|
||||
--dbpass : Same as above (if needed)
|
||||
|
||||
3. HOW TO WRITE YOUR OWN
|
||||
Make a file in the maintenance directory called myScript.php or something.
|
||||
In it, write the following:
|
||||
|
||||
==BEGIN==
|
||||
|
||||
<?php
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class DemoMaint extends Maintenance {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function execute() {
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "DemoMaint";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
||||
==END==
|
||||
|
||||
That's it. In the execute() method, you have access to all of the normal
|
||||
MediaWiki functions, so you can get a DB connection, use the cache, etc.
|
||||
For full docs on the Maintenance class, see the auto-generated docs at
|
||||
http://svn.wikimedia.org/doc/classMaintenance.html
|
||||
|
|
@ -35,9 +35,10 @@ Primary scripts:
|
|||
to force the profiler to save the informations in the database and apply the
|
||||
maintenance/archives/patch-profiling.sql patch to the database.
|
||||
|
||||
To enable the profileinfo.php itself, you'll need to set $wgDBadminuser
|
||||
and $wgDBadminpassword in your LocalSettings.php, as well as $wgEnableProfileInfo
|
||||
See also http://www.mediawiki.org/wiki/How_to_debug#Profiling.
|
||||
To enable the profileinfo.php itself, you'll need to create the
|
||||
AdminSettings.php file (see AdminSettings.sample for more information) and
|
||||
set $wgEnableProfileInfo to true in that file. See also
|
||||
http://www.mediawiki.org/wiki/How_to_debug#Profiling.
|
||||
|
||||
redirect.php
|
||||
Script that only redirect to the article passed in the wpDropdown parameter
|
||||
|
|
|
|||
|
|
@ -49,8 +49,11 @@ class SiteStats {
|
|||
// clean schema with mwdumper.
|
||||
wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" );
|
||||
|
||||
global $IP;
|
||||
require_once "$IP/maintenance/initStats.inc";
|
||||
|
||||
ob_start();
|
||||
self::init( false );
|
||||
wfInitStats();
|
||||
ob_end_clean();
|
||||
|
||||
$row = self::doLoad( wfGetDB( DB_MASTER ) );
|
||||
|
|
@ -174,63 +177,6 @@ class SiteStats {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ported from initStats.inc.
|
||||
* @param $update bool Whether to update the current stats write fresh
|
||||
* @param $noViews bool When true, do not update the number of page views
|
||||
*/
|
||||
function init( $update, $noViews = false ) {
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
|
||||
wfOut( "Counting total edits..." );
|
||||
$edits = $dbr->selectField( 'revision', 'COUNT(*)', '', __METHOD__ );
|
||||
$edits += $dbr->selectField( 'archive', 'COUNT(*)', '', __METHOD__ );
|
||||
wfOut( "{$edits}\nCounting number of articles..." );
|
||||
|
||||
global $wgContentNamespaces;
|
||||
$good = $dbr->selectField( 'page', 'COUNT(*)', array( 'page_namespace' => $wgContentNamespaces, 'page_is_redirect' => 0, 'page_len > 0' ), __METHOD__ );
|
||||
wfOut( "{$good}\nCounting total pages..." );
|
||||
|
||||
$pages = $dbr->selectField( 'page', 'COUNT(*)', '', __METHOD__ );
|
||||
wfOut( "{$pages}\nCounting number of users..." );
|
||||
|
||||
$users = $dbr->selectField( 'user', 'COUNT(*)', '', __METHOD__ );
|
||||
wfOut( "{$users}\nCounting number of admins..." );
|
||||
|
||||
$admin = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), __METHOD__ );
|
||||
wfOut( "{$admin}\nCounting number of images..." );
|
||||
|
||||
$image = $dbr->selectField( 'image', 'COUNT(*)', '', __METHOD__ );
|
||||
wfOut( "{$image}\n" );
|
||||
|
||||
if( !$noViews ) {
|
||||
wfOut( "Counting total page views..." );
|
||||
$views = $dbr->selectField( 'page', 'SUM(page_counter)', '', __METHOD__ );
|
||||
wfOut( "{$views}\n" );
|
||||
}
|
||||
|
||||
wfOut( "\nUpdating site statistics..." );
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$values = array( 'ss_total_edits' => $edits,
|
||||
'ss_good_articles' => $good,
|
||||
'ss_total_pages' => $pages,
|
||||
'ss_users' => $users,
|
||||
'ss_admins' => $admin,
|
||||
'ss_images' => $image );
|
||||
$conds = array( 'ss_row_id' => 1 );
|
||||
$views = array( 'ss_total_views' => isset( $views ) ? $views : 0 );
|
||||
|
||||
if( $update ) {
|
||||
$dbw->update( 'site_stats', $values, $conds, __METHOD__ );
|
||||
} else {
|
||||
$dbw->delete( 'site_stats', $conds, __METHOD__ );
|
||||
$dbw->insert( 'site_stats', array_merge( $values, $conds, $views ), __METHOD__ );
|
||||
}
|
||||
|
||||
wfOut( "done.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ FILE_PATTERNS = *.c \
|
|||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = YES
|
||||
EXCLUDE_PATTERNS = LocalSettings.php
|
||||
EXCLUDE_PATTERNS = LocalSettings.php AdminSettings.php
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
|
|
|
|||
|
|
@ -1,639 +0,0 @@
|
|||
<?php
|
||||
// Define this so scripts can easily find doMaintenance.php
|
||||
define( 'DO_MAINTENANCE', dirname(__FILE__) . '/doMaintenance.php' );
|
||||
|
||||
/**
|
||||
* Abstract maintenance class for quickly writing and churning out
|
||||
* maintenance scripts with minimal effort. All that _must_ be defined
|
||||
* is the execute() method. See docs/maintenance.txt for more info
|
||||
* and a quick demo of how to use it.
|
||||
*
|
||||
* @author Chad Horohoe <chad@anyonecanedit.org>
|
||||
* @since 1.16
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
abstract class Maintenance {
|
||||
|
||||
/**
|
||||
* Constants for DB access type
|
||||
* @see Maintenance::getDbType()
|
||||
*/
|
||||
const NO_DB = 0;
|
||||
const NORMAL_DB = 1;
|
||||
const ADMIN_DB = 2;
|
||||
|
||||
// This is the desired params
|
||||
private $mParams = array();
|
||||
|
||||
// Array of desired args
|
||||
private $mArgList = array();
|
||||
|
||||
// This is the list of options that were actually passed
|
||||
private $mOptions = array();
|
||||
|
||||
// This is the list of arguments that were actually passed
|
||||
protected $mArgs = array();
|
||||
|
||||
// Name of the script currently running
|
||||
protected $mSelf;
|
||||
|
||||
// Special vars for params that are always used
|
||||
private $mQuiet = false;
|
||||
private $mDbUser, $mDbPass;
|
||||
|
||||
// A description of the script, children should change this
|
||||
protected $mDescription = '';
|
||||
|
||||
// Have we already loaded our user input?
|
||||
private $inputLoaded = false;
|
||||
|
||||
// Batch size
|
||||
protected $mBatchSize = 100;
|
||||
|
||||
/**
|
||||
* Default constructor. Children should call this if implementing
|
||||
* their own constructors
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->addDefaultParams();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the actual work. All child classes will need to implement this
|
||||
*/
|
||||
abstract public function execute();
|
||||
|
||||
/**
|
||||
* Add a parameter to the script. Will be displayed on --help
|
||||
* with the associated description
|
||||
*
|
||||
* @param $name String The name of the param (help, version, etc)
|
||||
* @param $description String The description of the param to show on --help
|
||||
* @param $required boolean Is the param required?
|
||||
* @param $withArg Boolean Is an argument required with this option?
|
||||
*/
|
||||
protected function addParam( $name, $description, $required = false, $withArg = false ) {
|
||||
$this->mParams[ $name ] = array( 'desc' => $description, 'require' => $required, 'withArg' => $withArg );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a particular param exists.
|
||||
* @param $name String The name of the param
|
||||
* @return boolean
|
||||
*/
|
||||
protected function hasOption( $name ) {
|
||||
return isset( $this->mOptions[ $name ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an option, or return the default
|
||||
* @param $name String The name of the param
|
||||
* @param $default mixed Anything you want, default null
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getOption( $name, $default = null ) {
|
||||
if( $this->hasOption($name) ) {
|
||||
return $this->mOptions[$name];
|
||||
} else {
|
||||
// Set it so we don't have to provide the default again
|
||||
$this->mOptions[$name] = $default;
|
||||
return $this->mOptions[$name];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add some args that are needed. Used in formatting help
|
||||
*/
|
||||
protected function addArgs( $args ) {
|
||||
$this->mArgList = array_merge( $this->mArgList, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a given argument exist?
|
||||
* @param $argId int The integer value (from zero) for the arg
|
||||
* @return boolean
|
||||
*/
|
||||
protected function hasArg( $argId = 0 ) {
|
||||
return isset( $this->mArgs[ $argId ] ) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an argument.
|
||||
* @param $argId int The integer value (from zero) for the arg
|
||||
* @param $default mixed The default if it doesn't exist
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getArg( $argId = 0, $default = null ) {
|
||||
return $this->hasArg($name) ? $this->mArgs[$name] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the batch size.
|
||||
* @param $s int The number of operations to do in a batch
|
||||
*/
|
||||
protected function setBatchSize( $s = 0 ) {
|
||||
$this->mBatchSize = $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return input from stdin.
|
||||
* @param $length int The number of bytes to read. If null,
|
||||
* just return the handle
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getStdin( $len = null ) {
|
||||
$f = fopen( 'php://stdin', 'rt' );
|
||||
if( !$len ) {
|
||||
return $f;
|
||||
}
|
||||
$input = fgets( $f, $len );
|
||||
fclose ( $f );
|
||||
return rtrim( $input );
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw some output to the user. Scripts can call this with no fears,
|
||||
* as we handle all --quiet stuff here
|
||||
* @param $out String The text to show to the user
|
||||
*/
|
||||
protected function output( $out ) {
|
||||
if( $this->mQuiet ) {
|
||||
return;
|
||||
}
|
||||
$f = fopen( 'php://stdout', 'w' );
|
||||
fwrite( $f, $out );
|
||||
fclose( $f );
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an error to the user. Doesn't respect --quiet, so don't use
|
||||
* this for non-error output
|
||||
* @param $err String The error to display
|
||||
* @param $die boolean If true, go ahead and die out.
|
||||
*/
|
||||
protected function error( $err, $die = false ) {
|
||||
$f = fopen( 'php://stderr', 'w' );
|
||||
fwrite( $f, $err );
|
||||
fclose( $f );
|
||||
if( $die ) die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the script need normal DB access? By default, we give Maintenance
|
||||
* scripts admin rights to the DB (when available). Sometimes, a script needs
|
||||
* normal access for a reason and sometimes they want no access. Subclasses
|
||||
* should override and return one of the following values, as needed:
|
||||
* Maintenance::NO_DB - For no DB access at all
|
||||
* Maintenance::NORMAL_DB - For normal DB access
|
||||
* Maintenance::ADMIN_DB - For admin DB access, default
|
||||
* @return int
|
||||
*/
|
||||
protected function getDbType() {
|
||||
return Maintenance :: ADMIN_DB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the default parameters to the scripts
|
||||
*/
|
||||
private function addDefaultParams() {
|
||||
$this->addParam( 'help', "Display this help message" );
|
||||
$this->addParam( 'quiet', "Whether to supress non-error output" );
|
||||
$this->addParam( 'conf', "Location of LocalSettings.php, if not default", false, true );
|
||||
$this->addParam( 'wiki', "For specifying the wiki ID", false, true );
|
||||
if( $this->getDbType() > 0 ) {
|
||||
$this->addParam( 'dbuser', "The DB user to use for this script", false, true );
|
||||
$this->addParam( 'dbpass', "The password to use for this script", false, true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn a child maintenance script. Pass all of the current arguments
|
||||
* to it.
|
||||
* @param $maintClass String A name of a child maintenance class
|
||||
* @param $classFile String Full path of where the child is
|
||||
* @return Maintenance child
|
||||
*/
|
||||
protected function spawnChild( $maintClass, $classFile = null ) {
|
||||
// If we haven't already specified, kill setup procedures
|
||||
// for child scripts, we've already got a sane environment
|
||||
if( !defined( 'MW_NO_SETUP' ) ) {
|
||||
define( 'MW_NO_SETUP', true );
|
||||
}
|
||||
|
||||
// Make sure the class is loaded first
|
||||
if( !class_exists( $maintClass ) ) {
|
||||
if( $classFile ) {
|
||||
require_once( $classFile );
|
||||
}
|
||||
if( !class_exists( $maintClass ) ) {
|
||||
$this->error( "Cannot spawn child: $maintClass\n" );
|
||||
}
|
||||
}
|
||||
|
||||
$child = new $maintClass();
|
||||
$child->loadParamsAndArgs( $this->mSelf, $this->mOptions, $this->mArgs );
|
||||
return $child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do some sanity checking and basic setup
|
||||
*/
|
||||
public function setup() {
|
||||
global $IP, $wgCommandLineMode, $wgUseNormalUser, $wgRequestTime;
|
||||
|
||||
# Abort if called from a web server
|
||||
if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) {
|
||||
$this->error( "This script must be run from the command line\n", true );
|
||||
}
|
||||
|
||||
# Make sure we can handle script parameters
|
||||
if( !ini_get( 'register_argc_argv' ) ) {
|
||||
$this->error( "Cannot get command line arguments, register_argc_argv is set to false", true );
|
||||
}
|
||||
|
||||
# Make sure we're on PHP5 or better
|
||||
if( version_compare( PHP_VERSION, '5.0.0' ) < 0 ) {
|
||||
$this->error( "Sorry! This version of MediaWiki requires PHP 5; you are running " .
|
||||
PHP_VERSION . ".\n\n" .
|
||||
"If you are sure you already have PHP 5 installed, it may be installed\n" .
|
||||
"in a different path from PHP 4. Check with your system administrator.\n", true );
|
||||
}
|
||||
|
||||
if( version_compare( phpversion(), '5.2.4' ) >= 0 ) {
|
||||
// Send PHP warnings and errors to stderr instead of stdout.
|
||||
// This aids in diagnosing problems, while keeping messages
|
||||
// out of redirected output.
|
||||
if( ini_get( 'display_errors' ) ) {
|
||||
ini_set( 'display_errors', 'stderr' );
|
||||
}
|
||||
|
||||
// Don't touch the setting on earlier versions of PHP,
|
||||
// as setting it would disable output if you'd wanted it.
|
||||
|
||||
// Note that exceptions are also sent to stderr when
|
||||
// command-line mode is on, regardless of PHP version.
|
||||
}
|
||||
|
||||
# Set the memory limit
|
||||
ini_set( 'memory_limit', -1 );
|
||||
|
||||
$wgRequestTime = microtime(true);
|
||||
|
||||
# Define us as being in Mediawiki
|
||||
define( 'MEDIAWIKI', true );
|
||||
|
||||
# Setup $IP, using MW_INSTALL_PATH if it exists
|
||||
$IP = strval( getenv('MW_INSTALL_PATH') ) !== ''
|
||||
? getenv('MW_INSTALL_PATH')
|
||||
: realpath( dirname( __FILE__ ) . '/..' );
|
||||
|
||||
$wgCommandLineMode = true;
|
||||
# Turn off output buffering if it's on
|
||||
@ob_end_flush();
|
||||
|
||||
if (!isset( $wgUseNormalUser ) ) {
|
||||
$wgUseNormalUser = false;
|
||||
}
|
||||
|
||||
$this->loadParamsAndArgs();
|
||||
$this->maybeHelp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all params and arguments.
|
||||
*/
|
||||
public function clearParamsAndArgs() {
|
||||
$this->mOptions = array();
|
||||
$this->mArgs = array();
|
||||
$this->inputLoaded = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process command line arguments
|
||||
* $mOptions becomes an array with keys set to the option names
|
||||
* $mArgs becomes a zero-based array containing the non-option arguments
|
||||
*
|
||||
* @param $self String The name of the script, if any
|
||||
* @param $opts Array An array of options, in form of key=>value
|
||||
* @param $args Array An array of command line arguments
|
||||
*/
|
||||
public function loadParamsAndArgs( $self = null, $opts = null, $args = null ) {
|
||||
# If we were given opts or args, set those and return early
|
||||
if( $self ) {
|
||||
$this->mSelf = $self;
|
||||
$this->inputLoaded = true;
|
||||
}
|
||||
if( $opts ) {
|
||||
$this->mOptions = $opts;
|
||||
$this->inputLoaded = true;
|
||||
}
|
||||
if( $args ) {
|
||||
$this->mArgs = $args;
|
||||
$this->inputLoaded = true;
|
||||
}
|
||||
|
||||
# If we've already loaded input (either by user values or from $argv)
|
||||
# skip on loading it again. The array_shift() will corrupt values if
|
||||
# it's run again and again
|
||||
if( $this->inputLoaded ) {
|
||||
$this->loadSpecialVars();
|
||||
return;
|
||||
}
|
||||
|
||||
global $argv;
|
||||
$this->mSelf = array_shift( $argv );
|
||||
|
||||
$options = array();
|
||||
$args = array();
|
||||
|
||||
# Parse arguments
|
||||
for( $arg = reset( $argv ); $arg !== false; $arg = next( $argv ) ) {
|
||||
if ( $arg == '--' ) {
|
||||
# End of options, remainder should be considered arguments
|
||||
$arg = next( $argv );
|
||||
while( $arg !== false ) {
|
||||
$args[] = $arg;
|
||||
$arg = next( $argv );
|
||||
}
|
||||
break;
|
||||
} elseif ( substr( $arg, 0, 2 ) == '--' ) {
|
||||
# Long options
|
||||
$option = substr( $arg, 2 );
|
||||
if ( isset( $this->mParams[$option] ) && $this->mParams[$option]['withArg'] ) {
|
||||
$param = next( $argv );
|
||||
if ( $param === false ) {
|
||||
$this->error( "$arg needs a value after it\n", true );
|
||||
}
|
||||
$options[$option] = $param;
|
||||
} else {
|
||||
$bits = explode( '=', $option, 2 );
|
||||
if( count( $bits ) > 1 ) {
|
||||
$option = $bits[0];
|
||||
$param = $bits[1];
|
||||
} else {
|
||||
$param = 1;
|
||||
}
|
||||
$options[$option] = $param;
|
||||
}
|
||||
} elseif ( substr( $arg, 0, 1 ) == '-' ) {
|
||||
# Short options
|
||||
for ( $p=1; $p<strlen( $arg ); $p++ ) {
|
||||
$option = $arg{$p};
|
||||
if ( isset( $this->mParams[$option]['withArg'] ) ) {
|
||||
$param = next( $argv );
|
||||
if ( $param === false ) {
|
||||
$this->error( "$arg needs a value after it\n", true );
|
||||
}
|
||||
$options[$option] = $param;
|
||||
} else {
|
||||
$options[$option] = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$args[] = $arg;
|
||||
}
|
||||
}
|
||||
|
||||
# Check to make sure we've got all the required ones
|
||||
foreach( $this->mParams as $opt => $info ) {
|
||||
if( $info['require'] && !$this->hasOption($opt) ) {
|
||||
$this->error( "Param $opt required.\n", true );
|
||||
}
|
||||
}
|
||||
|
||||
# Also make sure we've got enough arguments
|
||||
if ( count( $args ) < count( $this->mArgList ) ) {
|
||||
$this->error( "Not enough arguments passed", true );
|
||||
}
|
||||
|
||||
$this->mOptions = $options;
|
||||
$this->mArgs = $args;
|
||||
$this->loadSpecialVars();
|
||||
$this->inputLoaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the special variables that are global to all scripts
|
||||
*/
|
||||
private function loadSpecialVars() {
|
||||
if( $this->hasOption( 'dbuser' ) )
|
||||
$this->mDbUser = $this->getOption( 'dbuser' );
|
||||
if( $this->hasOption( 'dbpass' ) )
|
||||
$this->mDbPass = $this->getOption( 'dbpass' );
|
||||
if( $this->hasOption( 'quiet' ) )
|
||||
$this->mQuiet = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe show the help.
|
||||
* @param $force boolean Whether to force the help to show, default false
|
||||
*/
|
||||
private function maybeHelp( $force = false ) {
|
||||
if( $this->hasOption('help') || in_array( 'help', $this->mArgs ) || $force ) {
|
||||
$this->mQuiet = false;
|
||||
if( $this->mDescription ) {
|
||||
$this->output( $this->mDescription . "\n" );
|
||||
}
|
||||
$this->output( "\nUsage: php " . $this->mSelf );
|
||||
if( $this->mParams ) {
|
||||
$this->output( " [--" . implode( array_keys( $this->mParams ), "|--" ) . "]" );
|
||||
}
|
||||
if( $this->mArgList ) {
|
||||
$this->output( " <" . implode( $this->mArgList, "> <" ) . ">" );
|
||||
}
|
||||
$this->output( "\n" );
|
||||
foreach( $this->mParams as $par => $info ) {
|
||||
$this->output( "\t$par : " . $info['desc'] . "\n" );
|
||||
}
|
||||
die( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle some last-minute setup here.
|
||||
*/
|
||||
private function finalSetup() {
|
||||
global $wgCommandLineMode, $wgUseNormalUser, $wgShowSQLErrors;
|
||||
global $wgTitle, $wgProfiling, $IP, $wgDBadminuser, $wgDBadminpassword;
|
||||
global $wgDBuser, $wgDBpassword, $wgDBservers, $wgLBFactoryConf;
|
||||
|
||||
# Turn off output buffering again, it might have been turned on in the settings files
|
||||
if( ob_get_level() ) {
|
||||
ob_end_flush();
|
||||
}
|
||||
# Same with these
|
||||
$wgCommandLineMode = true;
|
||||
|
||||
# If these were passed, use them
|
||||
if( $this->mDbUser )
|
||||
$wgDBadminuser = $this->mDbUser;
|
||||
if( $this->mDbPass )
|
||||
$wgDBadminpass = $this->mDbPass;
|
||||
|
||||
if ( empty( $wgUseNormalUser ) && isset( $wgDBadminuser ) ) {
|
||||
$wgDBuser = $wgDBadminuser;
|
||||
$wgDBpassword = $wgDBadminpassword;
|
||||
|
||||
if( $wgDBservers ) {
|
||||
foreach ( $wgDBservers as $i => $server ) {
|
||||
$wgDBservers[$i]['user'] = $wgDBuser;
|
||||
$wgDBservers[$i]['password'] = $wgDBpassword;
|
||||
}
|
||||
}
|
||||
if( isset( $wgLBFactoryConf['serverTemplate'] ) ) {
|
||||
$wgLBFactoryConf['serverTemplate']['user'] = $wgDBuser;
|
||||
$wgLBFactoryConf['serverTemplate']['password'] = $wgDBpassword;
|
||||
}
|
||||
}
|
||||
|
||||
if ( defined( 'MW_CMDLINE_CALLBACK' ) ) {
|
||||
$fn = MW_CMDLINE_CALLBACK;
|
||||
$fn();
|
||||
}
|
||||
|
||||
$wgShowSQLErrors = true;
|
||||
@set_time_limit( 0 );
|
||||
|
||||
$wgProfiling = false; // only for Profiler.php mode; avoids OOM errors
|
||||
}
|
||||
|
||||
/**
|
||||
* Do setup specific to WMF
|
||||
*/
|
||||
public function loadWikimediaSettings() {
|
||||
global $IP, $wgNoDBParam, $wgUseNormalUser, $wgConf;
|
||||
|
||||
if ( empty( $wgNoDBParam ) ) {
|
||||
# Check if we were passed a db name
|
||||
if ( isset( $this->mOptions['wiki'] ) ) {
|
||||
$db = $this->mOptions['wiki'];
|
||||
} else {
|
||||
$db = array_shift( $this->mArgs );
|
||||
}
|
||||
list( $site, $lang ) = $wgConf->siteFromDB( $db );
|
||||
|
||||
# If not, work out the language and site the old way
|
||||
if ( is_null( $site ) || is_null( $lang ) ) {
|
||||
if ( !$db ) {
|
||||
$lang = 'aa';
|
||||
} else {
|
||||
$lang = $db;
|
||||
}
|
||||
if ( isset( $this->mArgs[0] ) ) {
|
||||
$site = array_shift( $this->mArgs );
|
||||
} else {
|
||||
$site = 'wikipedia';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$lang = 'aa';
|
||||
$site = 'wikipedia';
|
||||
}
|
||||
|
||||
# This is for the IRC scripts, which now run as the apache user
|
||||
# The apache user doesn't have access to the wikiadmin_pass command
|
||||
if ( $_ENV['USER'] == 'apache' ) {
|
||||
#if ( posix_geteuid() == 48 ) {
|
||||
$wgUseNormalUser = true;
|
||||
}
|
||||
|
||||
putenv( 'wikilang=' . $lang );
|
||||
|
||||
$DP = $IP;
|
||||
ini_set( 'include_path', ".:$IP:$IP/includes:$IP/languages:$IP/maintenance" );
|
||||
|
||||
if ( $lang == 'test' && $site == 'wikipedia' ) {
|
||||
define( 'TESTWIKI', 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic setup for most installs. Returns the location of LocalSettings
|
||||
* @return String
|
||||
*/
|
||||
public function loadSettings() {
|
||||
global $wgWikiFarm, $wgCommandLineMode, $IP, $DP;
|
||||
|
||||
$wgWikiFarm = false;
|
||||
if ( isset( $this->mOptions['conf'] ) ) {
|
||||
$settingsFile = $this->mOptions['conf'];
|
||||
} else {
|
||||
$settingsFile = "$IP/LocalSettings.php";
|
||||
}
|
||||
if ( isset( $this->mOptions['wiki'] ) ) {
|
||||
$bits = explode( '-', $this->mOptions['wiki'] );
|
||||
if ( count( $bits ) == 1 ) {
|
||||
$bits[] = '';
|
||||
}
|
||||
define( 'MW_DB', $bits[0] );
|
||||
define( 'MW_PREFIX', $bits[1] );
|
||||
}
|
||||
|
||||
if ( ! is_readable( $settingsFile ) ) {
|
||||
$this->error( "A copy of your installation's LocalSettings.php\n" .
|
||||
"must exist and be readable in the source directory.\n", true );
|
||||
}
|
||||
$wgCommandLineMode = true;
|
||||
$DP = $IP;
|
||||
$this->finalSetup();
|
||||
return $settingsFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support function for cleaning up redundant text records
|
||||
* @param $delete boolean Whether or not to actually delete the records
|
||||
* @author Rob Church <robchur@gmail.com>
|
||||
*/
|
||||
protected function purgeRedundantText( $delete = true ) {
|
||||
# Data should come off the master, wrapped in a transaction
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
$tbl_arc = $dbw->tableName( 'archive' );
|
||||
$tbl_rev = $dbw->tableName( 'revision' );
|
||||
$tbl_txt = $dbw->tableName( 'text' );
|
||||
|
||||
# Get "active" text records from the revisions table
|
||||
$this->output( "Searching for active text records in revisions table..." );
|
||||
$res = $dbw->query( "SELECT DISTINCT rev_text_id FROM $tbl_rev" );
|
||||
while( $row = $dbw->fetchObject( $res ) ) {
|
||||
$cur[] = $row->rev_text_id;
|
||||
}
|
||||
$this->output( "done.\n" );
|
||||
|
||||
# Get "active" text records from the archive table
|
||||
$this->output( "Searching for active text records in archive table..." );
|
||||
$res = $dbw->query( "SELECT DISTINCT ar_text_id FROM $tbl_arc" );
|
||||
while( $row = $dbw->fetchObject( $res ) ) {
|
||||
$cur[] = $row->ar_text_id;
|
||||
}
|
||||
$this->output( "done.\n" );
|
||||
|
||||
# Get the IDs of all text records not in these sets
|
||||
$this->output( "Searching for inactive text records..." );
|
||||
$set = implode( ', ', $cur );
|
||||
$res = $dbw->query( "SELECT old_id FROM $tbl_txt WHERE old_id NOT IN ( $set )" );
|
||||
$old = array();
|
||||
while( $row = $dbw->fetchObject( $res ) ) {
|
||||
$old[] = $row->old_id;
|
||||
}
|
||||
$this->output( "done.\n" );
|
||||
|
||||
# Inform the user of what we're going to do
|
||||
$count = count( $old );
|
||||
$this->output( "$count inactive items found.\n" );
|
||||
|
||||
# Delete as appropriate
|
||||
if( $delete && $count ) {
|
||||
$this->output( "Deleting..." );
|
||||
$set = implode( ', ', $old );
|
||||
$dbw->query( "DELETE FROM $tbl_txt WHERE old_id IN ( $set )" );
|
||||
$this->output( "done.\n" );
|
||||
}
|
||||
|
||||
# Done
|
||||
$dbw->commit();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -10,8 +10,8 @@ proper installation.
|
|||
|
||||
Certain scripts will require elevated access to the database. In order to
|
||||
provide this, first create a MySQL user with "all" permissions on the wiki
|
||||
database, and then set $wgDBadminuser and $wgDBadminpassword in your
|
||||
LocalSettings.php
|
||||
database, and then place their username and password in an AdminSettings.php
|
||||
file in the directory above. See AdminSettings.sample for specifics on this.
|
||||
|
||||
=== Brief explanation of files ===
|
||||
|
||||
|
|
|
|||
|
|
@ -25,58 +25,49 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
class AttachLatest extends Maintenance {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->addParam( "fix", "Actually fix the entries, will dry run otherwise" );
|
||||
$this->mDescription = "Fix page_latest entries in the page table";
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$this->output( "Looking for pages with page_latest set to 0...\n" );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$result = $dbw->select( 'page',
|
||||
array( 'page_id', 'page_namespace', 'page_title' ),
|
||||
array( 'page_latest' => 0 ),
|
||||
__METHOD__ );
|
||||
$fixit = isset( $options['fix'] );
|
||||
$fname = 'attachLatest';
|
||||
|
||||
$n = 0;
|
||||
while( $row = $dbw->fetchObject( $result ) ) {
|
||||
$pageId = intval( $row->page_id );
|
||||
$title = Title::makeTitle( $row->page_namespace, $row->page_title );
|
||||
$name = $title->getPrefixedText();
|
||||
$latestTime = $dbw->selectField( 'revision',
|
||||
'MAX(rev_timestamp)',
|
||||
array( 'rev_page' => $pageId ),
|
||||
__METHOD__ );
|
||||
if( !$latestTime ) {
|
||||
$this->output( wfWikiID()." $pageId [[$name]] can't find latest rev time?!\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
$revision = Revision::loadFromTimestamp( $dbw, $title, $latestTime );
|
||||
if( is_null( $revision ) ) {
|
||||
$this->output( wfWikiID()." $pageId [[$name]] latest time $latestTime, can't find revision id\n" );
|
||||
continue;
|
||||
}
|
||||
$id = $revision->getId();
|
||||
$this->output( wfWikiID()." $pageId [[$name]] latest time $latestTime, rev id $id\n" );
|
||||
if( $this->hasOption('fix') ) {
|
||||
$article = new Article( $title );
|
||||
$article->updateRevisionOn( $dbw, $revision );
|
||||
}
|
||||
$n++;
|
||||
}
|
||||
$dbw->freeResult( $result );
|
||||
$this->output( "Done! Processed $n pages.\n" );
|
||||
if( !$this->hasOption('fix') ) {
|
||||
$this->output( "This was a dry run; rerun with --fix to update page_latest.\n" );
|
||||
}
|
||||
echo "Looking for pages with page_latest set to 0...\n";
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$result = $dbw->select( 'page',
|
||||
array( 'page_id', 'page_namespace', 'page_title' ),
|
||||
array( 'page_latest' => 0 ),
|
||||
$fname );
|
||||
|
||||
$n = 0;
|
||||
while( $row = $dbw->fetchObject( $result ) ) {
|
||||
$pageId = intval( $row->page_id );
|
||||
$title = Title::makeTitle( $row->page_namespace, $row->page_title );
|
||||
$name = $title->getPrefixedText();
|
||||
$latestTime = $dbw->selectField( 'revision',
|
||||
'MAX(rev_timestamp)',
|
||||
array( 'rev_page' => $pageId ),
|
||||
$fname );
|
||||
if( !$latestTime ) {
|
||||
echo wfWikiID()." $pageId [[$name]] can't find latest rev time?!\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$revision = Revision::loadFromTimestamp( $dbw, $title, $latestTime );
|
||||
if( is_null( $revision ) ) {
|
||||
echo wfWikiID()." $pageId [[$name]] latest time $latestTime, can't find revision id\n";
|
||||
continue;
|
||||
}
|
||||
$id = $revision->getId();
|
||||
echo wfWikiID()." $pageId [[$name]] latest time $latestTime, rev id $id\n";
|
||||
if( $fixit ) {
|
||||
$article = new Article( $title );
|
||||
$article->updateRevisionOn( $dbw, $revision );
|
||||
}
|
||||
$n++;
|
||||
}
|
||||
$dbw->freeResult( $result );
|
||||
echo "Done! Processed $n pages.\n";
|
||||
if( !$fixit ) {
|
||||
echo "This was a dry run; rerun with --fix to update page_latest.\n";
|
||||
}
|
||||
|
||||
$maintClass = "AttachLatest";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
||||
|
|
|
|||
|
|
@ -6,87 +6,74 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
/** */
|
||||
require_once( "commandLine.inc" );
|
||||
|
||||
class BenchmarkPurge extends Maintenance {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->addParams( "count", "How many URLs to feed to Squid for purging", false, true );
|
||||
$this->mDescription = "Benchmark the Squid purge functions.";
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUseSquid;
|
||||
if( !$wgUseSquid ) {
|
||||
$this->error( "Squid purge benchmark doesn't do much without squid support on.\n". true );
|
||||
} else {
|
||||
$this->output( "There are " . count( $wgSquidServers ) . " defined squid servers:\n" );
|
||||
if( $this->hasOption( 'count' ) ) {
|
||||
$lengths = array( intval( $this->getOption('count') ) );
|
||||
} else {
|
||||
$lengths = array( 1, 10, 100 );
|
||||
}
|
||||
foreach( $lengths as $length ) {
|
||||
$urls = $this->randomUrlList( $length );
|
||||
$trial = $this->benchSquid( $urls );
|
||||
$this->output( $trial . "\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a bunch of URLs through SquidUpdate::purge()
|
||||
* to benchmark Squid response times.
|
||||
* @param $urls array A bunch of URLs to purge
|
||||
* @param $trials int How many times to run the test?
|
||||
*/
|
||||
private function benchSquid( $urls, $trials = 1 ) {
|
||||
$start = wfTime();
|
||||
for( $i = 0; $i < $trials; $i++) {
|
||||
SquidUpdate::purge( $urls );
|
||||
}
|
||||
$delta = wfTime() - $start;
|
||||
$pertrial = $delta / $trials;
|
||||
$pertitle = $pertrial / count( $urls );
|
||||
return sprintf( "%4d titles in %6.2fms (%6.2fms each)",
|
||||
count( $urls ), $pertrial * 1000.0, $pertitle * 1000.0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of randomUrl()'s.
|
||||
* @param $length int How many urls to add to the array
|
||||
*/
|
||||
private function randomUrlList( $length ) {
|
||||
$list = array();
|
||||
for( $i = 0; $i < $length; $i++ ) {
|
||||
$list[] = $this->randomUrl();
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a random URL of the wiki. Not necessarily an actual title in the
|
||||
* database, but at least a URL that looks like one.
|
||||
*/
|
||||
private function randomUrl() {
|
||||
global $wgServer, $wgArticlePath;
|
||||
return $wgServer . str_replace( '$1', $this->randomTitle(), $wgArticlePath );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a random title string (not necessarily a Title object).
|
||||
* For use with randomUrl().
|
||||
*/
|
||||
private function randomTitle() {
|
||||
$str = '';
|
||||
$length = mt_rand( 1, 20 );
|
||||
for( $i = 0; $i < $length; $i++ ) {
|
||||
$str .= chr( mt_rand( ord('a'), ord('z') ) );
|
||||
}
|
||||
return ucfirst( $str );
|
||||
/**
|
||||
* Run a bunch of URLs through SquidUpdate::purge()
|
||||
* to benchmark Squid response times.
|
||||
* @param $urls array A bunch of URLs to purge
|
||||
* @param $trials int How many times to run the test?
|
||||
*/
|
||||
function benchSquid( $urls, $trials = 1 ) {
|
||||
$start = wfTime();
|
||||
for( $i = 0; $i < $trials; $i++) {
|
||||
SquidUpdate::purge( $urls );
|
||||
}
|
||||
$delta = wfTime() - $start;
|
||||
$pertrial = $delta / $trials;
|
||||
$pertitle = $pertrial / count( $urls );
|
||||
return sprintf( "%4d titles in %6.2fms (%6.2fms each)",
|
||||
count( $urls ), $pertrial * 1000.0, $pertitle * 1000.0 );
|
||||
}
|
||||
|
||||
$maintClass = "BenchmarkPurge";
|
||||
require_once( DO_MAINTENANCE );
|
||||
/**
|
||||
* Get an array of randomUrl()'s.
|
||||
* @param $length int How many urls to add to the array
|
||||
*/
|
||||
function randomUrlList( $length ) {
|
||||
$list = array();
|
||||
for( $i = 0; $i < $length; $i++ ) {
|
||||
$list[] = randomUrl();
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a random URL of the wiki. Not necessarily an actual title in the
|
||||
* database, but at least a URL that looks like one.
|
||||
*/
|
||||
function randomUrl() {
|
||||
global $wgServer, $wgArticlePath;
|
||||
return $wgServer . str_replace( '$1', randomTitle(), $wgArticlePath );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a random title string (not necessarily a Title object).
|
||||
* For use with randomUrl().
|
||||
*/
|
||||
function randomTitle() {
|
||||
$str = '';
|
||||
$length = mt_rand( 1, 20 );
|
||||
for( $i = 0; $i < $length; $i++ ) {
|
||||
$str .= chr( mt_rand( ord('a'), ord('z') ) );
|
||||
}
|
||||
return ucfirst( $str );
|
||||
}
|
||||
|
||||
if( !$wgUseSquid ) {
|
||||
wfDie( "Squid purge benchmark doesn't do much without squid support on.\n" );
|
||||
} else {
|
||||
printf( "There are %d defined squid servers:\n", count( $wgSquidServers ) );
|
||||
#echo implode( "\n", $wgSquidServers ) . "\n";
|
||||
if( isset( $options['count'] ) ) {
|
||||
$lengths = array( intval( $options['count'] ) );
|
||||
} else {
|
||||
$lengths = array( 1, 10, 100 );
|
||||
}
|
||||
foreach( $lengths as $length ) {
|
||||
$urls = randomUrlList( $length );
|
||||
$trial = benchSquid( $urls );
|
||||
print "$trial\n";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,32 +10,47 @@
|
|||
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$optionsWithArgs = array( 'user', 'password' );
|
||||
require_once 'commandLine.inc';
|
||||
|
||||
class ChangePassword extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->addParam( "user", "The username to operate on", true, true );
|
||||
$this->addParam( "password", "The password to use", true, true );
|
||||
$this->mDescription = "Change a user's password."
|
||||
$USAGE =
|
||||
"Usage: php changePassword.php [--user=user --password=password | --help]\n" .
|
||||
"\toptions:\n" .
|
||||
"\t\t--help show this message\n" .
|
||||
"\t\t--user the username to operate on\n" .
|
||||
"\t\t--password the password to use\n";
|
||||
|
||||
if( in_array( '--help', $argv ) )
|
||||
wfDie( $USAGE );
|
||||
|
||||
$cp = new ChangePassword( @$options['user'], @$options['password'] );
|
||||
$cp->main();
|
||||
|
||||
/**
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
class ChangePassword {
|
||||
var $dbw;
|
||||
var $user, $password;
|
||||
|
||||
function ChangePassword( $user, $password ) {
|
||||
global $USAGE;
|
||||
if( !strlen( $user ) or !strlen( $password ) ) {
|
||||
wfDie( $USAGE );
|
||||
}
|
||||
|
||||
$this->user = User::newFromName( $user );
|
||||
if ( !$this->user->getId() ) {
|
||||
die ( "No such user: $user\n" );
|
||||
}
|
||||
|
||||
$this->password = $password;
|
||||
|
||||
$this->dbw = wfGetDB( DB_MASTER );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
if( !$this->hasOption('user') || !$this->hasOption('password') ) {
|
||||
$this->error( "Username or password not provided, halting.", true );
|
||||
}
|
||||
$user = User::newFromName( $this->getOption('user') );
|
||||
if( !$user->getId() ) {
|
||||
$this->error( "No such user: " . $this->getOption('user') . "\n", true );
|
||||
}
|
||||
try {
|
||||
$user->setPassword( $this->getOption('password') );
|
||||
$user->saveSettings();
|
||||
} catch( PasswordError $pwe ) {
|
||||
$this->error( $pwe->getText(), true );
|
||||
}
|
||||
|
||||
function main() {
|
||||
$this->user->setPassword( $this->password );
|
||||
$this->user->saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "ChangePassword";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
|
|
|||
|
|
@ -1,40 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* Check the autoloader
|
||||
*/
|
||||
if ( php_sapi_name() != 'cli' ) exit;
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$IP = dirname(__FILE__) .'/..';
|
||||
require( "$IP/includes/AutoLoader.php" );
|
||||
$files = array_unique( $wgAutoloadLocalClasses );
|
||||
|
||||
class CheckAutoLoader extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "AutoLoader sanity checks";
|
||||
foreach ( $files as $file ) {
|
||||
if( function_exists( 'parsekit_compile_file' ) ){
|
||||
$parseInfo = parsekit_compile_file( "$IP/$file" );
|
||||
$classes = array_keys( $parseInfo['class_table'] );
|
||||
} else {
|
||||
$contents = file_get_contents( "$IP/$file" );
|
||||
$m = array();
|
||||
preg_match_all( '/\n\s*class\s+([a-zA-Z0-9_]+)/', $contents, $m, PREG_PATTERN_ORDER );
|
||||
$classes = $m[1];
|
||||
}
|
||||
public function execute() {
|
||||
global $wgAutoloadLocalClasses, $IP;
|
||||
$files = array_unique( $wgAutoloadLocalClasses );
|
||||
|
||||
foreach( $files as $file ) {
|
||||
if( function_exists( 'parsekit_compile_file' ) ){
|
||||
$parseInfo = parsekit_compile_file( "$IP/$file" );
|
||||
$classes = array_keys( $parseInfo['class_table'] );
|
||||
} else {
|
||||
$contents = file_get_contents( "$IP/$file" );
|
||||
$m = array();
|
||||
preg_match_all( '/\n\s*class\s+([a-zA-Z0-9_]+)/', $contents, $m, PREG_PATTERN_ORDER );
|
||||
$classes = $m[1];
|
||||
}
|
||||
foreach ( $classes as $class ) {
|
||||
if ( !isset( $wgAutoloadLocalClasses[$class] ) ) {
|
||||
//printf( "%-50s Unlisted, in %s\n", $class, $file );
|
||||
$this->output( "\t'$class' => '$file',\n" );
|
||||
} elseif ( $wgAutoloadLocalClasses[$class] !== $file ) {
|
||||
$this->output( "$class: Wrong file: found in $file, listed in " . $wgAutoloadLocalClasses[$class] . "\n" );
|
||||
}
|
||||
}
|
||||
foreach ( $classes as $class ) {
|
||||
if ( !isset( $wgAutoloadLocalClasses[$class] ) ) {
|
||||
//printf( "%-50s Unlisted, in %s\n", $class, $file );
|
||||
echo " '$class' => '$file',\n";
|
||||
} elseif ( $wgAutoloadLocalClasses[$class] !== $file ) {
|
||||
echo "$class: Wrong file: found in $file, listed in " . $wgAutoloadLocalClasses[$class] . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$maintClass = "CheckAutoLoader";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
||||
|
|
|
|||
|
|
@ -1,42 +1,30 @@
|
|||
<?php
|
||||
/**
|
||||
* CheckBadRedirects - See if pages marked as being redirects
|
||||
* really are.
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class CheckBadRedirects extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Look for bad redirects";
|
||||
}
|
||||
require "commandLine.inc";
|
||||
|
||||
public function execute() {
|
||||
$this->output( "Fetching redirects...\n" );
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$result = $dbr->select(
|
||||
array( 'page' ),
|
||||
array( 'page_namespace','page_title', 'page_latest' ),
|
||||
array( 'page_is_redirect' => 1 ) );
|
||||
|
||||
$count = $result->numRows();
|
||||
$this->output( "Found $count total redirects.\n" .
|
||||
"Looking for bad redirects:\n\n" );
|
||||
|
||||
foreach( $result as $row ) {
|
||||
$title = Title::makeTitle( $row->page_namespace, $row->page_title );
|
||||
$rev = Revision::newFromId( $row->page_latest );
|
||||
if( $rev ) {
|
||||
$target = Title::newFromRedirect( $rev->getText() );
|
||||
if( !$target ) {
|
||||
$this->output( $title->getPrefixedText() . "\n" );
|
||||
}
|
||||
}
|
||||
echo "Fetching redirects...\n";
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$result = $dbr->select(
|
||||
array( 'page' ),
|
||||
array( 'page_namespace','page_title', 'page_latest' ),
|
||||
array( 'page_is_redirect' => 1 ) );
|
||||
|
||||
$count = $result->numRows();
|
||||
echo "Found $count total redirects.\n";
|
||||
echo "Looking for bad redirects:\n";
|
||||
echo "\n";
|
||||
|
||||
foreach( $result as $row ) {
|
||||
$title = Title::makeTitle( $row->page_namespace, $row->page_title );
|
||||
$rev = Revision::newFromId( $row->page_latest );
|
||||
if( $rev ) {
|
||||
$target = Title::newFromRedirect( $rev->getText() );
|
||||
if( !$target ) {
|
||||
echo $title->getPrefixedText();
|
||||
echo "\n";
|
||||
}
|
||||
$this->output( "\ndone.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "CheckBadRedirects";
|
||||
require_once( DO_MAINTENANCE );
|
||||
echo "\n";
|
||||
echo "done.\n";
|
||||
|
|
|
|||
|
|
@ -1,63 +1,51 @@
|
|||
<?php
|
||||
/**
|
||||
* Check images to see if they exist, are readable, etc etc
|
||||
*/
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class CheckImages extends Maintenance {
|
||||
require( 'commandLine.inc' );
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Check images to see if they exist, are readable, etc";
|
||||
$batchSize = 1000;
|
||||
$start = '';
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$localRepo = RepoGroup::singleton()->getLocalRepo();
|
||||
|
||||
$numImages = 0;
|
||||
$numGood = 0;
|
||||
|
||||
do {
|
||||
$res = $dbr->select( 'image', '*', array( 'img_name > ' . $dbr->addQuotes( $start ) ),
|
||||
'checkImages.php', array( 'LIMIT' => $batchSize ) );
|
||||
foreach ( $res as $row ) {
|
||||
$numImages++;
|
||||
$start = $row->img_name;
|
||||
$file = $localRepo->newFileFromRow( $row );
|
||||
$path = $file->getPath();
|
||||
if ( !$path ) {
|
||||
echo "{$row->img_name}: not locally accessible\n";
|
||||
continue;
|
||||
}
|
||||
$stat = @stat( $file->getPath() );
|
||||
if ( !$stat ) {
|
||||
echo "{$row->img_name}: missing\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $stat['mode'] & 040000 ) {
|
||||
echo "{$row->img_name}: is a directory\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $stat['size'] == 0 && $row->img_size != 0 ) {
|
||||
echo "{$row->img_name}: truncated, was {$row->img_size}\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $stat['size'] != $row->img_size ) {
|
||||
echo "{$row->img_name}: size mismatch DB={$row->img_size}, actual={$stat['size']}\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$numGood++;
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$batchSize = 1000;
|
||||
$start = '';
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
|
||||
$numImages = 0;
|
||||
$numGood = 0;
|
||||
|
||||
do {
|
||||
$res = $dbr->select( 'image', '*', array( 'img_name > ' . $dbr->addQuotes( $start ) ),
|
||||
__METHOD__, array( 'LIMIT' => $batchSize ) );
|
||||
foreach ( $res as $row ) {
|
||||
$numImages++;
|
||||
$start = $row->img_name;
|
||||
$file = RepoGroup::singleton()->getLocalRepo()->newFileFromRow( $row );
|
||||
$path = $file->getPath();
|
||||
if ( !$path ) {
|
||||
$this->output( "{$row->img_name}: not locally accessible\n";
|
||||
continue;
|
||||
}
|
||||
$stat = @stat( $file->getPath() );
|
||||
if ( !$stat ) {
|
||||
$this->output( "{$row->img_name}: missing\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $stat['mode'] & 040000 ) {
|
||||
$this->output( "{$row->img_name}: is a directory\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $stat['size'] == 0 && $row->img_size != 0 ) {
|
||||
$this->output( "{$row->img_name}: truncated, was {$row->img_size}\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $stat['size'] != $row->img_size ) {
|
||||
$this->output( "{$row->img_name}: size mismatch DB={$row->img_size}, actual={$stat['size']}\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
$numGood++;
|
||||
}
|
||||
|
||||
} while ( $res->numRows() );
|
||||
|
||||
$this->output( "Good images: $numGood/$numImages\n" );
|
||||
}
|
||||
}
|
||||
} while ( $res->numRows() );
|
||||
|
||||
echo "Good images: $numGood/$numImages\n";
|
||||
|
|
|
|||
|
|
@ -7,33 +7,36 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
error_reporting(E_ALL ^ E_NOTICE);
|
||||
require_once 'commandLine.inc';
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
class checkUsernames {
|
||||
var $stderr, $log;
|
||||
|
||||
class CheckUsernames extends Maintenance {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Verify that database usernames are actually valid";
|
||||
function checkUsernames() {
|
||||
$this->stderr = fopen( 'php://stderr', 'wt' );
|
||||
}
|
||||
function main() {
|
||||
$fname = 'checkUsernames::main';
|
||||
|
||||
function execute() {
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
|
||||
$res = $dbr->select( 'user',
|
||||
array( 'user_id', 'user_name' ),
|
||||
null,
|
||||
__METHOD__
|
||||
$fname
|
||||
);
|
||||
|
||||
while ( $row = $dbr->fetchObject( $res ) ) {
|
||||
if ( ! User::isValidUserName( $row->user_name ) ) {
|
||||
$this->error( sprintf( "%s: %6d: '%s'\n", wfWikiID(), $row->user_id, $row->user_name ) );
|
||||
$out = sprintf( "%s: %6d: '%s'\n", wfWikiID(), $row->user_id, $row->user_name );
|
||||
fwrite( $this->stderr, $out );
|
||||
wfDebugLog( 'checkUsernames', $out );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "CheckUsernames";
|
||||
require_once( "doMaintenance.php" );
|
||||
$cun = new checkUsernames();
|
||||
$cun->main();
|
||||
|
||||
|
|
|
|||
|
|
@ -3,36 +3,25 @@
|
|||
* This script is used to clear the interwiki links for ALL languages in
|
||||
* memcached.
|
||||
*
|
||||
* @file
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
/** */
|
||||
require_once('commandLine.inc');
|
||||
|
||||
class ClearInterwikiCache extends Maintenance {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Clear all interwiki links for all languages from the cache";
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgLocalDatabases;
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$res = $dbr->select( 'interwiki', array( 'iw_prefix' ), false );
|
||||
$prefixes = array();
|
||||
while ( $row = $dbr->fetchObject( $res ) ) {
|
||||
$prefixes[] = $row->iw_prefix;
|
||||
}
|
||||
|
||||
foreach ( $wgLocalDatabases as $db ) {
|
||||
$this->output( "$db..." );
|
||||
foreach ( $prefixes as $prefix ) {
|
||||
$wgMemc->delete("$db:interwiki:$prefix");
|
||||
}
|
||||
$this->output( "done\n" );
|
||||
}
|
||||
}
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$res = $dbr->select( 'interwiki', array( 'iw_prefix' ), false );
|
||||
$prefixes = array();
|
||||
while ( $row = $dbr->fetchObject( $res ) ) {
|
||||
$prefixes[] = $row->iw_prefix;
|
||||
}
|
||||
|
||||
$maintClass = "ClearInterwikiCache";
|
||||
require_once( DO_MAINTENANCE );
|
||||
foreach ( $wgLocalDatabases as $db ) {
|
||||
print "$db ";
|
||||
foreach ( $prefixes as $prefix ) {
|
||||
$wgMemc->delete("$db:interwiki:$prefix");
|
||||
}
|
||||
}
|
||||
print "\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -6,34 +6,33 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( 'Maintenance.php' );
|
||||
require_once('commandLine.inc');
|
||||
|
||||
class clear_stats extends Maintenance {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Remove all statistics tracking from memcached";
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgLocalDatabases, $wgMemc;
|
||||
foreach ( $wgLocalDatabases as $db ) {
|
||||
$wgMemc->delete("$db:stats:request_with_session");
|
||||
$wgMemc->delete("$db:stats:request_without_session");
|
||||
$wgMemc->delete("$db:stats:pcache_hit");
|
||||
$wgMemc->delete("$db:stats:pcache_miss_invalid");
|
||||
$wgMemc->delete("$db:stats:pcache_miss_expired");
|
||||
$wgMemc->delete("$db:stats:pcache_miss_absent");
|
||||
$wgMemc->delete("$db:stats:pcache_miss_stub");
|
||||
$wgMemc->delete("$db:stats:image_cache_hit");
|
||||
$wgMemc->delete("$db:stats:image_cache_miss");
|
||||
$wgMemc->delete("$db:stats:image_cache_update");
|
||||
$wgMemc->delete("$db:stats:diff_cache_hit");
|
||||
$wgMemc->delete("$db:stats:diff_cache_miss");
|
||||
$wgMemc->delete("$db:stats:diff_uncacheable");
|
||||
}
|
||||
}
|
||||
foreach ( $wgLocalDatabases as $db ) {
|
||||
noisyDelete("$db:stats:request_with_session");
|
||||
noisyDelete("$db:stats:request_without_session");
|
||||
noisyDelete("$db:stats:pcache_hit");
|
||||
noisyDelete("$db:stats:pcache_miss_invalid");
|
||||
noisyDelete("$db:stats:pcache_miss_expired");
|
||||
noisyDelete("$db:stats:pcache_miss_absent");
|
||||
noisyDelete("$db:stats:pcache_miss_stub");
|
||||
noisyDelete("$db:stats:image_cache_hit");
|
||||
noisyDelete("$db:stats:image_cache_miss");
|
||||
noisyDelete("$db:stats:image_cache_update");
|
||||
noisyDelete("$db:stats:diff_cache_hit");
|
||||
noisyDelete("$db:stats:diff_cache_miss");
|
||||
noisyDelete("$db:stats:diff_uncacheable");
|
||||
}
|
||||
|
||||
function noisyDelete( $key ) {
|
||||
global $wgMemc;
|
||||
/*
|
||||
print "$key ";
|
||||
if ( $wgMemc->delete($key) ) {
|
||||
print "deleted\n";
|
||||
} else {
|
||||
print "FAILED\n";
|
||||
}*/
|
||||
$wgMemc->delete($key);
|
||||
}
|
||||
|
||||
$maintClass = "clear_stats";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
|
|
|||
|
|
@ -8,53 +8,61 @@
|
|||
* @author Rob Church <robchur@gmail.com>
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$options = array( 'help', 'bureaucrat' );
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
class CreateAndPromote extends Maintenance {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Create a new user account with administrator rights";
|
||||
$this->addParam( "bureaucrat", "Grant the account bureaucrat rights" );
|
||||
$this->addArgs( array( "username", "password" ) );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$username = $this->getArg(0);
|
||||
$password = $this->getArg(1);
|
||||
|
||||
$this->output( wfWikiID() . ": Creating and promoting User:{$username}..." );
|
||||
|
||||
$user = User::newFromName( $username );
|
||||
if( !is_object( $user ) ) {
|
||||
$this->error( "invalid username.\n", true );
|
||||
} elseif( 0 != $user->idForName() ) {
|
||||
$this->error( "account exists.\n", true );
|
||||
}
|
||||
|
||||
# Try to set the password
|
||||
try {
|
||||
$user->setPassword( $password );
|
||||
} catch( PasswordError $pwe ) {
|
||||
$this->error( $pwe->getText(), true );
|
||||
}
|
||||
|
||||
# Insert the account into the database
|
||||
$user->addToDatabase();
|
||||
$user->saveSettings();
|
||||
|
||||
# Promote user
|
||||
$user->addGroup( 'sysop' );
|
||||
if( $this->hasOption( 'bureaucrat' ) )
|
||||
$user->addGroup( 'bureaucrat' );
|
||||
|
||||
# Increment site_stats.ss_users
|
||||
$ssu = new SiteStatsUpdate( 0, 0, 0, 0, 1 );
|
||||
$ssu->doUpdate();
|
||||
|
||||
$this->output( "done.\n" );
|
||||
}
|
||||
if( isset( $options['help'] ) ) {
|
||||
showHelp();
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
$maintClass = "CreateAndPromote";
|
||||
require_once( DO_MAINTENANCE );
|
||||
if( count( $args ) < 2 ) {
|
||||
echo( "Please provide a username and password for the new account.\n" );
|
||||
die( 1 );
|
||||
}
|
||||
|
||||
$username = $args[0];
|
||||
$password = $args[1];
|
||||
|
||||
echo( wfWikiID() . ": Creating and promoting User:{$username}..." );
|
||||
|
||||
# Validate username and check it doesn't exist
|
||||
$user = User::newFromName( $username );
|
||||
if( !is_object( $user ) ) {
|
||||
echo( "invalid username.\n" );
|
||||
die( 1 );
|
||||
} elseif( 0 != $user->idForName() ) {
|
||||
echo( "account exists.\n" );
|
||||
die( 1 );
|
||||
}
|
||||
|
||||
# Insert the account into the database
|
||||
$user->addToDatabase();
|
||||
$user->setPassword( $password );
|
||||
$user->saveSettings();
|
||||
|
||||
# Promote user
|
||||
$user->addGroup( 'sysop' );
|
||||
if( isset( $option['bureaucrat'] ) )
|
||||
$user->addGroup( 'bureaucrat' );
|
||||
|
||||
# Increment site_stats.ss_users
|
||||
$ssu = new SiteStatsUpdate( 0, 0, 0, 0, 1 );
|
||||
$ssu->doUpdate();
|
||||
|
||||
echo( "done.\n" );
|
||||
|
||||
function showHelp() {
|
||||
echo( <<<EOT
|
||||
Create a new user account with administrator rights
|
||||
|
||||
USAGE: php createAndPromote.php [--bureaucrat|--help] <username> <password>
|
||||
|
||||
--bureaucrat
|
||||
Grant the account bureaucrat rights
|
||||
--help
|
||||
Show this help information
|
||||
|
||||
EOT
|
||||
);
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Deletes a batch of pages
|
||||
* Usage: php deleteBatch.php [-u <user>] [-r <reason>] [-i <interval>] [listfile]
|
||||
|
|
@ -12,87 +13,86 @@
|
|||
* @file
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class DeleteBatch extends Maintenance {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Deletes a batch of pages";
|
||||
$this->addParam( 'u', "User to perform deletion", false, true );
|
||||
$this->addParam( 'r', "Reason to delete page", false, true );
|
||||
$this->addParam( 'i', "Interval to sleep between deletions" );
|
||||
$this->addArgs( array( 'listfile' ) );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUser;
|
||||
$oldCwd = getcwd();
|
||||
$optionsWithArgs = array( 'u', 'r', 'i' );
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
# Change to current working directory
|
||||
$oldCwd = getcwd();
|
||||
chdir( $oldCwd );
|
||||
|
||||
# Options processing
|
||||
$user = $this->getOption( 'u', 'Delete page script' );
|
||||
$reason = $this->getOption( 'r', '' );
|
||||
$interval = $this->getOption( 'i', 0 );
|
||||
if( $this->hasArg() ) {
|
||||
$file = fopen( $this->getArg(), 'r' );
|
||||
} else {
|
||||
$file = $this->getStdin();
|
||||
}
|
||||
chdir( $oldCwd );
|
||||
|
||||
# Setup
|
||||
if( !$file ) {
|
||||
$this->error( "Unable to read file, exiting\n", true );
|
||||
}
|
||||
$wgUser = User::newFromName( $user );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
# Options processing
|
||||
|
||||
# Handle each entry
|
||||
for ( $linenum = 1; !feof( $file ); $linenum++ ) {
|
||||
$line = trim( fgets( $file ) );
|
||||
if ( $line == '' ) {
|
||||
continue;
|
||||
}
|
||||
$page = Title::newFromText( $line );
|
||||
if ( is_null( $page ) ) {
|
||||
$this->output( "Invalid title '$line' on line $linenum\n" );
|
||||
continue;
|
||||
}
|
||||
if( !$page->exists() ) {
|
||||
$this->output( "Skipping nonexistent page '$line'\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$this->output( $page->getPrefixedText() );
|
||||
$dbw->begin();
|
||||
if( $page->getNamespace() == NS_FILE ) {
|
||||
$art = new ImagePage( $page );
|
||||
$img = wfFindFile( $art->mTitle );
|
||||
if( !$img || !$img->delete( $reason ) ) {
|
||||
$this->output( "FAILED to delete image file... " );
|
||||
}
|
||||
} else {
|
||||
$art = new Article( $page );
|
||||
}
|
||||
$success = $art->doDeleteArticle( $reason );
|
||||
$dbw->immediateCommit();
|
||||
if ( $success ) {
|
||||
$this->output( "\n" );
|
||||
} else {
|
||||
$this->output( " FAILED to delete article\n" );
|
||||
}
|
||||
|
||||
if ( $interval ) {
|
||||
sleep( $interval );
|
||||
}
|
||||
wfWaitForSlaves( 5 );
|
||||
$filename = 'php://stdin';
|
||||
$user = 'Delete page script';
|
||||
$reason = '';
|
||||
$interval = 0;
|
||||
|
||||
if ( isset( $args[0] ) ) {
|
||||
$filename = $args[0];
|
||||
}
|
||||
}
|
||||
if ( isset( $options['u'] ) ) {
|
||||
$user = $options['u'];
|
||||
}
|
||||
if ( isset( $options['r'] ) ) {
|
||||
$reason = $options['r'];
|
||||
}
|
||||
if ( isset( $options['i'] ) ) {
|
||||
$interval = $options['i'];
|
||||
}
|
||||
|
||||
$maintClass = "DeleteBatch";
|
||||
require_once( DO_MAINTENANCE );
|
||||
$wgUser = User::newFromName( $user );
|
||||
|
||||
|
||||
# Setup complete, now start
|
||||
|
||||
$file = fopen( $filename, 'r' );
|
||||
if ( !$file ) {
|
||||
print "Unable to read file, exiting\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
for ( $linenum = 1; !feof( $file ); $linenum++ ) {
|
||||
$line = trim( fgets( $file ) );
|
||||
if ( $line == '' ) {
|
||||
continue;
|
||||
}
|
||||
$page = Title::newFromText( $line );
|
||||
if ( is_null( $page ) ) {
|
||||
print "Invalid title '$line' on line $linenum\n";
|
||||
continue;
|
||||
}
|
||||
if( !$page->exists() ) {
|
||||
print "Skipping nonexistent page '$line'\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
print $page->getPrefixedText();
|
||||
$dbw->begin();
|
||||
if( $page->getNamespace() == NS_FILE ) {
|
||||
$art = new ImagePage( $page );
|
||||
$img = wfFindFile( $art->mTitle );
|
||||
if( !$img || !$img->delete( $reason ) ) {
|
||||
print "FAILED to delete image file... ";
|
||||
}
|
||||
} else {
|
||||
$art = new Article( $page );
|
||||
}
|
||||
$success = $art->doDeleteArticle( $reason );
|
||||
$dbw->immediateCommit();
|
||||
if ( $success ) {
|
||||
print "\n";
|
||||
} else {
|
||||
print " FAILED to delete image page\n";
|
||||
}
|
||||
|
||||
if ( $interval ) {
|
||||
sleep( $interval );
|
||||
}
|
||||
wfWaitForSlaves( 5 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,53 +1,48 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Deletes all pages in the MediaWiki namespace which were last edited by
|
||||
* "MediaWiki default".
|
||||
*
|
||||
* @file
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
if ( !defined( 'MEDIAWIKI' ) ) {
|
||||
require_once( 'commandLine.inc' );
|
||||
deleteDefaultMessages();
|
||||
}
|
||||
|
||||
class DeleteDefaultMessages extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Deletes all pages in the MediaWiki namespace" .
|
||||
" which were last edited by \"MediaWiki default\"";
|
||||
}
|
||||
function deleteDefaultMessages() {
|
||||
$user = 'MediaWiki default';
|
||||
$reason = 'No longer required';
|
||||
|
||||
public function execute() {
|
||||
$user = 'MediaWiki default';
|
||||
$reason = 'No longer required';
|
||||
|
||||
global $wgUser;
|
||||
$wgUser = User::newFromName( $user );
|
||||
$wgUser->addGroup( 'bot' );
|
||||
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$res = $dbr->select( array( 'page', 'revision' ),
|
||||
array( 'page_namespace', 'page_title' ),
|
||||
array(
|
||||
'page_namespace' => NS_MEDIAWIKI,
|
||||
'page_latest=rev_id',
|
||||
'rev_user_text' => 'MediaWiki default',
|
||||
)
|
||||
);
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
global $wgUser;
|
||||
$wgUser = User::newFromName( $user );
|
||||
$wgUser->addGroup( 'bot' );
|
||||
|
||||
while ( $row = $dbr->fetchObject( $res ) ) {
|
||||
if ( function_exists( 'wfWaitForSlaves' ) ) {
|
||||
wfWaitForSlaves( 5 );
|
||||
}
|
||||
$dbw->ping();
|
||||
$title = Title::makeTitle( $row->page_namespace, $row->page_title );
|
||||
$article = new Article( $title );
|
||||
$dbw->begin();
|
||||
$article->doDeleteArticle( $reason );
|
||||
$dbw->commit();
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$res = $dbr->select( array( 'page', 'revision' ),
|
||||
array( 'page_namespace', 'page_title' ),
|
||||
array(
|
||||
'page_namespace' => NS_MEDIAWIKI,
|
||||
'page_latest=rev_id',
|
||||
'rev_user_text' => 'MediaWiki default',
|
||||
)
|
||||
);
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
while ( $row = $dbr->fetchObject( $res ) ) {
|
||||
if ( function_exists( 'wfWaitForSlaves' ) ) {
|
||||
wfWaitForSlaves( 5 );
|
||||
}
|
||||
$dbw->ping();
|
||||
$title = Title::makeTitle( $row->page_namespace, $row->page_title );
|
||||
$article = new Article( $title );
|
||||
$dbw->begin();
|
||||
$article->doDeleteArticle( $reason );
|
||||
$dbw->commit();
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "DeleteDefaultMessages";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
|
|
|||
|
|
@ -3,27 +3,31 @@
|
|||
* This script delete image information from memcached.
|
||||
*
|
||||
* Usage example:
|
||||
* php deleteImageMemcached.php --until "2005-09-05 00:00:00" --sleep 0
|
||||
* php deleteImageMemcached.php --until "2005-09-05 00:00:00" --sleep 0 --report 10
|
||||
*
|
||||
* @file
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$optionsWithArgs = array( 'until', 'sleep', 'report' );
|
||||
|
||||
class DeleteImageCache extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Delete image information from memcached";
|
||||
$this->addParam( 'sleep', 'How many seconds to sleep between deletions', true, true );
|
||||
$this->addParam( 'until', 'Timestamp to delete all entries prior to', true, true );
|
||||
require_once 'commandLine.inc';
|
||||
|
||||
/**
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
class DeleteImageCache {
|
||||
var $until, $sleep, $report;
|
||||
|
||||
function DeleteImageCache( $until, $sleep, $report ) {
|
||||
$this->until = $until;
|
||||
$this->sleep = $sleep;
|
||||
$this->report = $report;
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
function main() {
|
||||
global $wgMemc;
|
||||
|
||||
$until = preg_replace( "/[^\d]/", '', $this->getOption('until') );
|
||||
$sleep = (int)$this->getOption('sleep') * 1000; // milliseconds
|
||||
$fname = 'DeleteImageCache::main';
|
||||
|
||||
ini_set( 'display_errors', false );
|
||||
|
||||
|
|
@ -31,8 +35,8 @@ class DeleteImageCache extends Maintenance {
|
|||
|
||||
$res = $dbr->select( 'image',
|
||||
array( 'img_name' ),
|
||||
array( "img_timestamp < {$until}" ),
|
||||
__METHOD__
|
||||
array( "img_timestamp < {$this->until}" ),
|
||||
$fname
|
||||
);
|
||||
|
||||
$i = 0;
|
||||
|
|
@ -40,22 +44,29 @@ class DeleteImageCache extends Maintenance {
|
|||
|
||||
while ( $row = $dbr->fetchObject( $res ) ) {
|
||||
if ($i % $this->report == 0)
|
||||
$this->output( sprintf("%s: %13s done (%s)\n", wfWikiID(), "$i/$total", wfPercent( $i / $total * 100 ) ) );
|
||||
printf("%s: %13s done (%s)\n", wfWikiID(), "$i/$total", wfPercent( $i / $total * 100 ));
|
||||
$md5 = md5( $row->img_name );
|
||||
$wgMemc->delete( wfMemcKey( 'Image', $md5 ) );
|
||||
|
||||
if ($sleep != 0)
|
||||
usleep( $sleep );
|
||||
if ($this->sleep != 0)
|
||||
usleep( $this->sleep );
|
||||
|
||||
++$i;
|
||||
}
|
||||
}
|
||||
|
||||
private function getImageCount() {
|
||||
function getImageCount() {
|
||||
$fname = 'DeleteImageCache::getImageCount';
|
||||
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
return $dbr->selectField( 'image', 'COUNT(*)', array(), __METHOD__ );
|
||||
return $dbr->selectField( 'image', 'COUNT(*)', array(), $fname );
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "DeleteImageCache";
|
||||
require_once( DO_MAINTENANCE );
|
||||
$until = preg_replace( "/[^\d]/", '', $options['until'] );
|
||||
$sleep = (int)$options['sleep'] * 1000; // milliseconds
|
||||
$report = (int)$options['report'];
|
||||
|
||||
$dic = new DeleteImageCache( $until, $sleep, $report );
|
||||
$dic->main();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,52 +6,42 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
class DeleteRevision extends Maintenance {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Delete one or more revisions by moving them to the archive table";
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
if( count( $this->mArgs ) == 0 ) {
|
||||
$this->error( "No revisions specified", true );
|
||||
}
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
$this->output( "Deleting revision(s) " . implode( ',', $this->mArgs ) .
|
||||
" from " . wfWikiID() . "...\n" );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
$affected = 0;
|
||||
foreach ( $this->mArgs as $revID ) {
|
||||
$dbw->insertSelect( 'archive', array( 'page', 'revision' ),
|
||||
array(
|
||||
'ar_namespace' => 'page_namespace',
|
||||
'ar_title' => 'page_title',
|
||||
'ar_comment' => 'rev_comment',
|
||||
'ar_user' => 'rev_user',
|
||||
'ar_user_text' => 'rev_user_text',
|
||||
'ar_timestamp' => 'rev_timestamp',
|
||||
'ar_minor_edit' => 'rev_minor_edit',
|
||||
'ar_rev_id' => 'rev_id',
|
||||
'ar_text_id' => 'rev_text_id',
|
||||
), array(
|
||||
'rev_id' => $revID,
|
||||
'page_id = rev_page'
|
||||
), __METHOD__
|
||||
);
|
||||
if ( !$dbw->affectedRows() ) {
|
||||
$this->output( "Revision $revID not found\n" );
|
||||
} else {
|
||||
$affected += $dbw->affectedRows();
|
||||
$dbw->delete( 'revision', array( 'rev_id' => $revID ) );
|
||||
}
|
||||
}
|
||||
$this->output( "Deleted $affected revisions\n" );
|
||||
if ( count( $args ) == 0 ) {
|
||||
echo "Usage: php deleteRevision.php <revid> [<revid> ...]\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "Deleting revision(s) " . implode( ',', $args ) . " from ".wfWikiID()."...\n";
|
||||
|
||||
$affected = 0;
|
||||
foreach ( $args as $revID ) {
|
||||
$dbw->insertSelect( 'archive', array( 'page', 'revision' ),
|
||||
array(
|
||||
'ar_namespace' => 'page_namespace',
|
||||
'ar_title' => 'page_title',
|
||||
'ar_comment' => 'rev_comment',
|
||||
'ar_user' => 'rev_user',
|
||||
'ar_user_text' => 'rev_user_text',
|
||||
'ar_timestamp' => 'rev_timestamp',
|
||||
'ar_minor_edit' => 'rev_minor_edit',
|
||||
'ar_rev_id' => 'rev_id',
|
||||
'ar_text_id' => 'rev_text_id',
|
||||
), array(
|
||||
'rev_id' => $revID,
|
||||
'page_id = rev_page'
|
||||
), $fname
|
||||
);
|
||||
if ( !$dbw->affectedRows() ) {
|
||||
echo "Revision $revID not found\n";
|
||||
} else {
|
||||
$affected += $dbw->affectedRows();
|
||||
$dbw->delete( 'revision', array( 'rev_id' => $revID ) );
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "DeleteRevision";
|
||||
require_once( DO_MAINTENANCE );
|
||||
print "Deleted $affected revisions\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* We want to make this whole thing as seamless as possible to the
|
||||
* end-user. Unfortunately, we can't do _all_ of the work in the class
|
||||
* because A) included files are not in global scope, but in the scope
|
||||
* of their caller, and B) MediaWiki has way too many globals. So instead
|
||||
* we'll kinda fake it, and do the requires() inline. <3 PHP
|
||||
*/
|
||||
|
||||
if( !isset( $maintClass ) || !class_exists( $maintClass ) ) {
|
||||
echo "\$maintClass is not set or is set to a non-existent class.";
|
||||
die();
|
||||
}
|
||||
|
||||
if( defined( 'MW_NO_SETUP' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get an object to start us off
|
||||
$maintenance = new $maintClass();
|
||||
|
||||
// Basic sanity checks and such
|
||||
$maintenance->setup();
|
||||
|
||||
# Setup the profiler
|
||||
if ( file_exists( "$IP/StartProfiler.php" ) ) {
|
||||
require_once( "$IP/StartProfiler.php" );
|
||||
} else {
|
||||
require_once( "$IP/includes/ProfilerStub.php" );
|
||||
}
|
||||
|
||||
// Load settings, using wikimedia-mode if needed
|
||||
if( file_exists( dirname(__FILE__).'/wikimedia-mode' ) ) {
|
||||
# TODO FIXME! Wikimedia-specific stuff needs to go away to an ext
|
||||
# Maybe a hook?
|
||||
global $cluster;
|
||||
$wgWikiFarm = true;
|
||||
$cluster = 'pmtma';
|
||||
require_once( "$IP/includes/AutoLoader.php" );
|
||||
require_once( "$IP/includes/SiteConfiguration.php" );
|
||||
require( "$IP/wgConf.php" );
|
||||
$maintenance->loadWikimediaSettings();
|
||||
require( $IP.'/includes/Defines.php' );
|
||||
require( $IP.'/CommonSettings.php' );
|
||||
} else {
|
||||
require_once( "$IP/includes/AutoLoader.php" );
|
||||
require_once( "$IP/includes/Defines.php" );
|
||||
require_once( $maintenance->loadSettings() );
|
||||
}
|
||||
// Some last includes
|
||||
require_once( "$IP/includes/Setup.php" );
|
||||
require_once( "$IP/install-utils.inc" );
|
||||
|
||||
$wgTitle = null; # Much much faster startup than creating a title object
|
||||
|
||||
try {
|
||||
$maintenance->execute();
|
||||
} catch( MWException $mwe ) {
|
||||
echo( $mwe->getText() );
|
||||
}
|
||||
|
|
@ -16,66 +16,57 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$wgUseNormalUser = (bool)getenv('MW_WIKIUSER');
|
||||
|
||||
class EvalPrompt extends Maintenance {
|
||||
$optionsWithArgs = array( 'd' );
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "This script lets a command-line user start up the wiki engine and then poke\n" .
|
||||
"about by issuing PHP commands directly.";
|
||||
$this->addParam( 'd', "Enable MediaWiki debug output", false, true );
|
||||
/** */
|
||||
require_once( "commandLine.inc" );
|
||||
|
||||
if ( isset( $options['d'] ) ) {
|
||||
$d = $options['d'];
|
||||
if ( $d > 0 ) {
|
||||
$wgDebugLogFile = '/dev/stdout';
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUseNormalUser;
|
||||
$wgUseNormalUser = (bool)getenv('MW_WIKIUSER');
|
||||
if ( $this->hasOption('d') ) {
|
||||
$d = $this->getOption('d');
|
||||
if ( $d > 0 ) {
|
||||
$wgDebugLogFile = '/dev/stdout';
|
||||
}
|
||||
if ( $d > 1 ) {
|
||||
$lb = wfGetLB();
|
||||
foreach ( $lb->mServers as $i => $server ) {
|
||||
$lb->mServers[$i]['flags'] |= DBO_DEBUG;
|
||||
}
|
||||
}
|
||||
if ( $d > 2 ) {
|
||||
$wgDebugFunctionEntry = true;
|
||||
}
|
||||
if ( $d > 1 ) {
|
||||
$lb = wfGetLB();
|
||||
foreach ( $lb->mServers as $i => $server ) {
|
||||
$lb->mServers[$i]['flags'] |= DBO_DEBUG;
|
||||
}
|
||||
|
||||
if ( function_exists( 'readline_add_history' )
|
||||
&& function_exists( 'posix_isatty' ) && posix_isatty( 0 /*STDIN*/ ) )
|
||||
{
|
||||
$useReadline = true;
|
||||
} else {
|
||||
$useReadline = false;
|
||||
}
|
||||
|
||||
if ( $useReadline ) {
|
||||
$historyFile = "{$_ENV['HOME']}/.mweval_history";
|
||||
readline_read_history( $historyFile );
|
||||
}
|
||||
|
||||
while ( ( $line = readconsole( '> ' ) ) !== false ) {
|
||||
if ( $useReadline ) {
|
||||
readline_add_history( $line );
|
||||
readline_write_history( $historyFile );
|
||||
}
|
||||
$val = eval( $line . ";" );
|
||||
if( is_null( $val ) ) {
|
||||
echo "\n";
|
||||
} elseif( is_string( $val ) || is_numeric( $val ) ) {
|
||||
echo "$val\n";
|
||||
} else {
|
||||
var_dump( $val );
|
||||
}
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
if ( $d > 2 ) {
|
||||
$wgDebugFunctionEntry = true;
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "EvalPrompt";
|
||||
require_once( DO_MAINTENANCE );
|
||||
if ( function_exists( 'readline_add_history' )
|
||||
&& function_exists( 'posix_isatty' ) && posix_isatty( 0 /*STDIN*/ ) )
|
||||
{
|
||||
$useReadline = true;
|
||||
} else {
|
||||
$useReadline = false;
|
||||
}
|
||||
|
||||
if ( $useReadline ) {
|
||||
$historyFile = "{$_ENV['HOME']}/.mweval_history";
|
||||
readline_read_history( $historyFile );
|
||||
}
|
||||
|
||||
while ( ( $line = readconsole( '> ' ) ) !== false ) {
|
||||
if ( $useReadline ) {
|
||||
readline_add_history( $line );
|
||||
readline_write_history( $historyFile );
|
||||
}
|
||||
$val = eval( $line . ";" );
|
||||
if( is_null( $val ) ) {
|
||||
echo "\n";
|
||||
} elseif( is_string( $val ) || is_numeric( $val ) ) {
|
||||
echo "$val\n";
|
||||
} else {
|
||||
var_dump( $val );
|
||||
}
|
||||
}
|
||||
|
||||
print "\n";
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,48 +6,34 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
require "commandLine.inc";
|
||||
|
||||
class FetchText extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Fetch the revision text from an old_id";
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$db = wfGetDB( DB_SLAVE );
|
||||
$stdin = $this->getStdin();
|
||||
while( !feof( $stdin ) ) {
|
||||
$line = fgets( $stdin );
|
||||
if( $line === false ) {
|
||||
// We appear to have lost contact...
|
||||
break;
|
||||
}
|
||||
$textId = intval( $line );
|
||||
$text = $this->doGetText( $db, $textId );
|
||||
$this->output( strlen( $text ) . "\n". $text );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* May throw a database error if, say, the server dies during query.
|
||||
* @param $db Database object
|
||||
* @param $id int The old_id
|
||||
* @return String
|
||||
*/
|
||||
private function doGetText( $db, $id ) {
|
||||
$id = intval( $id );
|
||||
$row = $db->selectRow( 'text',
|
||||
array( 'old_text', 'old_flags' ),
|
||||
array( 'old_id' => $id ),
|
||||
'TextPassDumper::getText' );
|
||||
$text = Revision::getRevisionText( $row );
|
||||
if( $text === false ) {
|
||||
return false;
|
||||
}
|
||||
return $text;
|
||||
$db = wfGetDB( DB_SLAVE );
|
||||
$stdin = fopen( "php://stdin", "rt" );
|
||||
while( !feof( $stdin ) ) {
|
||||
$line = fgets( $stdin );
|
||||
if( $line === false ) {
|
||||
// We appear to have lost contact...
|
||||
break;
|
||||
}
|
||||
$textId = intval( $line );
|
||||
$text = doGetText( $db, $textId );
|
||||
echo strlen( $text ) . "\n";
|
||||
echo $text;
|
||||
}
|
||||
|
||||
$maintClass = "FetchText";
|
||||
require_once( DO_MAINTENANCE );
|
||||
/**
|
||||
* May throw a database error if, say, the server dies during query.
|
||||
*/
|
||||
function doGetText( $db, $id ) {
|
||||
$id = intval( $id );
|
||||
$row = $db->selectRow( 'text',
|
||||
array( 'old_text', 'old_flags' ),
|
||||
array( 'old_id' => $id ),
|
||||
'TextPassDumper::getText' );
|
||||
$text = Revision::getRevisionText( $row );
|
||||
if( $text === false ) {
|
||||
return false;
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,37 +4,26 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
require 'commandLine.inc';
|
||||
|
||||
class GetLagTimes extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Dump replication lag times";
|
||||
}
|
||||
$lb = wfGetLB();
|
||||
|
||||
public function execute() {
|
||||
$lb = wfGetLB();
|
||||
|
||||
if( $lb->getServerCount() == 1 ) {
|
||||
$this->error( "This script dumps replication lag times, but you don't seem to have\n"
|
||||
. "a multi-host db server configuration.\n" );
|
||||
if( $lb->getServerCount() == 1 ) {
|
||||
echo "This script dumps replication lag times, but you don't seem to have\n";
|
||||
echo "a multi-host db server configuration.\n";
|
||||
} else {
|
||||
$lags = $lb->getLagTimes();
|
||||
foreach( $lags as $n => $lag ) {
|
||||
$host = $lb->getServerName( $n );
|
||||
if( IP::isValid( $host ) ) {
|
||||
$ip = $host;
|
||||
$host = gethostbyaddr( $host );
|
||||
} else {
|
||||
$lags = $lb->getLagTimes();
|
||||
foreach( $lags as $n => $lag ) {
|
||||
$host = $lb->getServerName( $n );
|
||||
if( IP::isValid( $host ) ) {
|
||||
$ip = $host;
|
||||
$host = gethostbyaddr( $host );
|
||||
} else {
|
||||
$ip = gethostbyname( $host );
|
||||
}
|
||||
$starLen = min( intval( $lag ), 40 );
|
||||
$stars = str_repeat( '*', $starLen );
|
||||
$this->output( sprintf( "%10s %20s %3d %s\n", $ip, $host, $lag, $stars ) );
|
||||
}
|
||||
$ip = gethostbyname( $host );
|
||||
}
|
||||
$starLen = min( intval( $lag ), 40 );
|
||||
$stars = str_repeat( '*', $starLen );
|
||||
printf( "%10s %20s %3d %s\n", $ip, $host, $lag, $stars );
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "GetLagTimes";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
|
|
|||
|
|
@ -5,32 +5,24 @@
|
|||
* @file
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class GetSlaveServer extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->addParam( "group", "Query group to check specifically" );
|
||||
$this->mDescription = "Report the hostname of a slave server";
|
||||
}
|
||||
public function execute() {
|
||||
global $wgAllDBsAreLocalhost;
|
||||
if( $wgAllDBsAreLocalhost ) {
|
||||
$host = 'localhost';
|
||||
} else {
|
||||
if( $this->hasOption('group') ) {
|
||||
$db = wfGetDB( DB_SLAVE, $this->getOption('group') );
|
||||
$host = $db->getServer();
|
||||
} else {
|
||||
$lb = wfGetLB();
|
||||
$i = $lb->getReaderIndex();
|
||||
$host = $lb->getServerName( $i );
|
||||
}
|
||||
}
|
||||
$this->output( "$host\n" );
|
||||
}
|
||||
require_once( dirname(__FILE__).'/commandLine.inc' );
|
||||
|
||||
if ( $wgAllDBsAreLocalhost ) {
|
||||
# Can't fool the backup script
|
||||
print "localhost\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
$maintClass = "GetSlaveServer";
|
||||
require_once( DO_MAINTENANCE );
|
||||
if( isset( $options['group'] ) ) {
|
||||
$db = wfGetDB( DB_SLAVE, $options['group'] );
|
||||
$host = $db->getServer();
|
||||
} else {
|
||||
$lb = wfGetLB();
|
||||
$i = $lb->getReaderIndex();
|
||||
$host = $lb->getServerName( $i );
|
||||
}
|
||||
|
||||
print "$host\n";
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,22 +9,23 @@
|
|||
* @author Rob Church <robchur@gmail.com>
|
||||
* @licence GNU General Public Licence 2.0 or later
|
||||
*/
|
||||
|
||||
$options = array( 'help', 'update', 'noviews' );
|
||||
require_once( 'commandLine.inc' );
|
||||
echo( "Refresh Site Statistics\n\n" );
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class InitStats extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Re-initialise the site statistics tables";
|
||||
$this->addParam( 'update', 'Update the existing statistics (preserves the ss_total_views field)' );
|
||||
$this->addParam( 'noviews', "Don't update the page view counter" );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$this->output( "Refresh Site Statistics\n\n" );
|
||||
SiteStats::init( $this->hasOption('update'), $this->hasOption('noviews') );
|
||||
}
|
||||
if( isset( $options['help'] ) ) {
|
||||
showHelp();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require "$IP/maintenance/initStats.inc";
|
||||
wfInitStats( $options );
|
||||
|
||||
function showHelp() {
|
||||
echo( "Re-initialise the site statistics tables.\n\n" );
|
||||
echo( "Usage: php initStats.php [--update|--noviews]\n\n" );
|
||||
echo( " --update : Update the existing statistics (preserves the ss_total_views field)\n" );
|
||||
echo( "--noviews : Don't update the page view counter\n\n" );
|
||||
}
|
||||
|
||||
$maintClass = "InitStats";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
|
|
|||
|
|
@ -8,63 +8,58 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$optionsWithArgs = array( 'i' );
|
||||
|
||||
class mcTest extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Makes several 'set', 'incr' and 'get' requests on every"
|
||||
. " memcached server and shows a report";
|
||||
$this->addParam( 'i', 'Number of iterations', false, true );
|
||||
$this->addArgs( array( 'server' ) );
|
||||
}
|
||||
require_once('commandLine.inc');
|
||||
|
||||
public function execute() {
|
||||
global $wgMemCachedServers;
|
||||
function microtime_float()
|
||||
{
|
||||
list($usec, $sec) = explode(" ", microtime());
|
||||
return ((float)$usec + (float)$sec);
|
||||
}
|
||||
|
||||
$iterations = $this->getOption( 'i', 100 );
|
||||
if( $this->hasArg() )
|
||||
$wgMemCachedServers = array( $this->getArg() );
|
||||
|
||||
foreach ( $wgMemCachedServers as $server ) {
|
||||
$this->output( $server . " " );
|
||||
$mcc = new MemCachedClientforWiki( array('persistant' => true) );
|
||||
$mcc->set_servers( array( $server ) );
|
||||
$set = 0;
|
||||
$incr = 0;
|
||||
$get = 0;
|
||||
$time_start = $this->microtime_float();
|
||||
for ( $i=1; $i<=$iterations; $i++ ) {
|
||||
if ( !is_null( $mcc->set( "test$i", $i ) ) ) {
|
||||
$set++;
|
||||
}
|
||||
}
|
||||
for ( $i=1; $i<=$iterations; $i++ ) {
|
||||
if ( !is_null( $mcc->incr( "test$i", $i ) ) ) {
|
||||
$incr++;
|
||||
}
|
||||
}
|
||||
for ( $i=1; $i<=$iterations; $i++ ) {
|
||||
$value = $mcc->get( "test$i" );
|
||||
if ( $value == $i*2 ) {
|
||||
$get++;
|
||||
}
|
||||
}
|
||||
$exectime = $this->microtime_float() - $time_start;
|
||||
|
||||
$this->output( "set: $set incr: $incr get: $get time: $exectime\n" );
|
||||
#$wgDebugLogFile = '/dev/stdout';
|
||||
|
||||
if ( isset( $args[0] ) ) {
|
||||
$wgMemCachedServers = array( $args[0] );
|
||||
}
|
||||
if ( isset( $options['i'] ) ) {
|
||||
$iterations = $options['i'];
|
||||
} else {
|
||||
$iterations = 100;
|
||||
}
|
||||
|
||||
foreach ( $wgMemCachedServers as $server ) {
|
||||
print "$server ";
|
||||
$mcc = new MemCachedClientforWiki( array('persistant' => true) );
|
||||
$mcc->set_servers( array( $server ) );
|
||||
$set = 0;
|
||||
$incr = 0;
|
||||
$get = 0;
|
||||
$time_start=microtime_float();
|
||||
for ( $i=1; $i<=$iterations; $i++ ) {
|
||||
if ( !is_null( $mcc->set( "test$i", $i ) ) ) {
|
||||
$set++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return microtime() as a float
|
||||
* @return float
|
||||
*/
|
||||
private function microtime_float() {
|
||||
list($usec, $sec) = explode(" ", microtime());
|
||||
return ((float)$usec + (float)$sec);
|
||||
for ( $i=1; $i<=$iterations; $i++ ) {
|
||||
if ( !is_null( $mcc->incr( "test$i", $i ) ) ) {
|
||||
$incr++;
|
||||
}
|
||||
}
|
||||
|
||||
for ( $i=1; $i<=$iterations; $i++ ) {
|
||||
$value = $mcc->get( "test$i" );
|
||||
if ( $value == $i*2 ) {
|
||||
$get++;
|
||||
}
|
||||
}
|
||||
$exectime=microtime_float()-$time_start;
|
||||
|
||||
print "set: $set incr: $incr get: $get time: $exectime\n";
|
||||
}
|
||||
|
||||
$maintClass = "mcTest";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Maintenance script to move a batch of pages
|
||||
*
|
||||
* @file
|
||||
* @ingroup Maintenance
|
||||
* @author Tim Starling
|
||||
*
|
||||
|
|
@ -18,77 +20,77 @@
|
|||
* e.g. immobile_namespace for namespaces which can't be moved
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$oldCwd = getcwd();
|
||||
$optionsWithArgs = array( 'u', 'r', 'i' );
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
class MoveBatch extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Moves a batch of pages";
|
||||
$this->addParam( 'u', "User to perform move", false, true );
|
||||
$this->addParam( 'r', "Reason to move page", false, true );
|
||||
$this->addParam( 'i', "Interval to sleep between moves" );
|
||||
$this->addArgs( array( 'listfile' ) );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUser;
|
||||
chdir( $oldCwd );
|
||||
|
||||
# Change to current working directory
|
||||
$oldCwd = getcwd();
|
||||
chdir( $oldCwd );
|
||||
# Options processing
|
||||
|
||||
# Options processing
|
||||
$user = $this->getOption( 'u', 'Move page script' );
|
||||
$reason = $this->getOption( 'r', '' );
|
||||
$interval = $this->getOption( 'i', 0 );
|
||||
if( $this->hasArg() ) {
|
||||
$file = fopen( $this->getArg(), 'r' );
|
||||
} else {
|
||||
$file = $this->getStdin();
|
||||
}
|
||||
$filename = 'php://stdin';
|
||||
$user = 'Move page script';
|
||||
$reason = '';
|
||||
$interval = 0;
|
||||
|
||||
# Setup
|
||||
if( !$file ) {
|
||||
$this->error( "Unable to read file, exiting\n", true );
|
||||
}
|
||||
$wgUser = User::newFromName( $user );
|
||||
|
||||
# Setup complete, now start
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
for ( $linenum = 1; !feof( $file ); $linenum++ ) {
|
||||
$line = fgets( $file );
|
||||
if ( $line === false ) {
|
||||
break;
|
||||
}
|
||||
$parts = array_map( 'trim', explode( '|', $line ) );
|
||||
if ( count( $parts ) != 2 ) {
|
||||
$this->error( "Error on line $linenum, no pipe character\n" );
|
||||
continue;
|
||||
}
|
||||
$source = Title::newFromText( $parts[0] );
|
||||
$dest = Title::newFromText( $parts[1] );
|
||||
if ( is_null( $source ) || is_null( $dest ) ) {
|
||||
$this->error( "Invalid title on line $linenum\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$this->output( $source->getPrefixedText() . ' --> ' . $dest->getPrefixedText() );
|
||||
$dbw->begin();
|
||||
$err = $source->moveTo( $dest, false, $reason );
|
||||
if( $err !== true ) {
|
||||
$this->output( "\nFAILED: $err" );
|
||||
}
|
||||
$dbw->immediateCommit();
|
||||
$this->output( "\n" );
|
||||
|
||||
if ( $interval ) {
|
||||
sleep( $interval );
|
||||
}
|
||||
wfWaitForSlaves( 5 );
|
||||
}
|
||||
}
|
||||
if ( isset( $args[0] ) ) {
|
||||
$filename = $args[0];
|
||||
}
|
||||
if ( isset( $options['u'] ) ) {
|
||||
$user = $options['u'];
|
||||
}
|
||||
if ( isset( $options['r'] ) ) {
|
||||
$reason = $options['r'];
|
||||
}
|
||||
if ( isset( $options['i'] ) ) {
|
||||
$interval = $options['i'];
|
||||
}
|
||||
|
||||
$maintClass = "MoveBatch";
|
||||
require_once( DO_MAINTENANCE );
|
||||
$wgUser = User::newFromName( $user );
|
||||
|
||||
|
||||
# Setup complete, now start
|
||||
|
||||
$file = fopen( $filename, 'r' );
|
||||
if ( !$file ) {
|
||||
print "Unable to read file, exiting\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
for ( $linenum = 1; !feof( $file ); $linenum++ ) {
|
||||
$line = fgets( $file );
|
||||
if ( $line === false ) {
|
||||
break;
|
||||
}
|
||||
$parts = array_map( 'trim', explode( '|', $line ) );
|
||||
if ( count( $parts ) != 2 ) {
|
||||
print "Error on line $linenum, no pipe character\n";
|
||||
continue;
|
||||
}
|
||||
$source = Title::newFromText( $parts[0] );
|
||||
$dest = Title::newFromText( $parts[1] );
|
||||
if ( is_null( $source ) || is_null( $dest ) ) {
|
||||
print "Invalid title on line $linenum\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
print $source->getPrefixedText() . ' --> ' . $dest->getPrefixedText();
|
||||
$dbw->begin();
|
||||
$err = $source->moveTo( $dest, false, $reason );
|
||||
if( $err !== true ) {
|
||||
print "\nFAILED: $err";
|
||||
}
|
||||
$dbw->immediateCommit();
|
||||
print "\n";
|
||||
|
||||
if ( $interval ) {
|
||||
sleep( $interval );
|
||||
}
|
||||
wfWaitForSlaves( 5 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,71 +6,55 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$options = array( 'type' );
|
||||
|
||||
class nextJobDB extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Pick a database that has pending jobs";
|
||||
$this->addParam( 'type', "The type of job to search for", false, true );
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
$type = isset($options['type'])
|
||||
? $options['type']
|
||||
: false;
|
||||
|
||||
$mckey = $type === false
|
||||
? "jobqueue:dbs"
|
||||
: "jobqueue:dbs:$type";
|
||||
|
||||
$pendingDBs = $wgMemc->get( $mckey );
|
||||
if ( !$pendingDBs ) {
|
||||
$pendingDBs = array();
|
||||
# Cross-reference DBs by master DB server
|
||||
$dbsByMaster = array();
|
||||
foreach ( $wgLocalDatabases as $db ) {
|
||||
$lb = wfGetLB( $db );
|
||||
$dbsByMaster[$lb->getServerName(0)][] = $db;
|
||||
}
|
||||
public function execute() {
|
||||
global $wgMemc;
|
||||
$type = $this->getParam( 'type', false );
|
||||
$mckey = $type === false
|
||||
? "jobqueue:dbs"
|
||||
: "jobqueue:dbs:$type";
|
||||
$pendingDBs = $wgMemcKey->get( $mckey );
|
||||
|
||||
# If we didn't get it from the cache
|
||||
if( !$pendingDBs ) {
|
||||
$pendingDBs = $this->getPendingDbs( $type );
|
||||
$wgMemc->get( $mckey, $pendingDBs, 300 )
|
||||
}
|
||||
# If we've got a pending job in a db, display it.
|
||||
if ( $pendingDBs ) {
|
||||
$this->output( $pendingDBs[mt_rand(0, count( $pendingDBs ) - 1)] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all databases that have a pending job
|
||||
* @param $type String Job type
|
||||
* @return array
|
||||
*/
|
||||
private function getPendingDbs( $type ) {
|
||||
$pendingDBs = array();
|
||||
# Cross-reference DBs by master DB server
|
||||
$dbsByMaster = array();
|
||||
foreach ( $wgLocalDatabases as $db ) {
|
||||
$lb = wfGetLB( $db );
|
||||
$dbsByMaster[$lb->getServerName(0)][] = $db;
|
||||
}
|
||||
|
||||
foreach ( $dbsByMaster as $master => $dbs ) {
|
||||
$dbConn = wfGetDB( DB_MASTER, array(), $dbs[0] );
|
||||
$stype = $dbConn->addQuotes($type);
|
||||
$jobTable = $dbConn->getTable( 'job' );
|
||||
|
||||
# Padding row for MySQL bug
|
||||
$sql = "(SELECT '-------------------------------------------')";
|
||||
foreach ( $dbs as $dbName ) {
|
||||
if ( $sql != '' ) {
|
||||
$sql .= ' UNION ';
|
||||
}
|
||||
if ($type === false)
|
||||
$sql .= "(SELECT '$dbName' FROM `$dbName`.$jobTable LIMIT 1)";
|
||||
else
|
||||
$sql .= "(SELECT '$dbName' FROM `$dbName`.$jobTable WHERE job_cmd=$stype LIMIT 1)";
|
||||
}
|
||||
$res = $dbConn->query( $sql, __METHOD__ );
|
||||
$row = $dbConn->fetchRow( $res ); // discard padding row
|
||||
while ( $row = $dbConn->fetchRow( $res ) ) {
|
||||
$pendingDBs[] = $row[0];
|
||||
|
||||
foreach ( $dbsByMaster as $master => $dbs ) {
|
||||
$dbConn = wfGetDB( DB_MASTER, array(), $dbs[0] );
|
||||
$stype = $dbConn->addQuotes($type);
|
||||
|
||||
# Padding row for MySQL bug
|
||||
$sql = "(SELECT '-------------------------------------------')";
|
||||
foreach ( $dbs as $dbName ) {
|
||||
if ( $sql != '' ) {
|
||||
$sql .= ' UNION ';
|
||||
}
|
||||
if ($type === false)
|
||||
$sql .= "(SELECT '$dbName' FROM `$dbName`.job LIMIT 1)";
|
||||
else
|
||||
$sql .= "(SELECT '$dbName' FROM `$dbName`.job WHERE job_cmd=$stype LIMIT 1)";
|
||||
}
|
||||
$res = $dbConn->query( $sql, 'nextJobDB.php' );
|
||||
$row = $dbConn->fetchRow( $res ); // discard padding row
|
||||
while ( $row = $dbConn->fetchRow( $res ) ) {
|
||||
$pendingDBs[] = $row[0];
|
||||
}
|
||||
}
|
||||
|
||||
$wgMemc->set( $mckey, $pendingDBs, 300 );
|
||||
}
|
||||
|
||||
$maintClass = "nextJobDb";
|
||||
require_once( DO_MAINTENANCE );
|
||||
if ( $pendingDBs ) {
|
||||
echo $pendingDBs[mt_rand(0, count( $pendingDBs ) - 1)];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,80 +19,90 @@
|
|||
* based on nukePage by Rob Church
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
require_once( 'commandLine.inc' );
|
||||
require_once( 'nukePage.inc' );
|
||||
|
||||
class NukeNS extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Remove pages with only 1 revision from any namespace";
|
||||
$this->addParam( 'delete', "Actually delete the page" );
|
||||
$this->addParam( 'ns', 'Namespace to delete from, default NS_MEDIAWIKI', false, true );
|
||||
}
|
||||
$ns = NS_MEDIAWIKI;
|
||||
$delete = false;
|
||||
|
||||
public function execute() {
|
||||
$ns = $this->getOption( 'ns', NS_MEDIAWIKI );
|
||||
$delete = $this->getOption( 'delete', false );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
$tbl_pag = $dbw->tableName( 'page' );
|
||||
$tbl_rev = $dbw->tableName( 'revision' );
|
||||
$res = $dbw->query( "SELECT page_title FROM $tbl_pag WHERE page_namespace = $ns" );
|
||||
|
||||
$n_deleted = 0;
|
||||
|
||||
while( $row = $dbw->fetchObject( $res ) ) {
|
||||
//echo "$ns_name:".$row->page_title, "\n";
|
||||
$title = Title::newFromText($row->page_title, $ns);
|
||||
$id = $title->getArticleID();
|
||||
|
||||
// Get corresponding revisions
|
||||
$res2 = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_page = $id" );
|
||||
$revs = array();
|
||||
|
||||
while( $row2 = $dbw->fetchObject( $res2 ) ) {
|
||||
$revs[] = $row2->rev_id;
|
||||
}
|
||||
$count = count( $revs );
|
||||
|
||||
//skip anything that looks modified (i.e. multiple revs)
|
||||
if (($count == 1)) {
|
||||
#echo $title->getPrefixedText(), "\t", $count, "\n";
|
||||
$this->output( "delete: ", $title->getPrefixedText(), "\n" );
|
||||
|
||||
//as much as I hate to cut & paste this, it's a little different, and
|
||||
//I already have the id & revs
|
||||
if( $delete ) {
|
||||
$dbw->query( "DELETE FROM $tbl_pag WHERE page_id = $id" );
|
||||
$dbw->commit();
|
||||
// Delete revisions as appropriate
|
||||
$child = $this->spawnChild( 'NukePage', 'NukePage.php' );
|
||||
$child->deleteRevisions( $revs );
|
||||
$this->purgeRedundantText( true );
|
||||
$n_deleted ++;
|
||||
}
|
||||
} else {
|
||||
$this->output( "skip: ", $title->getPrefixedText(), "\n" );
|
||||
}
|
||||
}
|
||||
$dbw->commit();
|
||||
|
||||
if ($n_deleted > 0) {
|
||||
#update statistics - better to decrement existing count, or just count
|
||||
#the page table?
|
||||
$pages = $dbw->selectField('site_stats', 'ss_total_pages');
|
||||
$pages -= $n_deleted;
|
||||
$dbw->update( 'site_stats',
|
||||
array('ss_total_pages' => $pages ),
|
||||
array( 'ss_row_id' => 1),
|
||||
__METHOD__ );
|
||||
}
|
||||
|
||||
if (!$delete) {
|
||||
$this->output( "To update the database, run the script with the --delete option.\n" );
|
||||
}
|
||||
}
|
||||
if (isset($options['ns']))
|
||||
{
|
||||
$ns = $options['ns'];
|
||||
}
|
||||
|
||||
$maintClass = "NukeNS";
|
||||
require_once( DO_MAINTENANCE );
|
||||
if (isset( $options['delete'] ) and $options['delete'])
|
||||
{
|
||||
$delete = true;
|
||||
}
|
||||
|
||||
|
||||
NukeNS( $ns, $delete);
|
||||
|
||||
function NukeNS($ns_no, $delete) {
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
$tbl_pag = $dbw->tableName( 'page' );
|
||||
$tbl_rev = $dbw->tableName( 'revision' );
|
||||
$res = $dbw->query( "SELECT page_title FROM $tbl_pag WHERE page_namespace = $ns_no" );
|
||||
|
||||
$n_deleted = 0;
|
||||
|
||||
while( $row = $dbw->fetchObject( $res ) ) {
|
||||
//echo "$ns_name:".$row->page_title, "\n";
|
||||
$title = Title::newFromText($row->page_title, $ns_no);
|
||||
$id = $title->getArticleID();
|
||||
|
||||
// Get corresponding revisions
|
||||
$res2 = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_page = $id" );
|
||||
$revs = array();
|
||||
|
||||
while( $row2 = $dbw->fetchObject( $res2 ) ) {
|
||||
$revs[] = $row2->rev_id;
|
||||
}
|
||||
$count = count( $revs );
|
||||
|
||||
//skip anything that looks modified (i.e. multiple revs)
|
||||
if (($count == 1)) {
|
||||
#echo $title->getPrefixedText(), "\t", $count, "\n";
|
||||
echo "delete: ", $title->getPrefixedText(), "\n";
|
||||
|
||||
//as much as I hate to cut & paste this, it's a little different, and
|
||||
//I already have the id & revs
|
||||
|
||||
if( $delete ) {
|
||||
$dbw->query( "DELETE FROM $tbl_pag WHERE page_id = $id" );
|
||||
$dbw->commit();
|
||||
// Delete revisions as appropriate
|
||||
DeleteRevisions( $revs );
|
||||
PurgeRedundantText( true );
|
||||
$n_deleted ++;
|
||||
}
|
||||
} else {
|
||||
echo "skip: ", $title->getPrefixedText(), "\n";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
$dbw->commit();
|
||||
|
||||
if ($n_deleted > 0) {
|
||||
#update statistics - better to decrement existing count, or just count
|
||||
#the page table?
|
||||
$pages = $dbw->selectField('site_stats', 'ss_total_pages');
|
||||
$pages -= $n_deleted;
|
||||
$dbw->update( 'site_stats',
|
||||
array('ss_total_pages' => $pages ),
|
||||
array( 'ss_row_id' => 1),
|
||||
__METHOD__ );
|
||||
|
||||
}
|
||||
|
||||
if (!$delete) {
|
||||
echo( "To update the database, run the script with the --delete option.\n" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Erase a page record from the database
|
||||
* Irreversible (can't use standard undelete) and does not update link tables
|
||||
|
|
@ -8,92 +9,21 @@
|
|||
* @author Rob Church <robchur@gmail.com>
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
require_once( 'commandLine.inc' );
|
||||
require_once( 'nukePage.inc' );
|
||||
|
||||
class NukePage extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Remove a page record from the database";
|
||||
$this->addParam( 'delete', "Actually delete the page" );
|
||||
$this->addArgs( array( 'title' ) );
|
||||
}
|
||||
echo( "Erase Page Record\n\n" );
|
||||
|
||||
public function execute() {
|
||||
|
||||
$name = $this->getArg();
|
||||
$delete = $this->getOption( 'delete', false );
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
$tbl_pag = $dbw->tableName( 'page' );
|
||||
$tbl_rec = $dbw->tableName( 'recentchanges' );
|
||||
$tbl_rev = $dbw->tableName( 'revision' );
|
||||
|
||||
# Get page ID
|
||||
$this->output( "Searching for \"$name\"..." );
|
||||
$title = Title::newFromText( $name );
|
||||
if( $title ) {
|
||||
$id = $title->getArticleID();
|
||||
$real = $title->getPrefixedText();
|
||||
$isGoodArticle = $title->isContentPage();
|
||||
$this->output( "found \"$real\" with ID $id.\n" );
|
||||
|
||||
# Get corresponding revisions
|
||||
$this->output( "Searching for revisions..." );
|
||||
$res = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_page = $id" );
|
||||
while( $row = $dbw->fetchObject( $res ) ) {
|
||||
$revs[] = $row->rev_id;
|
||||
}
|
||||
$count = count( $revs );
|
||||
$this->output( "found $count.\n" );
|
||||
|
||||
# Delete the page record and associated recent changes entries
|
||||
if( $delete ) {
|
||||
$this->output( "Deleting page record..." );
|
||||
$dbw->query( "DELETE FROM $tbl_pag WHERE page_id = $id" );
|
||||
$this->output( "done.\n" );
|
||||
$this->output( "Cleaning up recent changes..." );
|
||||
$dbw->query( "DELETE FROM $tbl_rec WHERE rc_cur_id = $id" );
|
||||
$this->output( "done.\n" );
|
||||
}
|
||||
|
||||
$dbw->commit();
|
||||
|
||||
# Delete revisions as appropriate
|
||||
if( $delete && $count ) {
|
||||
$this->output( "Deleting revisions..." );
|
||||
$this->deleteRevisions( $revs );
|
||||
$this->output( "done.\n" );
|
||||
$this->purgeRedundantText( true );
|
||||
}
|
||||
|
||||
# Update stats as appropriate
|
||||
if ( $delete ) {
|
||||
$this->output( "Updating site stats..." );
|
||||
$ga = $isGoodArticle ? -1 : 0; // if it was good, decrement that too
|
||||
$stats = new SiteStatsUpdate( 0, -$count, $ga, -1 );
|
||||
$stats->doUpdate();
|
||||
$this->output( "done.\n" );
|
||||
}
|
||||
} else {
|
||||
$this->output( "not found in database.\n" );
|
||||
$dbw->commit();
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteRevisions( $ids ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->begin();
|
||||
|
||||
$tbl_rev = $dbw->tableName( 'revision' );
|
||||
|
||||
$set = implode( ', ', $ids );
|
||||
$dbw->query( "DELETE FROM $tbl_rev WHERE rev_id IN ( $set )" );
|
||||
|
||||
$dbw->commit();
|
||||
}
|
||||
if( isset( $args[0] ) ) {
|
||||
NukePage( $args[0], true );
|
||||
} else {
|
||||
ShowUsage();
|
||||
}
|
||||
|
||||
/** Show script usage information */
|
||||
function ShowUsage() {
|
||||
echo( "Remove a page record from the database.\n\n" );
|
||||
echo( "Usage: php nukePage.php <title>\n\n" );
|
||||
echo( " <title> : Page title; spaces escaped with underscores\n\n" );
|
||||
}
|
||||
|
||||
$maintClass = "NukePage";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
|
@ -9,88 +9,13 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class PopulateLogSearch extends Maintenance {
|
||||
|
||||
const LOG_SEARCH_BATCH_SIZE = 100;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Migrate log params to new table and index for searching";
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$db = wfGetDB( DB_MASTER );
|
||||
if ( !$db->tableExists( 'log_search' ) ) {
|
||||
$this->error( "log_search does not exist\n", true );
|
||||
}
|
||||
$start = $db->selectField( 'logging', 'MIN(log_id)', false, __FUNCTION__ );
|
||||
if( !$start ) {
|
||||
$this->output( "Nothing to do.\n" );
|
||||
return true;
|
||||
}
|
||||
$end = $db->selectField( 'logging', 'MAX(log_id)', false, __FUNCTION__ );
|
||||
require_once 'commandLine.inc';
|
||||
require_once 'populateLogSearch.inc';
|
||||
|
||||
# Do remaining chunk
|
||||
$end += self::LOG_SEARCH_BATCH_SIZE - 1;
|
||||
$blockStart = $start;
|
||||
$blockEnd = $start + self::LOG_SEARCH_BATCH_SIZE - 1;
|
||||
while( $blockEnd <= $end ) {
|
||||
$this->output( "...doing log_id from $blockStart to $blockEnd\n" );
|
||||
$cond = "log_id BETWEEN $blockStart AND $blockEnd";
|
||||
$res = $db->select( 'logging', '*', $cond, __FUNCTION__ );
|
||||
$batch = array();
|
||||
while( $row = $db->fetchObject( $res ) ) {
|
||||
// RevisionDelete logs - revisions
|
||||
if( LogEventsList::typeAction( $row, array('delete','suppress'), 'revision' ) ) {
|
||||
$params = LogPage::extractParams( $row->log_params );
|
||||
// Param format: <urlparam> <item CSV> [<ofield> <nfield>]
|
||||
if( count($params) >= 2 ) {
|
||||
$field = RevisionDeleter::getRelationType($params[0]);
|
||||
// B/C, the params may start with a title key
|
||||
if( $field == null ) {
|
||||
array_shift($params);
|
||||
$field = RevisionDeleter::getRelationType($params[0]);
|
||||
}
|
||||
if( $field == null ) {
|
||||
$this->output( "Invalid param type for $row->log_id\n" );
|
||||
continue; // skip this row
|
||||
}
|
||||
$items = explode(',',$params[1]);
|
||||
$log = new LogPage( $row->log_type );
|
||||
$log->addRelations( $field, $items, $row->log_id );
|
||||
}
|
||||
// RevisionDelete logs - log events
|
||||
} else if( LogEventsList::typeAction( $row, array('delete','suppress'), 'event' ) ) {
|
||||
$params = LogPage::extractParams( $row->log_params );
|
||||
// Param format: <item CSV> [<ofield> <nfield>]
|
||||
if( count($params) >= 1 ) {
|
||||
$items = explode(',',$params[0]);
|
||||
$log = new LogPage( $row->log_type );
|
||||
$log->addRelations( 'log_id', $items, $row->log_id );
|
||||
}
|
||||
}
|
||||
}
|
||||
$blockStart += self::LOG_SEARCH_BATCH_SIZE;
|
||||
$blockEnd += self::LOG_SEARCH_BATCH_SIZE;
|
||||
wfWaitForSlaves( 5 );
|
||||
}
|
||||
if( $db->insert(
|
||||
'updatelog',
|
||||
array( 'ul_key' => 'populate log_search' ),
|
||||
__FUNCTION__,
|
||||
'IGNORE'
|
||||
)
|
||||
) {
|
||||
$this->output( "log_search population complete.\n" );
|
||||
return true;
|
||||
} else {
|
||||
$this->output( "Could not insert log_search population row.\n" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$db =& wfGetDB( DB_MASTER );
|
||||
if ( !$db->tableExists( 'log_search' ) ) {
|
||||
echo "log_search does not exist\n";
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
$maintClass = "PopulateLogSearch";
|
||||
require_once( DO_MAINTENANCE );
|
||||
migrate_log_params( $db );
|
||||
|
|
|
|||
|
|
@ -1,105 +1,18 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Makes the required database updates for rev_parent_id
|
||||
* to be of any use. It can be used for some simple tracking
|
||||
* and to find new page edits by users.
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class PopulateParentId extends Maintenance {
|
||||
|
||||
// Batch size
|
||||
const BATCH_SIZE = 200;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Populates rev_parent_id";
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$db = wfGetDB( DB_MASTER );
|
||||
if ( !$db->tableExists( 'revision' ) ) {
|
||||
$this->error( "revision table does not exist\n", true );
|
||||
}
|
||||
$this->output( "Populating rev_parent_id column\n" );
|
||||
$start = $db->selectField( 'revision', 'MIN(rev_id)', false, __FUNCTION__ );
|
||||
$end = $db->selectField( 'revision', 'MAX(rev_id)', false, __FUNCTION__ );
|
||||
if( is_null( $start ) || is_null( $end ) ){
|
||||
$this->output( "...revision table seems to be empty.\n" );
|
||||
$db->insert( 'updatelog',
|
||||
array( 'ul_key' => 'populate rev_parent_id' ),
|
||||
__FUNCTION__,
|
||||
'IGNORE' );
|
||||
return;
|
||||
}
|
||||
# Do remaining chunk
|
||||
$end += self::BATCH_SIZE - 1;
|
||||
$blockStart = intval( $start );
|
||||
$blockEnd = intval( $start ) + self::BATCH_SIZE - 1;
|
||||
$count = 0;
|
||||
$changed = 0;
|
||||
while( $blockEnd <= $end ) {
|
||||
$this->output( "...doing rev_id from $blockStart to $blockEnd\n" );
|
||||
$cond = "rev_id BETWEEN $blockStart AND $blockEnd";
|
||||
$res = $db->select( 'revision',
|
||||
array('rev_id','rev_page','rev_timestamp','rev_parent_id'),
|
||||
$cond, __FUNCTION__ );
|
||||
# Go through and update rev_parent_id from these rows.
|
||||
# Assume that the previous revision of the title was
|
||||
# the original previous revision of the title when the
|
||||
# edit was made...
|
||||
foreach( $res as $row ) {
|
||||
# First, check rows with the same timestamp other than this one
|
||||
# with a smaller rev ID. The highest ID "wins". This avoids loops
|
||||
# as timestamp can only decrease and never loops with IDs (from parent to parent)
|
||||
$previousID = $db->selectField( 'revision', 'rev_id',
|
||||
array( 'rev_page' => $row->rev_page, 'rev_timestamp' => $row->rev_timestamp,
|
||||
"rev_id < " . intval( $row->rev_id ) ),
|
||||
__FUNCTION__,
|
||||
array( 'ORDER BY' => 'rev_id DESC' ) );
|
||||
# If there are none, check the the highest ID with a lower timestamp
|
||||
if( !$previousID ) {
|
||||
# Get the highest older timestamp
|
||||
$lastTimestamp = $db->selectField( 'revision', 'rev_timestamp',
|
||||
array( 'rev_page' => $row->rev_page, "rev_timestamp < " . $db->addQuotes( $row->rev_timestamp ) ),
|
||||
__FUNCTION__,
|
||||
array( 'ORDER BY' => 'rev_timestamp DESC' ) );
|
||||
# If there is one, let the highest rev ID win
|
||||
if( $lastTimestamp ) {
|
||||
$previousID = $db->selectField( 'revision', 'rev_id',
|
||||
array( 'rev_page' => $row->rev_page, 'rev_timestamp' => $lastTimestamp ),
|
||||
__FUNCTION__,
|
||||
array( 'ORDER BY' => 'rev_id DESC' ) );
|
||||
}
|
||||
}
|
||||
$previousID = intval($previousID);
|
||||
if( $previousID != $row->rev_parent_id )
|
||||
$changed++;
|
||||
# Update the row...
|
||||
$db->update( 'revision',
|
||||
array( 'rev_parent_id' => $previousID ),
|
||||
array( 'rev_id' => $row->rev_id ),
|
||||
__FUNCTION__ );
|
||||
$count++;
|
||||
}
|
||||
$blockStart += self::BATCH_SIZE - 1;
|
||||
$blockEnd += self::BATCH_SIZE - 1;
|
||||
wfWaitForSlaves( 5 );
|
||||
}
|
||||
$logged = $db->insert( 'updatelog',
|
||||
array( 'ul_key' => 'populate rev_parent_id' ),
|
||||
__FUNCTION__,
|
||||
'IGNORE' );
|
||||
if( $logged ) {
|
||||
$this->output( "rev_parent_id population complete ... {$count} rows [{$changed} changed]\n" );
|
||||
return true;
|
||||
} else {
|
||||
$this->output( "Could not insert rev_parent_id population row.\n" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
require_once 'commandLine.inc';
|
||||
require_once 'populateParentId.inc';
|
||||
|
||||
$db =& wfGetDB( DB_MASTER );
|
||||
if ( !$db->tableExists( 'revision' ) ) {
|
||||
echo "revision table does not exist\n";
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
$maintClass = "PopulateParentId";
|
||||
require_once( DO_MAINTENANCE );
|
||||
populate_rev_parent_id( $db );
|
||||
|
|
|
|||
|
|
@ -1,24 +1,29 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Purge old text records from the database
|
||||
*
|
||||
* @file
|
||||
* @ingroup Maintenance
|
||||
* @author Rob Church <robchur@gmail.com>
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$options = array( 'purge', 'help' );
|
||||
require_once( 'commandLine.inc' );
|
||||
require_once( 'purgeOldText.inc' );
|
||||
|
||||
class PurgeOldText extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Purge old text records from the database";
|
||||
$this->addOption( 'purge', 'Performs the deletion' );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$this->purgeRedundantText( $this->hasOption('purge') );
|
||||
}
|
||||
echo( "Purge Old Text\n\n" );
|
||||
|
||||
if( @$options['help'] ) {
|
||||
ShowUsage();
|
||||
} else {
|
||||
PurgeRedundantText( @$options['purge'] );
|
||||
}
|
||||
|
||||
function ShowUsage() {
|
||||
echo( "Prunes unused text records from the database.\n\n" );
|
||||
echo( "Usage: php purgeOldText.php [--purge]\n\n" );
|
||||
echo( "purge : Performs the deletion\n" );
|
||||
echo( " help : Show this usage information\n" );
|
||||
}
|
||||
|
||||
$maintClass = "PurgeOldText";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
|
|
|||
|
|
@ -1,153 +1,56 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Reassign edits from a user or IP address to another user
|
||||
*
|
||||
* @file
|
||||
* @ingroup Maintenance
|
||||
* @author Rob Church <robchur@gmail.com>
|
||||
* @licence GNU General Public Licence 2.0 or later
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$options = array( 'force', 'norc', 'quiet', 'report' );
|
||||
require_once( 'commandLine.inc' );
|
||||
require_once( 'reassignEdits.inc' );
|
||||
|
||||
class ReassignEdits extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Reassign edits from one user to another";
|
||||
$this->addParam( "force", "Reassign even if the target user doesn't exist" );
|
||||
$this->addParam( "norc", "Don't update the recent changes table" );
|
||||
$this->addParam( "report", "Print out details of what would be changed, but don't update it" );
|
||||
$this->addArgs( array( 'from', 'to' ) );
|
||||
# Set silent mode; --report overrides --quiet
|
||||
if( !@$options['report'] && @$options['quiet'] )
|
||||
setSilent();
|
||||
|
||||
out( "Reassign Edits\n\n" );
|
||||
|
||||
if( @$args[0] && @$args[1] ) {
|
||||
|
||||
# Set up the users involved
|
||||
$from =& initialiseUser( $args[0] );
|
||||
$to =& initialiseUser( $args[1] );
|
||||
|
||||
# If the target doesn't exist, and --force is not set, stop here
|
||||
if( $to->getId() || @$options['force'] ) {
|
||||
# Reassign the edits
|
||||
$report = @$options['report'];
|
||||
$count = reassignEdits( $from, $to, !@$options['norc'], $report );
|
||||
# If reporting, and there were items, advise the user to run without --report
|
||||
if( $report )
|
||||
out( "Run the script again without --report to update.\n" );
|
||||
} else {
|
||||
$ton = $to->getName();
|
||||
echo( "User '{$ton}' not found.\n" );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
if( $this->hasArg(0) && $this->hasArg(1) ) {
|
||||
# Set up the users involved
|
||||
$from =& $this->initialiseUser( $this->getArg(0) );
|
||||
$to =& $this->initialiseUser( $this->getArg(1) );
|
||||
|
||||
# If the target doesn't exist, and --force is not set, stop here
|
||||
if( $to->getId() || $this->hasOption('force') ) {
|
||||
# Reassign the edits
|
||||
$report = $this->hasOption('report');
|
||||
$count = $this->reassignEdits( $from, $to, !$this->hasOption('norc'), $report );
|
||||
# If reporting, and there were items, advise the user to run without --report
|
||||
if( $report )
|
||||
$this->output( "Run the script again without --report to update.\n" );
|
||||
} else {
|
||||
$ton = $to->getName();
|
||||
$this->error( "User '{$ton}' not found.\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reassign edits from one user to another
|
||||
*
|
||||
* @param $from User to take edits from
|
||||
* @param $to User to assign edits to
|
||||
* @param $rc Update the recent changes table
|
||||
* @param $report Don't change things; just echo numbers
|
||||
* @return integer Number of entries changed, or that would be changed
|
||||
*/
|
||||
private function reassignEdits( &$from, &$to, $rc = false, $report = false ) {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->immediateBegin();
|
||||
|
||||
# Count things
|
||||
$this->output( "Checking current edits..." );
|
||||
$res = $dbw->select( 'revision', 'COUNT(*) AS count', $this->userConditions( $from, 'rev_user', 'rev_user_text' ), __METHOD__ );
|
||||
$row = $dbw->fetchObject( $res );
|
||||
$cur = $row->count;
|
||||
$this->output( "found {$cur}.\n" );
|
||||
|
||||
$this->output( "Checking deleted edits..." );
|
||||
$res = $dbw->select( 'archive', 'COUNT(*) AS count', $this->userConditions( $from, 'ar_user', 'ar_user_text' ), __METHOD__ );
|
||||
$row = $dbw->fetchObject( $res );
|
||||
$del = $row->count;
|
||||
$this->output( "found {$del}.\n" );
|
||||
|
||||
# Don't count recent changes if we're not supposed to
|
||||
if( $rc ) {
|
||||
$this->output( "Checking recent changes..." );
|
||||
$res = $dbw->select( 'recentchanges', 'COUNT(*) AS count', $this->userConditions( $from, 'rc_user', 'rc_user_text' ), __METHOD__ );
|
||||
$row = $dbw->fetchObject( $res );
|
||||
$rec = $row->count;
|
||||
$this->output( "found {$rec}.\n" );
|
||||
} else {
|
||||
$rec = 0;
|
||||
}
|
||||
|
||||
$total = $cur + $del + $rec;
|
||||
$this->output( "\nTotal entries to change: {$total}\n" );
|
||||
|
||||
if( !$report ) {
|
||||
if( $total ) {
|
||||
# Reassign edits
|
||||
$this->output( "\nReassigning current edits..." );
|
||||
$res = $dbw->update( 'revision', userSpecification( $to, 'rev_user', 'rev_user_text' ), $this->userConditions( $from, 'rev_user', 'rev_user_text' ), __METHOD__ );
|
||||
$this->output( "done.\nReassigning deleted edits..." );
|
||||
$res = $dbw->update( 'archive', userSpecification( $to, 'ar_user', 'ar_user_text' ), $this->userConditions( $from, 'ar_user', 'ar_user_text' ), __METHOD__ );
|
||||
$this->output( "done.\n" );
|
||||
# Update recent changes if required
|
||||
if( $rc ) {
|
||||
$this->output( "Updating recent changes..." );
|
||||
$res = $dbw->update( 'recentchanges', $this->userSpecification( $to, 'rc_user', 'rc_user_text' ), $this->userConditions( $from, 'rc_user', 'rc_user_text' ), __METHOD__ );
|
||||
$this->output( "done.\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$dbw->immediateCommit();
|
||||
return (int)$total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the most efficient set of user conditions
|
||||
* i.e. a user => id mapping, or a user_text => text mapping
|
||||
*
|
||||
* @param $user User for the condition
|
||||
* @param $idfield Field name containing the identifier
|
||||
* @param $utfield Field name containing the user text
|
||||
* @return array
|
||||
*/
|
||||
private function userConditions( &$user, $idfield, $utfield ) {
|
||||
return $user->getId() ? array( $idfield => $user->getId() ) : array( $utfield => $user->getName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return user specifications
|
||||
* i.e. user => id, user_text => text
|
||||
*
|
||||
* @param $user User for the spec
|
||||
* @param $idfield Field name containing the identifier
|
||||
* @param $utfield Field name containing the user text
|
||||
* @return array
|
||||
*/
|
||||
private function userSpecification( &$user, $idfield, $utfield ) {
|
||||
return array( $idfield => $user->getId(), $utfield => $user->getName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the user object
|
||||
*
|
||||
* @param $username Username or IP address
|
||||
* @return User
|
||||
*/
|
||||
private function initialiseUser( $username ) {
|
||||
if( User::isIP( $username ) ) {
|
||||
$user = new User();
|
||||
$user->setId( 0 );
|
||||
$user->setName( $username );
|
||||
} else {
|
||||
$user = User::newFromName( $username );
|
||||
}
|
||||
$user->load();
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
ShowUsage();
|
||||
}
|
||||
|
||||
$maintClass = "ReassignEdits";
|
||||
require_once( DO_MAINTENANCE );
|
||||
/** Show script usage information */
|
||||
function ShowUsage() {
|
||||
echo( "Reassign edits from one user to another.\n\n" );
|
||||
echo( "Usage: php reassignEdits.php [--force|--quiet|--norc|--report] <from> <to>\n\n" );
|
||||
echo( " <from> : Name of the user to assign edits from\n" );
|
||||
echo( " <to> : Name of the user to assign edits to\n" );
|
||||
echo( " --force : Reassign even if the target user doesn't exist\n" );
|
||||
echo( " --quiet : Don't print status information (except for errors)\n" );
|
||||
echo( " --norc : Don't update the recent changes table\n" );
|
||||
echo( " --report : Print out details of what would be changed, but don't update it\n\n" );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,96 +6,87 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class RebuildFileCache extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Build file cache for content pages";
|
||||
$this->addArgs( array( 'start', 'overwrite' ) );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgUseFileCache, $wgDisableCounters, $wgTitle, $wgArticle, $wgOut;
|
||||
if( !$wgUseFileCache ) {
|
||||
$this->error( "Nothing to do -- \$wgUseFileCache is disabled.\n", true );
|
||||
}
|
||||
$wgDisableCounters = false;
|
||||
$start = intval( $this->getArg( 0, 0 ) );
|
||||
$overwrite = $this->hasArg(1) && $this->getArg(1) === 'overwrite';
|
||||
$this->output( "Building content page file cache from page {$start}!\n" );
|
||||
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$start = $start > 0 ? $start : $dbr->selectField( 'page', 'MIN(page_id)', false, __FUNCTION__ );
|
||||
$end = $dbr->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ );
|
||||
if( !$start ) {
|
||||
$this->error( "Nothing to do.\n", true );
|
||||
}
|
||||
|
||||
$_SERVER['HTTP_ACCEPT_ENCODING'] = 'bgzip'; // hack, no real client
|
||||
OutputPage::setEncodings(); # Not really used yet
|
||||
|
||||
$BATCH_SIZE = 100;
|
||||
# Do remaining chunk
|
||||
$end += $BATCH_SIZE - 1;
|
||||
$blockStart = $start;
|
||||
$blockEnd = $start + $BATCH_SIZE - 1;
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
// Go through each page and save the output
|
||||
while( $blockEnd <= $end ) {
|
||||
// Get the pages
|
||||
$res = $dbr->select( 'page', array('page_namespace','page_title','page_id'),
|
||||
array('page_namespace' => $wgContentNamespaces,
|
||||
"page_id BETWEEN $blockStart AND $blockEnd" ),
|
||||
array('ORDER BY' => 'page_id ASC','USE INDEX' => 'PRIMARY')
|
||||
);
|
||||
while( $row = $dbr->fetchObject( $res ) ) {
|
||||
$rebuilt = false;
|
||||
$wgTitle = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
|
||||
if( null == $wgTitle ) {
|
||||
$this->output( "Page {$row->page_id} bad title\n" );
|
||||
continue; // broken title?
|
||||
}
|
||||
$wgArticle = new Article( $wgTitle );
|
||||
// If the article is cacheable, then load it
|
||||
if( $wgArticle->isFileCacheable() ) {
|
||||
$cache = new HTMLFileCache( $wgTitle );
|
||||
if( $cache->isFileCacheGood() ) {
|
||||
if( $overwrite ) {
|
||||
$rebuilt = true;
|
||||
} else {
|
||||
$this->output( "Page {$row->page_id} already cached\n" );
|
||||
continue; // done already!
|
||||
}
|
||||
}
|
||||
ob_start( array(&$cache, 'saveToFileCache' ) ); // save on ob_end_clean()
|
||||
$wgUseFileCache = false; // hack, we don't want $wgArticle fiddling with filecache
|
||||
$wgArticle->view();
|
||||
@$wgOut->output(); // header notices
|
||||
$wgUseFileCache = true;
|
||||
ob_end_clean(); // clear buffer
|
||||
$wgOut = new OutputPage(); // empty out any output page garbage
|
||||
if( $rebuilt )
|
||||
$this->output( "Re-cached page {$row->page_id}\n" );
|
||||
else
|
||||
$this->output( "Cached page {$row->page_id}\n" );
|
||||
} else {
|
||||
$this->output( "Page {$row->page_id} not cacheable\n" );
|
||||
}
|
||||
$dbw->commit(); // commit any changes
|
||||
}
|
||||
$blockStart += $BATCH_SIZE;
|
||||
$blockEnd += $BATCH_SIZE;
|
||||
wfWaitForSlaves( 5 );
|
||||
}
|
||||
$this->output( "Done!\n" );
|
||||
|
||||
// Remove these to be safe
|
||||
if( isset($wgTitle) )
|
||||
unset($wgTitle);
|
||||
if( isset($wgArticle) )
|
||||
unset($wgArticle);
|
||||
}
|
||||
}
|
||||
/** */
|
||||
require_once( "commandLine.inc" );
|
||||
if( !$wgUseFileCache ) {
|
||||
echo "Nothing to do -- \$wgUseFileCache is disabled.\n";
|
||||
exit(0);
|
||||
}
|
||||
$wgDisableCounters = false; // no real hits here
|
||||
|
||||
$start = isset($args[0]) ? intval($args[0]) : 0;
|
||||
$overwrite = isset( $args[1] ) && $args[1] === 'overwrite';
|
||||
echo "Building content page file cache from page {$start}!\n";
|
||||
echo "Format: <start> [overwrite]\n";
|
||||
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$start = $start > 0 ? $start : $dbr->selectField( 'page', 'MIN(page_id)', false, __FUNCTION__ );
|
||||
$end = $dbr->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ );
|
||||
if( !$start ) {
|
||||
die("Nothing to do.\n");
|
||||
}
|
||||
|
||||
$_SERVER['HTTP_ACCEPT_ENCODING'] = 'bgzip'; // hack, no real client
|
||||
OutputPage::setEncodings(); # Not really used yet
|
||||
|
||||
$BATCH_SIZE = 100;
|
||||
# Do remaining chunk
|
||||
$end += $BATCH_SIZE - 1;
|
||||
$blockStart = $start;
|
||||
$blockEnd = $start + $BATCH_SIZE - 1;
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
// Go through each page and save the output
|
||||
while( $blockEnd <= $end ) {
|
||||
// Get the pages
|
||||
$res = $dbr->select( 'page', array('page_namespace','page_title','page_id'),
|
||||
array('page_namespace' => $wgContentNamespaces,
|
||||
"page_id BETWEEN $blockStart AND $blockEnd" ),
|
||||
array('ORDER BY' => 'page_id ASC','USE INDEX' => 'PRIMARY')
|
||||
);
|
||||
while( $row = $dbr->fetchObject( $res ) ) {
|
||||
$rebuilt = false;
|
||||
$wgTitle = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
|
||||
if( null == $wgTitle ) {
|
||||
echo "Page {$row->page_id} bad title\n";
|
||||
continue; // broken title?
|
||||
}
|
||||
$wgArticle = new Article( $wgTitle );
|
||||
// If the article is cacheable, then load it
|
||||
if( $wgArticle->isFileCacheable() ) {
|
||||
$cache = new HTMLFileCache( $wgTitle );
|
||||
if( $cache->isFileCacheGood() ) {
|
||||
if( $overwrite ) {
|
||||
$rebuilt = true;
|
||||
} else {
|
||||
echo "Page {$row->page_id} already cached\n";
|
||||
continue; // done already!
|
||||
}
|
||||
}
|
||||
ob_start( array(&$cache, 'saveToFileCache' ) ); // save on ob_end_clean()
|
||||
$wgUseFileCache = false; // hack, we don't want $wgArticle fiddling with filecache
|
||||
$wgArticle->view();
|
||||
@$wgOut->output(); // header notices
|
||||
$wgUseFileCache = true;
|
||||
ob_end_clean(); // clear buffer
|
||||
$wgOut = new OutputPage(); // empty out any output page garbage
|
||||
if( $rebuilt )
|
||||
echo "Re-cached page {$row->page_id}\n";
|
||||
else
|
||||
echo "Cached page {$row->page_id}\n";
|
||||
} else {
|
||||
echo "Page {$row->page_id} not cacheable\n";
|
||||
}
|
||||
$dbw->commit(); // commit any changes
|
||||
}
|
||||
$blockStart += $BATCH_SIZE;
|
||||
$blockEnd += $BATCH_SIZE;
|
||||
wfWaitForSlaves( 5 );
|
||||
}
|
||||
echo "Done!\n";
|
||||
|
||||
// Remove these to be safe
|
||||
if( isset($wgTitle) )
|
||||
unset($wgTitle);
|
||||
if( isset($wgArticle) )
|
||||
unset($wgArticle);
|
||||
|
|
|
|||
|
|
@ -7,34 +7,23 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
require_once( "commandLine.inc" );
|
||||
|
||||
class RefreshImageCount extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Resets ss_image count, forcing slaves to pick it up.";
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
// Load the current value from the master
|
||||
$count = $dbw->selectField( 'site_stats', 'ss_images' );
|
||||
// Load the current value from the master
|
||||
$count = $dbw->selectField( 'site_stats', 'ss_images' );
|
||||
|
||||
$this->output( wfWikiID() . ": forcing ss_images to $count\n" );
|
||||
echo wfWikiID().": forcing ss_images to $count\n";
|
||||
|
||||
// First set to NULL so that it changes on the master
|
||||
$dbw->update( 'site_stats',
|
||||
array( 'ss_images' => null ),
|
||||
array( 'ss_row_id' => 1 ) );
|
||||
|
||||
// Now this update will be forced to go out
|
||||
$dbw->update( 'site_stats',
|
||||
array( 'ss_images' => $count ),
|
||||
array( 'ss_row_id' => 1 ) );
|
||||
}
|
||||
}
|
||||
// First set to NULL so that it changes on the master
|
||||
$dbw->update( 'site_stats',
|
||||
array( 'ss_images' => null ),
|
||||
array( 'ss_row_id' => 1 ) );
|
||||
|
||||
// Now this update will be forced to go out
|
||||
$dbw->update( 'site_stats',
|
||||
array( 'ss_images' => $count ),
|
||||
array( 'ss_row_id' => 1 ) );
|
||||
|
||||
$maintClass = "RefreshImageCount";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
||||
|
|
|
|||
|
|
@ -8,89 +8,63 @@
|
|||
* @author Rob Church <robchur@gmail.com>
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$options = array( 'help', 'delete' );
|
||||
require_once( 'commandLine.inc' );
|
||||
require_once( 'removeUnusedAccounts.inc' );
|
||||
echo( "Remove Unused Accounts\n\n" );
|
||||
$fname = 'removeUnusedAccounts';
|
||||
|
||||
class RemoveUnusedAccounts extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->addParam( 'delete', 'Actually delete the account' );
|
||||
$this->addParam( 'ignore-groups', 'List of comma-separated groups to exclude', false, true );
|
||||
$this->addParam( 'ignore-touched', 'Skip accounts touched in last N days', false, true );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
|
||||
$this->output( "Remove unused accounts\n\n" );
|
||||
|
||||
# Do an initial scan for inactive accounts and report the result
|
||||
$this->output( "Checking for unused user accounts...\n" );
|
||||
$del = array();
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$res = $dbr->select( 'user', array( 'user_id', 'user_name', 'user_touched' ), '', __METHOD__ );
|
||||
if( $this->hasOption('ignore-groups') ) {
|
||||
$excludedGroups = explode( ',', $this->getOption('ignore-groups') );
|
||||
} else {
|
||||
$excludedGroups = array();
|
||||
}
|
||||
$touched = $this->getOption( 'ignore-touched', "1" );
|
||||
if( !ctype_digit( $touched ) ) {
|
||||
$this->error( "Please put a valid positive integer on the --ignore-touched parameter.\n", true );
|
||||
}
|
||||
$touchedSeconds = 86400 * $touched;
|
||||
while( $row = $dbr->fetchObject( $res ) ) {
|
||||
# Check the account, but ignore it if it's within a $excludedGroups group or if it's touched within the $touchedSeconds seconds.
|
||||
$instance = User::newFromId( $row->user_id );
|
||||
if( count( array_intersect( $instance->getEffectiveGroups(), $excludedGroups ) ) == 0
|
||||
&& $this->isInactiveAccount( $row->user_id, true )
|
||||
&& wfTimestamp( TS_UNIX, $row->user_touched ) < wfTimestamp( TS_UNIX, time() - $touchedSeconds )
|
||||
) {
|
||||
# Inactive; print out the name and flag it
|
||||
$del[] = $row->user_id;
|
||||
$this->output( $row->user_name . "\n" );
|
||||
}
|
||||
}
|
||||
$count = count( $del );
|
||||
$this->output( "...found {$count}.\n" );
|
||||
|
||||
# If required, go back and delete each marked account
|
||||
if( $count > 0 && $this->hasOption('delete') ) {
|
||||
$this->output( "\nDeleting inactive accounts..." );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->delete( 'user', array( 'user_id' => $del ), __METHOD__ );
|
||||
$this->output( "done.\n" );
|
||||
# Update the site_stats.ss_users field
|
||||
$users = $dbw->selectField( 'user', 'COUNT(*)', array(), __METHOD__ );
|
||||
$dbw->update( 'site_stats', array( 'ss_users' => $users ), array( 'ss_row_id' => 1 ), __METHOD__ );
|
||||
} elseif( $count > 0 ) {
|
||||
$this->output( "\nRun the script again with --delete to remove them from the database.\n" );
|
||||
}
|
||||
$this->output( "\n" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Could the specified user account be deemed inactive?
|
||||
* (No edits, no deleted edits, no log entries, no current/old uploads)
|
||||
*
|
||||
* @param $id User's ID
|
||||
* @param $master Perform checking on the master
|
||||
* @return bool
|
||||
*/
|
||||
private function isInactiveAccount( $id, $master = false ) {
|
||||
$dbo = wfGetDB( $master ? DB_MASTER : DB_SLAVE );
|
||||
$checks = array( 'revision' => 'rev', 'archive' => 'ar', 'logging' => 'log',
|
||||
'image' => 'img', 'oldimage' => 'oi' );
|
||||
$count = 0;
|
||||
|
||||
$dbo->immediateBegin();
|
||||
foreach( $checks as $table => $fprefix ) {
|
||||
$conds = array( $fprefix . '_user' => $id );
|
||||
$count += (int)$dbo->selectField( $table, 'COUNT(*)', $conds, __METHOD__ );
|
||||
}
|
||||
$dbo->immediateCommit();
|
||||
|
||||
return $count == 0;
|
||||
}
|
||||
if( isset( $options['help'] ) ) {
|
||||
showHelp();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$maintClass = "RemoveUnusedAccounts";
|
||||
require_once( DO_MAINTENANCE );
|
||||
# Do an initial scan for inactive accounts and report the result
|
||||
echo( "Checking for unused user accounts...\n" );
|
||||
$del = array();
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$res = $dbr->select( 'user', array( 'user_id', 'user_name', 'user_touched' ), '', $fname );
|
||||
if( isset( $options['ignore-groups'] ) ) {
|
||||
$excludedGroups = explode( ',', $options['ignore-groups'] );
|
||||
} else { $excludedGroups = array(); }
|
||||
$touchedSeconds = 0;
|
||||
if( isset( $options['ignore-touched'] ) ) {
|
||||
$touchedParamError = 0;
|
||||
if( ctype_digit( $options['ignore-touched'] ) ) {
|
||||
if( $options['ignore-touched'] <= 0 ) {
|
||||
$touchedParamError = 1;
|
||||
}
|
||||
} else { $touchedParamError = 1; }
|
||||
if( $touchedParamError == 1 ) {
|
||||
die( "Please put a valid positive integer on the --ignore-touched parameter.\n" );
|
||||
} else { $touchedSeconds = 86400 * $options['ignore-touched']; }
|
||||
}
|
||||
while( $row = $dbr->fetchObject( $res ) ) {
|
||||
# Check the account, but ignore it if it's within a $excludedGroups group or if it's touched within the $touchedSeconds seconds.
|
||||
$instance = User::newFromId( $row->user_id );
|
||||
if( count( array_intersect( $instance->getEffectiveGroups(), $excludedGroups ) ) == 0
|
||||
&& isInactiveAccount( $row->user_id, true )
|
||||
&& wfTimestamp( TS_UNIX, $row->user_touched ) < wfTimestamp( TS_UNIX, time() - $touchedSeconds )
|
||||
) {
|
||||
# Inactive; print out the name and flag it
|
||||
$del[] = $row->user_id;
|
||||
echo( $row->user_name . "\n" );
|
||||
}
|
||||
}
|
||||
$count = count( $del );
|
||||
echo( "...found {$count}.\n" );
|
||||
|
||||
# If required, go back and delete each marked account
|
||||
if( $count > 0 && isset( $options['delete'] ) ) {
|
||||
echo( "\nDeleting inactive accounts..." );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->delete( 'user', array( 'user_id' => $del ), $fname );
|
||||
echo( "done.\n" );
|
||||
# Update the site_stats.ss_users field
|
||||
$users = $dbw->selectField( 'user', 'COUNT(*)', array(), $fname );
|
||||
$dbw->update( 'site_stats', array( 'ss_users' => $users ), array( 'ss_row_id' => 1 ), $fname );
|
||||
} else {
|
||||
if( $count > 0 )
|
||||
echo( "\nRun the script again with --delete to remove them from the database.\n" );
|
||||
}
|
||||
echo( "\n" );
|
||||
|
|
|
|||
|
|
@ -6,59 +6,62 @@
|
|||
* @file
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$optionsWithArgs = array( 'old', 'new', 'help' );
|
||||
|
||||
class RenameDbPrefix extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->addParam( "old", "Old db prefix [0 for none]", true, true );
|
||||
$this->addParam( "new", "New db prefix [0 for none]", true, true );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
// Allow for no old prefix
|
||||
if( $this->getOption( 'old', 0 ) === '0' ) {
|
||||
$old = '';
|
||||
} else {
|
||||
// Use nice safe, sane, prefixes
|
||||
preg_match( '/^[a-zA-Z]+_$/', $this->getOption('old'), $m );
|
||||
$old = isset( $m[0] ) ? $m[0] : false;
|
||||
}
|
||||
// Allow for no new prefix
|
||||
if( $this->getOption( 'new', 0 ) === '0' ) {
|
||||
$new = '';
|
||||
} else {
|
||||
// Use nice safe, sane, prefixes
|
||||
preg_match( '/^[a-zA-Z]+_$/', $this->getOption('new'), $m );
|
||||
$new = isset( $m[0] ) ? $m[0] : false;
|
||||
}
|
||||
|
||||
if( $old === false || $new === false ) {
|
||||
$this->error( "Invalid prefix!\n", true );
|
||||
}
|
||||
if( $old === $new ) {
|
||||
$this->( "Same prefix. Nothing to rename!\n", true );
|
||||
}
|
||||
|
||||
$this->output( "Renaming DB prefix for tables of $wgDBname from '$old' to '$new'\n" );
|
||||
$count = 0;
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$res = $dbw->query( "SHOW TABLES LIKE '".$dbw->escapeLike( $old )."%'" );
|
||||
foreach( $res as $row ) {
|
||||
// XXX: odd syntax. MySQL outputs an oddly cased "Tables of X"
|
||||
// sort of message. Best not to try $row->x stuff...
|
||||
$fields = get_object_vars( $row );
|
||||
// Silly for loop over one field...
|
||||
foreach( $fields as $resName => $table ) {
|
||||
// $old should be regexp safe ([a-zA-Z_])
|
||||
$newTable = preg_replace( '/^'.$old.'/', $new, $table );
|
||||
$this->output( "Renaming table $table to $newTable\n" );
|
||||
$dbw->query( "RENAME TABLE $table TO $newTable" );
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
$this->output( "Done! [$count tables]\n" );
|
||||
}
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
if( @$options['help'] || !isset( $options['old'] ) || !isset( $options['new'] ) ) {
|
||||
print "usage: renameDbPrefix.php [--help] [--old x] [new y]\n";
|
||||
print " --help : this help message\n";
|
||||
print " --old x : old db prefix x\n";
|
||||
print " --old 0 : EMPTY old db prefix x\n";
|
||||
print " --new y : new db prefix y\n";
|
||||
print " --new 0 : EMPTY new db prefix\n";
|
||||
wfDie();
|
||||
}
|
||||
|
||||
// Allow for no old prefix
|
||||
if( $options['old'] === '0' ) {
|
||||
$old = '';
|
||||
} else {
|
||||
// Use nice safe, sane, prefixes
|
||||
preg_match( '/^[a-zA-Z]+_$/', $options['old'], $m );
|
||||
$old = isset( $m[0] ) ? $m[0] : false;
|
||||
}
|
||||
// Allow for no new prefix
|
||||
if( $options['new'] === '0' ) {
|
||||
$new = '';
|
||||
} else {
|
||||
// Use nice safe, sane, prefixes
|
||||
preg_match( '/^[a-zA-Z]+_$/', $options['new'], $m );
|
||||
$new = isset( $m[0] ) ? $m[0] : false;
|
||||
}
|
||||
|
||||
if( $old === false || $new === false ) {
|
||||
print "Invalid prefix!\n";
|
||||
wfDie();
|
||||
}
|
||||
if( $old === $new ) {
|
||||
print "Same prefix. Nothing to rename!\n";
|
||||
wfDie();
|
||||
}
|
||||
|
||||
print "Renaming DB prefix for tables of $wgDBname from '$old' to '$new'\n";
|
||||
$count = 0;
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$res = $dbw->query( "SHOW TABLES LIKE '".$dbw->escapeLike( $old )."%'" );
|
||||
foreach( $res as $row ) {
|
||||
// XXX: odd syntax. MySQL outputs an oddly cased "Tables of X"
|
||||
// sort of message. Best not to try $row->x stuff...
|
||||
$fields = get_object_vars( $row );
|
||||
// Silly for loop over one field...
|
||||
foreach( $fields as $resName => $table ) {
|
||||
// $old should be regexp safe ([a-zA-Z_])
|
||||
$newTable = preg_replace( '/^'.$old.'/', $new, $table );
|
||||
print "Renaming table $table to $newTable\n";
|
||||
$dbw->query( "RENAME TABLE $table TO $newTable" );
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
print "Done! [$count tables]\n";
|
||||
|
|
@ -27,61 +27,42 @@
|
|||
* @file
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class DumpRenderer extends Maintenance {
|
||||
$optionsWithArgs = array( 'report' );
|
||||
|
||||
private $count = 0;
|
||||
private $outputDirectory, $startTime;
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Take page text out of an XML dump file and render basic HTML out to files";
|
||||
$this->addParam( 'output-dir', 'The directory to output the HTML files to', true, true );
|
||||
class DumpRenderer {
|
||||
function __construct( $dir ) {
|
||||
$this->stderr = fopen( "php://stderr", "wt" );
|
||||
$this->outputDirectory = $dir;
|
||||
$this->count = 0;
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$this->outputDirectory = $this->getOption( 'output-dir' );
|
||||
$this->startTime = wfTime();
|
||||
|
||||
$source = new ImportStreamSource( $this->getStdin() );
|
||||
$importer = new WikiImporter( $source );
|
||||
|
||||
$importer->setRevisionCallback(
|
||||
array( &$this, 'handleRevision' ) );
|
||||
|
||||
return $importer->doImport();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for each revision, turn into HTML and save
|
||||
* @param $rev Revision
|
||||
*/
|
||||
private function handleRevision( $rev ) {
|
||||
function handleRevision( $rev ) {
|
||||
$title = $rev->getTitle();
|
||||
if (!$title) {
|
||||
$this->error( "Got bogus revision with null title!" );
|
||||
fprintf( $this->stderr, "Got bogus revision with null title!" );
|
||||
return;
|
||||
}
|
||||
$display = $title->getPrefixedText();
|
||||
|
||||
|
||||
$this->count++;
|
||||
|
||||
|
||||
$sanitized = rawurlencode( $display );
|
||||
$filename = sprintf( "%s/wiki-%07d-%s.html",
|
||||
$this->outputDirectory,
|
||||
$this->count,
|
||||
$sanitized );
|
||||
$this->output( sprintf( $this->stderr, "%s\n", $filename, $display ) );
|
||||
|
||||
// fixme (what?)
|
||||
fprintf( $this->stderr, "%s\n", $filename, $display );
|
||||
|
||||
// fixme
|
||||
$user = new User();
|
||||
$parser = new Parser();
|
||||
$options = ParserOptions::newFromUser( $user );
|
||||
|
||||
|
||||
$output = $parser->parse( $rev->getText(), $title, $options );
|
||||
|
||||
|
||||
file_put_contents( $filename,
|
||||
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" " .
|
||||
"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" .
|
||||
|
|
@ -95,7 +76,27 @@ class DumpRenderer extends Maintenance {
|
|||
"</body>\n" .
|
||||
"</html>" );
|
||||
}
|
||||
|
||||
function run() {
|
||||
$this->startTime = wfTime();
|
||||
|
||||
$file = fopen( 'php://stdin', 'rt' );
|
||||
$source = new ImportStreamSource( $file );
|
||||
$importer = new WikiImporter( $source );
|
||||
|
||||
$importer->setRevisionCallback(
|
||||
array( &$this, 'handleRevision' ) );
|
||||
|
||||
return $importer->doImport();
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "DumpRenderer";
|
||||
require_once( DO_MAINTENANCE );
|
||||
if( isset( $options['output-dir'] ) ) {
|
||||
$dir = $options['output-dir'];
|
||||
} else {
|
||||
wfDie( "Must use --output-dir=/some/dir\n" );
|
||||
}
|
||||
$render = new DumpRenderer( $dir );
|
||||
$render->run();
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,77 +10,71 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$optionsWithArgs = array( 'maxjobs', 'type', 'procs' );
|
||||
$wgUseNormalUser = true;
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
class RunJobs extends Maintenance {
|
||||
public function __construct() {
|
||||
global $wgUseNormalUser;
|
||||
parent::__construct();
|
||||
$this->mDescription = "Run pending jobs";
|
||||
$this->addParam( 'maxjobs', 'Maximum number of jobs to run', false, true );
|
||||
$this->addParam( 'type', 'Type of job to run', false, true );
|
||||
$this->addParam( 'procs', 'Number of processes to use', false, true );
|
||||
$wgUseNormalUser = true;
|
||||
if ( isset( $options['procs'] ) ) {
|
||||
$procs = intval( $options['procs'] );
|
||||
if ( $procs < 1 || $procs > 1000 ) {
|
||||
echo "Invalid argument to --procs\n";
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgTitle;
|
||||
if ( $this->hasOption( 'procs' ) ) {
|
||||
$procs = intval( $this->getOption('procs') );
|
||||
if ( $procs < 1 || $procs > 1000 ) {
|
||||
$this->error( "Invalid argument to --procs\n", true );
|
||||
}
|
||||
$fc = new ForkController( $procs );
|
||||
if ( $fc->start( $procs ) != 'child' ) {
|
||||
exit( 0 );
|
||||
}
|
||||
}
|
||||
$maxJobs = $this->getOption( 'maxjobs', 10000 );
|
||||
$type = $this->getOption( 'type', false );
|
||||
$wgTitle = Title::newFromText( 'RunJobs.php' );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$n = 0;
|
||||
$conds = '';
|
||||
if ($type !== false)
|
||||
$conds = "job_cmd = " . $dbw->addQuotes($type);
|
||||
|
||||
while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) {
|
||||
$offset=0;
|
||||
for (;;) {
|
||||
$job = ($type == false) ?
|
||||
Job::pop($offset)
|
||||
: Job::pop_type($type);
|
||||
|
||||
if ($job == false)
|
||||
break;
|
||||
|
||||
wfWaitForSlaves( 5 );
|
||||
$t = microtime( true );
|
||||
$offset=$job->id;
|
||||
$status = $job->run();
|
||||
$t = microtime( true ) - $t;
|
||||
$timeMs = intval( $t * 1000 );
|
||||
if ( !$status ) {
|
||||
$this->runJobsLog( $job->toString() . " t=$timeMs error={$job->error}" );
|
||||
} else {
|
||||
$this->runJobsLog( $job->toString() . " t=$timeMs good" );
|
||||
}
|
||||
if ( $maxJobs && ++$n > $maxJobs ) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the job message
|
||||
* @param $msg String The message to log
|
||||
*/
|
||||
private function runJobsLog( $msg ) {
|
||||
$this->output( wfTimestamp( TS_DB ) . " $msg\n" );
|
||||
wfDebugLog( 'runJobs', $msg );
|
||||
$fc = new ForkController( $procs );
|
||||
if ( $fc->start( $procs ) != 'child' ) {
|
||||
exit( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "RunJobs";
|
||||
require_once( DO_MAINTENANCE );
|
||||
if ( isset( $options['maxjobs'] ) ) {
|
||||
$maxJobs = $options['maxjobs'];
|
||||
} else {
|
||||
$maxJobs = 10000;
|
||||
}
|
||||
|
||||
$type = false;
|
||||
if ( isset( $options['type'] ) )
|
||||
$type = $options['type'];
|
||||
|
||||
$wgTitle = Title::newFromText( 'RunJobs.php' );
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$n = 0;
|
||||
$conds = '';
|
||||
if ($type !== false)
|
||||
$conds = "job_cmd = " . $dbw->addQuotes($type);
|
||||
|
||||
while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) {
|
||||
$offset=0;
|
||||
for (;;) {
|
||||
$job = ($type == false) ?
|
||||
Job::pop($offset)
|
||||
: Job::pop_type($type);
|
||||
|
||||
if ($job == false)
|
||||
break;
|
||||
|
||||
wfWaitForSlaves( 5 );
|
||||
$t = microtime( true );
|
||||
$offset=$job->id;
|
||||
$status = $job->run();
|
||||
$t = microtime( true ) - $t;
|
||||
$timeMs = intval( $t * 1000 );
|
||||
if ( !$status ) {
|
||||
runJobsLog( $job->toString() . " t=$timeMs error={$job->error}" );
|
||||
} else {
|
||||
runJobsLog( $job->toString() . " t=$timeMs good" );
|
||||
}
|
||||
if ( $maxJobs && ++$n > $maxJobs ) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function runJobsLog( $msg ) {
|
||||
print wfTimestamp( TS_DB ) . " $msg\n";
|
||||
wfDebugLog( 'runJobs', $msg );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,19 +9,10 @@
|
|||
* @author Tim Starling
|
||||
* @author Ashar Voultoiz
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$count = $dbw->selectField( 'job', 'count(*)', '', 'runJobs.php' );
|
||||
print $count."\n";
|
||||
|
||||
class ShowJobs extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Show number of jobs waiting in master database";
|
||||
}
|
||||
public function execute() {
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$this->output( $dbw->selectField( 'job', 'count(*)', '', 'runJobs.php' ) . "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "ShowJobs";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
|
|
|||
|
|
@ -14,41 +14,35 @@
|
|||
* @license GNU General Public License 2.0 or later
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
class ShowStats extends Maintenance {
|
||||
public function __construct() {
|
||||
$this->mDescription = "Show the cached statistics";
|
||||
}
|
||||
public function execute() {
|
||||
$fields = array(
|
||||
'ss_total_views' => 'Total views',
|
||||
'ss_total_edits' => 'Total edits',
|
||||
'ss_good_articles' => 'Number of articles',
|
||||
'ss_total_pages' => 'Total pages',
|
||||
'ss_users' => 'Number of users',
|
||||
'ss_admins' => 'Number of admins',
|
||||
'ss_images' => 'Number of images',
|
||||
);
|
||||
|
||||
// Get cached stats from slave database
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$stats = $dbr->selectRow( 'site_stats', '*', '', __METHOD__ );
|
||||
|
||||
// Get maximum size for each column
|
||||
$max_length_value = $max_length_desc = 0;
|
||||
foreach( $fields as $field => $desc ) {
|
||||
$max_length_value = max( $max_length_value, strlen( $stats->$field ) );
|
||||
$max_length_desc = max( $max_length_desc , strlen( $desc )) ;
|
||||
}
|
||||
|
||||
// Show them
|
||||
foreach( $fields as $field => $desc ) {
|
||||
$this->output( sprintf( "%-{$max_length_desc}s: %{$max_length_value}d\n", $desc, $stats->$field ) );
|
||||
}
|
||||
}
|
||||
#
|
||||
# Configuration
|
||||
#
|
||||
$fields = array(
|
||||
'ss_total_views' => 'Total views',
|
||||
'ss_total_edits' => 'Total edits',
|
||||
'ss_good_articles' => 'Number of articles',
|
||||
'ss_total_pages' => 'Total pages',
|
||||
'ss_users' => 'Number of users',
|
||||
'ss_admins' => 'Number of admins',
|
||||
'ss_images' => 'Number of images',
|
||||
);
|
||||
|
||||
// Get cached stats from slave database
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$fname = 'showStats';
|
||||
$stats = $dbr->selectRow( 'site_stats', '*', '' );
|
||||
|
||||
// Get maximum size for each column
|
||||
$max_length_value = $max_length_desc = 0;
|
||||
foreach( $fields as $field => $desc ) {
|
||||
$max_length_value = max( $max_length_value, strlen( $stats->$field ) );
|
||||
$max_length_desc = max( $max_length_desc , strlen( $desc )) ;
|
||||
}
|
||||
|
||||
$maintClass = "ShowStats";
|
||||
require_once( DO_MAINTENANCE );
|
||||
// Show them
|
||||
foreach( $fields as $field => $desc ) {
|
||||
printf( "%-{$max_length_desc}s: %{$max_length_value}d\n", $desc, $stats->$field );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,56 +7,38 @@
|
|||
* @ingroup Database Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
require_once( dirname(__FILE__) . '/' . 'commandLine.inc' );
|
||||
|
||||
class MwSql extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Send SQL queries to a MediaWiki database";
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
if ( $this->hasArg() ) {
|
||||
$fileName = $this->getArg();
|
||||
$file = fopen( $fileName, 'r' );
|
||||
$promptCallback = false;
|
||||
} else {
|
||||
$file = $this->getStdin();
|
||||
$promptObject = new SqlPromptPrinter( "> " );
|
||||
$promptCallback = $promptObject->cb();
|
||||
}
|
||||
|
||||
if ( !$file )
|
||||
$this->error( "Unable to open input file\n", true );
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$error = $dbw->sourceStream( $file, $promptCallback, array( $this, 'sqlPrintResult' ) );
|
||||
if ( $error !== true ) {
|
||||
$this->error( $error, true );
|
||||
} else {
|
||||
exit( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the results, callback for $db->sourceStream()
|
||||
* @param $res The results object
|
||||
* @param $db Database object
|
||||
*/
|
||||
public function sqlPrintResult( $res, $db ) {
|
||||
if ( !$res ) {
|
||||
// Do nothing
|
||||
} elseif ( is_object( $res ) && $res->numRows() ) {
|
||||
while ( $row = $res->fetchObject() ) {
|
||||
$this->output( print_r( $row, true ) );
|
||||
}
|
||||
} else {
|
||||
$affected = $db->affectedRows();
|
||||
$this->output( "Query OK, $affected row(s) affected\n" );
|
||||
}
|
||||
}
|
||||
if ( isset( $options['help'] ) ) {
|
||||
echo "Send SQL queries to a MediaWiki database.\nUsage: php sql.php [<file>]\n";
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
if ( isset( $args[0] ) ) {
|
||||
$fileName = $args[0];
|
||||
$file = fopen( $fileName, 'r' );
|
||||
$promptCallback = false;
|
||||
} else {
|
||||
$file = STDIN;
|
||||
$promptObject = new SqlPromptPrinter( "> " );
|
||||
$promptCallback = $promptObject->cb();
|
||||
}
|
||||
|
||||
if ( !$file ) {
|
||||
echo "Unable to open input file\n";
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
$dbw =& wfGetDB( DB_MASTER );
|
||||
$error = $dbw->sourceStream( $file, $promptCallback, 'sqlPrintResult' );
|
||||
if ( $error !== true ) {
|
||||
echo $error;
|
||||
exit( 1 );
|
||||
} else {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class SqlPromptPrinter {
|
||||
function __construct( $prompt ) {
|
||||
$this->prompt = $prompt;
|
||||
|
|
@ -71,5 +53,17 @@ class SqlPromptPrinter {
|
|||
}
|
||||
}
|
||||
|
||||
$maintClass = "MwSql";
|
||||
require_once( DO_MAINTENANCE );
|
||||
function sqlPrintResult( $res, $db ) {
|
||||
if ( !$res ) {
|
||||
// Do nothing
|
||||
} elseif ( is_object( $res ) && $res->numRows() ) {
|
||||
while ( $row = $res->fetchObject() ) {
|
||||
print_r( $row );
|
||||
}
|
||||
} else {
|
||||
$affected = $db->affectedRows();
|
||||
echo "Query OK, $affected row(s) affected\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,73 +1,58 @@
|
|||
<?php
|
||||
/**
|
||||
* Show statistics from memcached
|
||||
*
|
||||
* @file
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
require_once('commandLine.inc');
|
||||
|
||||
class MemcachedStats extends Maintenance {
|
||||
|
||||
public function __construct() {
|
||||
$this->mDescription = "Show statistics from memcached";
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgMemc;
|
||||
|
||||
// Can't do stats if
|
||||
if( get_class( $wgMemc ) == 'FakeMemCachedClient' ) {
|
||||
$this->error( "You are running FakeMemCachedClient, I can not provide any statistics.\n", true );
|
||||
}
|
||||
$session = intval($wgMemc->get(wfMemcKey('stats','request_with_session')));
|
||||
$noSession = intval($wgMemc->get(wfMemcKey('stats','request_without_session')));
|
||||
$total = $session + $noSession;
|
||||
if ( $total == 0 ) {
|
||||
$this->error( "You either have no stats or memcached isn't running. Aborting.\n", true );
|
||||
}
|
||||
$this->output( "Requests\n" );
|
||||
$this->output( sprintf( "with session: %-10d %6.2f%%\n", $session, $session/$total*100 );
|
||||
$this->output( sprintf( "without session: %-10d %6.2f%%\n", $noSession, $noSession/$total*100 );
|
||||
$this->output( sprintf( "total: %-10d %6.2f%%\n", $total, 100 );
|
||||
|
||||
|
||||
$this->output( "\nParser cache\n" );
|
||||
$hits = intval($wgMemc->get(wfMemcKey('stats','pcache_hit')));
|
||||
$invalid = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_invalid')));
|
||||
$expired = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_expired')));
|
||||
$absent = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_absent')));
|
||||
$stub = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_stub')));
|
||||
$total = $hits + $invalid + $expired + $absent + $stub;
|
||||
$this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ) );
|
||||
$this->output( sprintf( "invalid: %-10d %6.2f%%\n", $invalid, $invalid/$total*100 ) );
|
||||
$this->output( sprintf( "expired: %-10d %6.2f%%\n", $expired, $expired/$total*100 ) );
|
||||
$this->output( sprintf( "absent: %-10d %6.2f%%\n", $absent, $absent/$total*100 ) );
|
||||
$this->output( sprintf( "stub threshold: %-10d %6.2f%%\n", $stub, $stub/$total*100 ) );
|
||||
$this->output( sprintf( "total: %-10d %6.2f%%\n", $total, 100 ) );
|
||||
|
||||
$hits = intval($wgMemc->get(wfMemcKey('stats','image_cache_hit')));
|
||||
$misses = intval($wgMemc->get(wfMemcKey('stats','image_cache_miss')));
|
||||
$updates = intval($wgMemc->get(wfMemcKey('stats','image_cache_update')));
|
||||
$total = $hits + $misses;
|
||||
$this->output("\nImage cache\n");
|
||||
$this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 ) );
|
||||
$this->output( sprintf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 ) );
|
||||
$this->output( sprintf( "updates: %-10d\n", $updates ) );
|
||||
|
||||
$hits = intval($wgMemc->get(wfMemcKey('stats','diff_cache_hit')));
|
||||
$misses = intval($wgMemc->get(wfMemcKey('stats','diff_cache_miss')));
|
||||
$uncacheable = intval($wgMemc->get(wfMemcKey('stats','diff_uncacheable')));
|
||||
$total = $hits + $misses + $uncacheable;
|
||||
$this->output("\nDiff cache\n");
|
||||
$this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 );
|
||||
$this->output( sprintf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 );
|
||||
$this->output( sprintf( "uncacheable: %-10d %6.2f%%\n", $uncacheable, $uncacheable/$total*100 );
|
||||
}
|
||||
if( get_class( $wgMemc ) == 'FakeMemCachedClient' ) {
|
||||
die("You are running FakeMemCachedClient, I can not provide any statistics.\n");
|
||||
}
|
||||
|
||||
$maintClass = "MemcachedStats";
|
||||
require_once( DO_MAINTENANCE );
|
||||
$session = intval($wgMemc->get(wfMemcKey('stats','request_with_session')));
|
||||
$noSession = intval($wgMemc->get(wfMemcKey('stats','request_without_session')));
|
||||
$total = $session + $noSession;
|
||||
if ( $total == 0 ) {
|
||||
die("You either have no stats or memcached isn't running. Aborting.\n");
|
||||
}
|
||||
print "Requests\n";
|
||||
printf( "with session: %-10d %6.2f%%\n", $session, $session/$total*100 );
|
||||
printf( "without session: %-10d %6.2f%%\n", $noSession, $noSession/$total*100 );
|
||||
printf( "total: %-10d %6.2f%%\n", $total, 100 );
|
||||
|
||||
|
||||
print "\nParser cache\n";
|
||||
$hits = intval($wgMemc->get(wfMemcKey('stats','pcache_hit')));
|
||||
$invalid = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_invalid')));
|
||||
$expired = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_expired')));
|
||||
$absent = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_absent')));
|
||||
$stub = intval($wgMemc->get(wfMemcKey('stats','pcache_miss_stub')));
|
||||
$total = $hits + $invalid + $expired + $absent + $stub;
|
||||
printf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 );
|
||||
printf( "invalid: %-10d %6.2f%%\n", $invalid, $invalid/$total*100 );
|
||||
printf( "expired: %-10d %6.2f%%\n", $expired, $expired/$total*100 );
|
||||
printf( "absent: %-10d %6.2f%%\n", $absent, $absent/$total*100 );
|
||||
printf( "stub threshold: %-10d %6.2f%%\n", $stub, $stub/$total*100 );
|
||||
printf( "total: %-10d %6.2f%%\n", $total, 100 );
|
||||
|
||||
$hits = intval($wgMemc->get(wfMemcKey('stats','image_cache_hit')));
|
||||
$misses = intval($wgMemc->get(wfMemcKey('stats','image_cache_miss')));
|
||||
$updates = intval($wgMemc->get(wfMemcKey('stats','image_cache_update')));
|
||||
$total = $hits + $misses;
|
||||
print("\nImage cache\n");
|
||||
printf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 );
|
||||
printf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 );
|
||||
printf( "updates: %-10d\n", $updates );
|
||||
|
||||
$hits = intval($wgMemc->get(wfMemcKey('stats','diff_cache_hit')));
|
||||
$misses = intval($wgMemc->get(wfMemcKey('stats','diff_cache_miss')));
|
||||
$uncacheable = intval($wgMemc->get(wfMemcKey('stats','diff_uncacheable')));
|
||||
$total = $hits + $misses + $uncacheable;
|
||||
print("\nDiff cache\n");
|
||||
printf( "hits: %-10d %6.2f%%\n", $hits, $hits/$total*100 );
|
||||
printf( "misses: %-10d %6.2f%%\n", $misses, $misses/$total*100 );
|
||||
printf( "uncacheable: %-10d %6.2f%%\n", $uncacheable, $uncacheable/$total*100 );
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,35 +6,34 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$usage = <<<EOT
|
||||
Undelete a page
|
||||
Usage: php undelete.php [-u <user>] [-r <reason>] <pagename>
|
||||
|
||||
class Undelete extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Undelete a page";
|
||||
$this->addParam( 'u', 'The user to perform the undeletion', false, true );
|
||||
$this->addParam( 'r', 'The reason to undelete', false, true );
|
||||
$this->addArgs( array( 'pagename' ) );
|
||||
}
|
||||
EOT;
|
||||
|
||||
public function execute() {
|
||||
global $wgUser;
|
||||
$optionsWithArgs = array( 'u', 'r' );
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
$user = $this->getOption( 'u', 'Command line script' );
|
||||
$reason = $this->getOption( 'r', '' );
|
||||
$pageName = $this->getArg();
|
||||
$user = 'Command line script';
|
||||
$reason = '';
|
||||
|
||||
$title = Title::newFromText( $pageName );
|
||||
if ( !$title ) {
|
||||
$this->error( "Invalid title", true );
|
||||
}
|
||||
$wgUser = User::newFromName( $user );
|
||||
$archive = new PageArchive( $title );
|
||||
$this->output( "Undeleting " . $title->getPrefixedDBkey() . '...' );
|
||||
$archive->undelete( array(), $reason );
|
||||
$this->output( "done\n" );
|
||||
}
|
||||
if ( isset( $options['u'] ) ) {
|
||||
$user = $options['u'];
|
||||
}
|
||||
if ( isset( $options['r'] ) ) {
|
||||
$reason = $options['r'];
|
||||
}
|
||||
$pageName = @$args[0];
|
||||
$title = Title::newFromText( $pageName );
|
||||
if ( !$title ) {
|
||||
echo $usage;
|
||||
exit( 1 );
|
||||
}
|
||||
$wgUser = User::newFromName( $user );
|
||||
$archive = new PageArchive( $title );
|
||||
echo "Undeleting " . $title->getPrefixedDBkey() . '...';
|
||||
$archive->undelete( array(), $reason );
|
||||
echo "done\n";
|
||||
|
||||
|
||||
$maintClass = "Undelete";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
|
|
|||
|
|
@ -3,84 +3,38 @@
|
|||
* Maintenance script to provide a better count of the number of articles
|
||||
* and update the site statistics table, if desired
|
||||
*
|
||||
* @file
|
||||
* @ingroup Maintenance
|
||||
* @author Rob Church <robchur@gmail.com>
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$options = array( 'update', 'help' );
|
||||
require_once( 'commandLine.inc' );
|
||||
require_once( 'updateArticleCount.inc' );
|
||||
echo( "Update Article Count\n\n" );
|
||||
|
||||
class UpdateArticleCount extends Maintenance {
|
||||
|
||||
// Content namespaces
|
||||
private $namespaces;
|
||||
|
||||
public function __construct() {
|
||||
global $wgContentNamespaces;
|
||||
parent::__construct();
|
||||
$this->mDescription = "Count of the number of articles and update the site statistics table";
|
||||
$this->addParam( 'update', 'Update the site_stats table with the new count' );
|
||||
$this->namespaces = $wgContentNamespaces;
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$this->output( "Counting articles..." );
|
||||
$result = $this->count();
|
||||
|
||||
if( $result !== false ) {
|
||||
$this->output( "found {$result}.\n" );
|
||||
if( isset( $options['update'] ) && $options['update'] ) {
|
||||
$this->output( "Updating site statistics table... " );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->update( 'site_stats', array( 'ss_good_articles' => $result ), array( 'ss_row_id' => 1 ), __METHOD__ );
|
||||
$this->output( "done.\n" );
|
||||
} else {
|
||||
$this->output( "To update the site statistics table, run the script with the --update option.\n" );
|
||||
}
|
||||
} else {
|
||||
$this->output( "failed.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a comma-delimited set of namespaces
|
||||
* Includes paranoia
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function makeNsSet() {
|
||||
foreach( $this->namespaces as $namespace )
|
||||
$namespaces[] = intval( $namespace );
|
||||
return implode( ', ', $namespaces );
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce SQL for the query
|
||||
*
|
||||
* @param $dbr Database handle
|
||||
* @return string
|
||||
*/
|
||||
private function makeSql( $dbr ) {
|
||||
list( $page, $pagelinks ) = $dbr->tableNamesN( 'page', 'pagelinks' );
|
||||
$nsset = $this->makeNsSet();
|
||||
return "SELECT COUNT(DISTINCT page_namespace, page_title) AS pagecount " .
|
||||
"FROM $page, $pagelinks " .
|
||||
"WHERE pl_from=page_id and page_namespace IN ( $nsset ) " .
|
||||
"AND page_is_redirect = 0 AND page_len > 0";
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of valid content pages in the wiki
|
||||
*
|
||||
* @return mixed Integer, or false if there's a problem
|
||||
*/
|
||||
private function count() {
|
||||
$dbr = wfGetDB( DB_SLAVE );
|
||||
$res = $dbr->query( $this->makeSql( $dbr ), __METHOD__ );
|
||||
$row = $dbr->fetchObject( $res );
|
||||
$dbr->freeResult( $res );
|
||||
return $row->pagecount;
|
||||
}
|
||||
if( isset( $options['help'] ) && $options['help'] ) {
|
||||
echo( "Usage: php updateArticleCount.php [--update]\n\n" );
|
||||
echo( "--update : Update site statistics table\n" );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
$maintClass = "UpdateArticleCount";
|
||||
require_once( DO_MAINTENANCE );
|
||||
echo( "Counting articles..." );
|
||||
$counter = new ArticleCounter();
|
||||
$result = $counter->count();
|
||||
|
||||
if( $result !== false ) {
|
||||
echo( "found {$result}.\n" );
|
||||
if( isset( $options['update'] ) && $options['update'] ) {
|
||||
echo( "Updating site statistics table... " );
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$dbw->update( 'site_stats', array( 'ss_good_articles' => $result ), array( 'ss_row_id' => 1 ), __METHOD__ );
|
||||
echo( "done.\n" );
|
||||
} else {
|
||||
echo( "To update the site statistics table, run the script with the --update option.\n" );
|
||||
}
|
||||
} else {
|
||||
echo( "failed.\n" );
|
||||
}
|
||||
echo( "\n" );
|
||||
|
||||
|
|
|
|||
|
|
@ -5,159 +5,58 @@
|
|||
* Usage: php updateSearchIndex.php [-s START] [-e END] [-p POSFILE] [-l LOCKTIME] [-q]
|
||||
* Where START is the starting timestamp
|
||||
* END is the ending timestamp
|
||||
* POSFILE is a file to load timestamps from and save them to, searchUpdate.WIKI_ID.pos by default
|
||||
* LOCKTIME is how long the searchindex and revision tables will be locked for
|
||||
* POSFILE is a file to load timestamps from and save them to, searchUpdate.pos by default
|
||||
* LOCKTIME is how long the searchindex and cur tables will be locked for
|
||||
* -q means quiet
|
||||
*
|
||||
* @file
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class UpdateSearchIndex extends Maintenance {
|
||||
/** */
|
||||
$optionsWithArgs = array( 's', 'e', 'p' );
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->mDescription = "Script for periodic off-peak updating of the search index";
|
||||
$this->addParam( 's', 'starting timestamp', false, true );
|
||||
$this->addParam( 'e', 'Ending timestamp', false, true );
|
||||
$this->addParam( 'p', 'File for saving/loading timestamps, searchUpdate.WIKI_ID.pos by default', false, true );
|
||||
$this->addParam( 'l', 'How long the searchindex and revision tables will be locked for', false, true );
|
||||
}
|
||||
require_once( 'commandLine.inc' );
|
||||
require_once( 'updateSearchIndex.inc' );
|
||||
|
||||
public function execute() {
|
||||
$posFile = $this->getOption( 'p', 'searchUpdate.' . wfWikiId() . '.pos' );
|
||||
$end = $this->getOption( 'e', wfTimestampNow() );
|
||||
if ( $this->hasOption( 's' ) ) {
|
||||
$start = $this->getOption('s');
|
||||
} elseif( is_readable( 'searchUpdate.pos' ) ) {
|
||||
# B/c to the old position file name which was hardcoded
|
||||
# We can safely delete the file when we're done though.
|
||||
$start = file_get_contents( 'searchUpdate.pos' );
|
||||
unlink( 'searchUpdate.pos' );
|
||||
} else {
|
||||
$start = @file_get_contents( $posFile );
|
||||
if ( !$start ) {
|
||||
$start = wfTimestamp( TS_MW, time() - 86400 );
|
||||
}
|
||||
}
|
||||
$lockTime = $this->getOption( 'l', 20 );
|
||||
|
||||
$this->updateSearchIndex( $start, $end, $lockTime );
|
||||
$file = fopen( $posFile, 'w' );
|
||||
fwrite( $file, $end );
|
||||
fclose( $file );
|
||||
}
|
||||
|
||||
private function updateSearchIndex( $start, $end, $maxLockTime ) {
|
||||
global $wgDisableSearchUpdate;
|
||||
if ( isset( $options['p'] ) ) {
|
||||
$posFile = $options['p'];
|
||||
} else {
|
||||
$posFile = 'searchUpdate.' . wfWikiId() . '.pos';
|
||||
}
|
||||
|
||||
$wgDisableSearchUpdate = false;
|
||||
if ( isset( $options['e'] ) ) {
|
||||
$end = $options['e'];
|
||||
} else {
|
||||
$end = wfTimestampNow();
|
||||
}
|
||||
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
$recentchanges = $dbw->tableName( 'recentchanges' );
|
||||
|
||||
$this->output( "Updating searchindex between $start and $end\n" );
|
||||
|
||||
# Select entries from recentchanges which are on top and between the specified times
|
||||
$start = $dbw->strencode( $start );
|
||||
$end = $dbw->strencode( $end );
|
||||
|
||||
$page = $dbw->tableName( 'page' );
|
||||
$sql = "SELECT rc_cur_id,rc_type,rc_moved_to_ns,rc_moved_to_title FROM $recentchanges
|
||||
JOIN $page ON rc_cur_id=page_id AND rc_this_oldid=page_latest
|
||||
WHERE rc_timestamp BETWEEN '$start' AND '$end'
|
||||
";
|
||||
$res = $dbw->query( $sql, __METHOD__ );
|
||||
|
||||
|
||||
# Lock searchindex
|
||||
if ( $maxLockTime ) {
|
||||
$this->output( " --- Waiting for lock ---" );
|
||||
$this->lockSearchindex( $dbw );
|
||||
$lockTime = time();
|
||||
$this->output( "\n" );
|
||||
}
|
||||
|
||||
# Loop through the results and do a search update
|
||||
while ( $row = $dbw->fetchObject( $res ) ) {
|
||||
# Allow reads to be processed
|
||||
if ( $maxLockTime && time() > $lockTime + $maxLockTime ) {
|
||||
$this->output( " --- Relocking ---" );
|
||||
$this->relockSearchindex( $dbw );
|
||||
$lockTime = time();
|
||||
$this->output( "\n" );
|
||||
}
|
||||
if ( $row->rc_type == RC_LOG ) {
|
||||
continue;
|
||||
} elseif ( $row->rc_type == RC_MOVE || $row->rc_type == RC_MOVE_OVER_REDIRECT ) {
|
||||
# Rename searchindex entry
|
||||
$titleObj = Title::makeTitle( $row->rc_moved_to_ns, $row->rc_moved_to_title );
|
||||
$title = $titleObj->getPrefixedDBkey();
|
||||
$this->output( "$title..." );
|
||||
$u = new SearchUpdate( $row->rc_cur_id, $title, false );
|
||||
$this->output( "\n" );
|
||||
} else {
|
||||
// Get current revision
|
||||
$rev = Revision::loadFromPageId( $dbw, $row->rc_cur_id );
|
||||
if( $rev ) {
|
||||
$titleObj = $rev->getTitle();
|
||||
$title = $titleObj->getPrefixedDBkey();
|
||||
$this->output( $title );
|
||||
# Update searchindex
|
||||
$u = new SearchUpdate( $row->rc_cur_id, $titleObj->getText(), $rev->getText() );
|
||||
$u->doUpdate();
|
||||
$this->output( "\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Unlock searchindex
|
||||
if ( $maxLockTime ) {
|
||||
$this->output( " --- Unlocking --" );
|
||||
$this->unlockSearchindex( $dbw );
|
||||
$this->output( "\n" );
|
||||
}
|
||||
$this->output( "Done\n" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock the search index
|
||||
* @param &$db Database object
|
||||
*/
|
||||
private function lockSearchindex( &$db ) {
|
||||
$write = array( 'searchindex' );
|
||||
$read = array( 'page', 'revision', 'text', 'interwiki' );
|
||||
$items = array();
|
||||
|
||||
foreach( $write as $table ) {
|
||||
$items[] = $db->tableName( $table ) . ' LOW_PRIORITY WRITE';
|
||||
}
|
||||
foreach( $read as $table ) {
|
||||
$items[] = $db->tableName( $table ) . ' READ';
|
||||
}
|
||||
$sql = "LOCK TABLES " . implode( ',', $items );
|
||||
$db->query( $sql, 'updateSearchIndex.php ' . __METHOD__ );
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock the tables
|
||||
* @param &$db Database object
|
||||
*/
|
||||
private function unlockSearchindex( &$db ) {
|
||||
$db->query( "UNLOCK TABLES", 'updateSearchIndex.php ' . __METHOD__ );
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock and lock again
|
||||
* Since the lock is low-priority, queued reads will be able to complete
|
||||
* @param &$db Database object
|
||||
*/
|
||||
private function relockSearchindex( &$db ) {
|
||||
$this->unlockSearchindex( $db );
|
||||
$this->lockSearchindex( $db );
|
||||
if ( isset( $options['s'] ) ) {
|
||||
$start = $options['s'];
|
||||
} elseif( is_readable( 'searchUpdate.pos' ) ) {
|
||||
# B/c to the old position file name which was hardcoded
|
||||
# We can safely delete the file when we're done though.
|
||||
$start = file_get_contents( 'searchUpdate.pos' );
|
||||
unlink( 'searchUpdate.pos' );
|
||||
} else {
|
||||
$start = @file_get_contents( $posFile );
|
||||
if ( !$start ) {
|
||||
$start = wfTimestamp( TS_MW, time() - 86400 );
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = "UpdateSearchIndex";
|
||||
require_once( DO_MAINTENANCE );
|
||||
if ( isset( $options['l'] ) ) {
|
||||
$lockTime = $options['l'];
|
||||
} else {
|
||||
$lockTime = 20;
|
||||
}
|
||||
|
||||
$quiet = (bool)(@$options['q']);
|
||||
|
||||
updateSearchIndex( $start, $end, $lockTime, $quiet );
|
||||
|
||||
$file = fopen( $posFile, 'w' );
|
||||
fwrite( $file, $end );
|
||||
fclose( $file );
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,114 +6,114 @@
|
|||
* @file
|
||||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
$options = array('only','help');
|
||||
|
||||
class UpdateSpecialPages extends Maintenance {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->addParam( 'list', 'List special page names' );
|
||||
$this->addParam( 'only', 'Only update "page". Ex: --only=BrokenRedirects', false, true );
|
||||
$this->addParam( 'override', 'Also update pages that have updates disabled' );
|
||||
require_once( 'commandLine.inc' );
|
||||
|
||||
require_once( "$IP/includes/SpecialPage.php" );
|
||||
require_once( "$IP/includes/QueryPage.php" );
|
||||
|
||||
if(@$options['help']) {
|
||||
print "usage:updateSpecialPages.php [--help] [--only=page]\n";
|
||||
print " --help : this help message\n";
|
||||
print " --list : list special pages names\n";
|
||||
print " --only=page : only update 'page'. Ex: --only=BrokenRedirects\n";
|
||||
print " --override : update even pages which have had updates disabled\n";
|
||||
wfDie();
|
||||
}
|
||||
|
||||
$wgOut->disable();
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
|
||||
foreach( $wgSpecialPageCacheUpdates as $special => $call ) {
|
||||
if( !is_callable($call) ) {
|
||||
print "Uncallable function $call!\n";
|
||||
continue;
|
||||
}
|
||||
$t1 = explode( ' ', microtime() );
|
||||
call_user_func( $call, $dbw );
|
||||
$t2 = explode( ' ', microtime() );
|
||||
printf( '%-30s ', $special );
|
||||
$elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]);
|
||||
$hours = intval( $elapsed / 3600 );
|
||||
$minutes = intval( $elapsed % 3600 / 60 );
|
||||
$seconds = $elapsed - $hours * 3600 - $minutes * 60;
|
||||
if ( $hours ) {
|
||||
print $hours . 'h ';
|
||||
}
|
||||
if ( $minutes ) {
|
||||
print $minutes . 'm ';
|
||||
}
|
||||
printf( "completed in %.2fs\n", $seconds );
|
||||
# Wait for the slave to catch up
|
||||
wfWaitForSlaves( 5 );
|
||||
}
|
||||
|
||||
foreach( $wgQueryPages as $page ) {
|
||||
@list( $class, $special, $limit ) = $page;
|
||||
|
||||
# --list : just show the name of pages
|
||||
if( @$options['list'] ) {
|
||||
print "$special\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
global $wgOut;
|
||||
$wgOut->disable();
|
||||
$dbw = wfGetDB( DB_MASTER );
|
||||
if ( !isset( $options['override'] ) && $wgDisableQueryPageUpdate && in_array( $special, $wgDisableQueryPageUpdate ) ) {
|
||||
printf("%-30s disabled\n", $special);
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach( $wgSpecialPageCacheUpdates as $special => $call ) {
|
||||
if( !is_callable($call) ) {
|
||||
$this->error( "Uncallable function $call!\n" );
|
||||
continue;
|
||||
}
|
||||
$specialObj = SpecialPage::getPage( $special );
|
||||
if ( !$specialObj ) {
|
||||
print "No such special page: $special\n";
|
||||
exit;
|
||||
}
|
||||
if ( !class_exists( $class ) ) {
|
||||
$file = $specialObj->getFile();
|
||||
require_once( $file );
|
||||
}
|
||||
$queryPage = new $class;
|
||||
|
||||
if( !isset($options['only']) or $options['only'] == $queryPage->getName() ) {
|
||||
printf( '%-30s ', $special );
|
||||
if ( $queryPage->isExpensive() ) {
|
||||
$t1 = explode( ' ', microtime() );
|
||||
call_user_func( $call, $dbw );
|
||||
# Do the query
|
||||
$num = $queryPage->recache( $limit === null ? $wgQueryCacheLimit : $limit );
|
||||
$t2 = explode( ' ', microtime() );
|
||||
$this->output( sprintf( '%-30s ', $special ) );
|
||||
$elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]);
|
||||
$hours = intval( $elapsed / 3600 );
|
||||
$minutes = intval( $elapsed % 3600 / 60 );
|
||||
$seconds = $elapsed - $hours * 3600 - $minutes * 60;
|
||||
if ( $hours ) {
|
||||
$this->output( $hours . 'h ' );
|
||||
}
|
||||
if ( $minutes ) {
|
||||
$this->output( $minutes . 'm ' );
|
||||
}
|
||||
$this->output( sprintf( "completed in %.2fs\n", $seconds ) );
|
||||
# Wait for the slave to catch up
|
||||
wfWaitForSlaves( 5 );
|
||||
if ( $num === false ) {
|
||||
print "FAILED: database error\n";
|
||||
} else {
|
||||
print "got $num rows in ";
|
||||
|
||||
$elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]);
|
||||
$hours = intval( $elapsed / 3600 );
|
||||
$minutes = intval( $elapsed % 3600 / 60 );
|
||||
$seconds = $elapsed - $hours * 3600 - $minutes * 60;
|
||||
if ( $hours ) {
|
||||
print $hours . 'h ';
|
||||
}
|
||||
if ( $minutes ) {
|
||||
print $minutes . 'm ';
|
||||
}
|
||||
printf( "%.2fs\n", $seconds );
|
||||
}
|
||||
|
||||
foreach( $wgQueryPages as $page ) {
|
||||
@list( $class, $special, $limit ) = $page;
|
||||
|
||||
# --list : just show the name of pages
|
||||
if( $this->hasOption('list') ) {
|
||||
$this->output( "$special\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $this->hasOption('override') && $wgDisableQueryPageUpdate && in_array( $special, $wgDisableQueryPageUpdate ) ) {
|
||||
$this->output( sprintf( "%-30s disabled\n", $special ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
$specialObj = SpecialPage::getPage( $special );
|
||||
if ( !$specialObj ) {
|
||||
$this->output( "No such special page: $special\n" );
|
||||
exit;
|
||||
}
|
||||
if ( !class_exists( $class ) ) {
|
||||
$file = $specialObj->getFile();
|
||||
require_once( $file );
|
||||
}
|
||||
$queryPage = new $class;
|
||||
|
||||
if( !$this->hasOption('only') || $this->getOption('only') == $queryPage->getName() ) {
|
||||
$this->output( sprintf( '%-30s ', $special ) );
|
||||
if ( $queryPage->isExpensive() ) {
|
||||
$t1 = explode( ' ', microtime() );
|
||||
# Do the query
|
||||
$num = $queryPage->recache( $limit === null ? $wgQueryCacheLimit : $limit );
|
||||
$t2 = explode( ' ', microtime() );
|
||||
if ( $num === false ) {
|
||||
$this->output( "FAILED: database error\n" );
|
||||
} else {
|
||||
$this->output( "got $num rows in " );
|
||||
|
||||
$elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]);
|
||||
$hours = intval( $elapsed / 3600 );
|
||||
$minutes = intval( $elapsed % 3600 / 60 );
|
||||
$seconds = $elapsed - $hours * 3600 - $minutes * 60;
|
||||
if ( $hours ) {
|
||||
$this->output( $hours . 'h ' );
|
||||
}
|
||||
if ( $minutes ) {
|
||||
$this->output( $minutes . 'm ' );
|
||||
}
|
||||
$this->output( sprintf( "%.2fs\n", $seconds ) );
|
||||
}
|
||||
# Reopen any connections that have closed
|
||||
if ( !wfGetLB()->pingAll()) {
|
||||
$this->output( "\n" );
|
||||
do {
|
||||
$this->error( "Connection failed, reconnecting in 10 seconds...\n" );
|
||||
sleep(10);
|
||||
} while ( !wfGetLB()->pingAll() );
|
||||
$this->output( "Reconnected\n\n" );
|
||||
} else {
|
||||
# Commit the results
|
||||
$dbw->immediateCommit();
|
||||
}
|
||||
# Wait for the slave to catch up
|
||||
wfWaitForSlaves( 5 );
|
||||
} else {
|
||||
$this->output( "cheap, skipped\n" );
|
||||
}
|
||||
}
|
||||
# Reopen any connections that have closed
|
||||
if ( !wfGetLB()->pingAll()) {
|
||||
print "\n";
|
||||
do {
|
||||
print "Connection failed, reconnecting in 10 seconds...\n";
|
||||
sleep(10);
|
||||
} while ( !wfGetLB()->pingAll() );
|
||||
print "Reconnected\n\n";
|
||||
} else {
|
||||
# Commit the results
|
||||
$dbw->immediateCommit();
|
||||
}
|
||||
# Wait for the slave to catch up
|
||||
wfWaitForSlaves( 5 );
|
||||
} else {
|
||||
print "cheap, skipped\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1038,7 +1038,10 @@ function do_stats_init() {
|
|||
wfOut( "ok.\n" );
|
||||
return;
|
||||
}
|
||||
SiteStats::init( false );
|
||||
|
||||
global $IP;
|
||||
require_once "$IP/maintenance/initStats.inc";
|
||||
wfInitStats();
|
||||
}
|
||||
|
||||
function do_active_users_init() {
|
||||
|
|
|
|||
|
|
@ -5,16 +5,11 @@
|
|||
* @ingroup Maintenance
|
||||
*/
|
||||
|
||||
require_once( "Maintenance.php" );
|
||||
|
||||
class WaitForSlave extends Maintenance {
|
||||
public function __construct() {
|
||||
$this->addArgs( array( 'maxlag' ) );
|
||||
}
|
||||
public function execute() {
|
||||
wfWaitForSlaves( $this->getArg( 0, 10 ) );
|
||||
}
|
||||
require_once( "commandLine.inc" );
|
||||
if ( isset( $args[0] ) ) {
|
||||
wfWaitForSlaves($args[0]);
|
||||
} else {
|
||||
wfWaitForSlaves(10);
|
||||
}
|
||||
|
||||
$maintClass = "WaitForSlave";
|
||||
require_once( DO_MAINTENANCE );
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ ini_set( 'zlib.output_compression', 'off' );
|
|||
$wgEnableProfileInfo = $wgProfileToDatabase = false;
|
||||
|
||||
require_once( './includes/WebStart.php' );
|
||||
@include_once( './AdminSettings.php' );
|
||||
|
||||
?>
|
||||
<!--
|
||||
|
|
|
|||
|
|
@ -7,10 +7,11 @@ require 't/Test.php';
|
|||
require 'includes/Defines.php';
|
||||
require 'includes/ProfilerStub.php';
|
||||
require 'LocalSettings.php';
|
||||
require 'AdminSettings.php';
|
||||
require 'includes/Setup.php';
|
||||
|
||||
function buildTestDatabase( $tables ) {
|
||||
global $wgDBprefix, $wgDBserver, $wgDBname, $wgDBtype;
|
||||
global $wgDBprefix, $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname, $wgDBtype;
|
||||
$oldPrefix = $wgDBprefix;
|
||||
$wgDBprefix = 'parsertest';
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue