summaryrefslogtreecommitdiff
path: root/maintenance
diff options
context:
space:
mode:
authorPierre Schmitz <pierre@archlinux.de>2014-12-27 15:41:37 +0100
committerPierre Schmitz <pierre@archlinux.de>2014-12-31 11:43:28 +0100
commitc1f9b1f7b1b77776192048005dcc66dcf3df2bfb (patch)
tree2b38796e738dd74cb42ecd9bfd151803108386bc /maintenance
parentb88ab0086858470dd1f644e64cb4e4f62bb2be9b (diff)
Update to MediaWiki 1.24.1
Diffstat (limited to 'maintenance')
-rw-r--r--maintenance/7zip.inc4
-rw-r--r--maintenance/Maintenance.php275
-rw-r--r--maintenance/README5
-rw-r--r--maintenance/archives/patch-drop-rc_cur_time.sql2
-rw-r--r--maintenance/archives/patch-fa_major_mime-chemical.sql3
-rw-r--r--maintenance/archives/patch-hitcounter.sql2
-rw-r--r--maintenance/archives/patch-il_from_namespace.sql4
-rw-r--r--maintenance/archives/patch-img_major_mime-chemical.sql3
-rw-r--r--maintenance/archives/patch-logging_user_text_time_index.sql1
-rw-r--r--maintenance/archives/patch-logging_user_text_type_time_index.sql1
-rw-r--r--maintenance/archives/patch-mimesearch-indexes.sql2
-rw-r--r--maintenance/archives/patch-oi_major_mime-chemical.sql3
-rw-r--r--maintenance/archives/patch-page_lang.sql2
-rw-r--r--maintenance/archives/patch-page_links_updated.sql2
-rw-r--r--maintenance/archives/patch-pl_from_namespace.sql4
-rw-r--r--maintenance/archives/patch-pp_sortkey.sql8
-rw-r--r--maintenance/archives/patch-profiling.sql2
-rw-r--r--maintenance/archives/patch-rc_source.sql16
-rw-r--r--maintenance/archives/patch-restructure.sql146
-rw-r--r--maintenance/archives/patch-tl_from_namespace.sql4
-rw-r--r--maintenance/archives/patch-uploadstash.sql4
-rw-r--r--maintenance/archives/patch-user_password_expire.sql3
-rw-r--r--maintenance/archives/patch-val_ip.sql4
-rw-r--r--maintenance/archives/patch-validate.sql13
-rw-r--r--maintenance/archives/patch-watchlist-user-notificationtimestamp-index.sql4
-rw-r--r--maintenance/archives/upgradeLogging.php6
-rw-r--r--maintenance/attachLatest.php14
-rw-r--r--maintenance/backup.inc185
-rw-r--r--maintenance/backupPrefetch.inc74
-rw-r--r--maintenance/backupTextPass.inc210
-rw-r--r--maintenance/benchmarks/Benchmarker.php21
-rw-r--r--maintenance/benchmarks/bench_HTTP_HTTPS.php7
-rw-r--r--maintenance/benchmarks/bench_delete_truncate.php9
-rw-r--r--maintenance/benchmarks/bench_if_switch.php89
-rw-r--r--maintenance/benchmarks/bench_strtr_str_replace.php11
-rw-r--r--maintenance/benchmarks/bench_utf8_title_check.php29
-rw-r--r--maintenance/benchmarks/bench_wfBaseConvert.php12
-rw-r--r--maintenance/benchmarks/bench_wfIsWindows.php12
-rw-r--r--maintenance/benchmarks/benchmarkHooks.php8
-rw-r--r--maintenance/benchmarks/benchmarkParse.php174
-rw-r--r--maintenance/benchmarks/benchmarkPurge.php11
-rw-r--r--maintenance/cdb.php15
-rw-r--r--maintenance/checkBadRedirects.php2
-rw-r--r--maintenance/checkImages.php4
-rw-r--r--maintenance/checkLess.php48
-rw-r--r--maintenance/checkSyntax.php63
-rw-r--r--maintenance/checkUsernames.php2
-rw-r--r--maintenance/cleanupAncientTables.php9
-rw-r--r--maintenance/cleanupCaps.php5
-rw-r--r--maintenance/cleanupImages.php20
-rw-r--r--maintenance/cleanupRemovedModules.php10
-rw-r--r--maintenance/cleanupSpam.php32
-rw-r--r--maintenance/cleanupTitles.php10
-rw-r--r--maintenance/cleanupUploadStash.php52
-rw-r--r--maintenance/cleanupWatchlist.php14
-rw-r--r--maintenance/commandLine.inc7
-rw-r--r--maintenance/compareParserCache.php104
-rw-r--r--maintenance/compareParsers.php52
-rw-r--r--maintenance/convertLinks.php124
-rw-r--r--maintenance/convertUserOptions.php48
-rw-r--r--maintenance/copyFileBackend.php49
-rw-r--r--maintenance/copyJobQueue.php11
-rw-r--r--maintenance/createAndPromote.php14
-rw-r--r--maintenance/cssjanus/COPYING13
-rw-r--r--maintenance/cssjanus/LICENSE202
-rw-r--r--maintenance/cssjanus/README91
-rw-r--r--maintenance/cssjanus/cssjanus.py574
-rw-r--r--maintenance/cssjanus/csslex.py114
-rw-r--r--maintenance/deleteArchivedFiles.inc14
-rw-r--r--maintenance/deleteArchivedFiles.php1
-rw-r--r--maintenance/deleteArchivedRevisions.inc3
-rw-r--r--maintenance/deleteArchivedRevisions.php6
-rw-r--r--maintenance/deleteBatch.php14
-rw-r--r--maintenance/deleteDefaultMessages.php3
-rw-r--r--maintenance/deleteEqualMessages.php25
-rw-r--r--maintenance/deleteImageMemcached.php8
-rw-r--r--maintenance/deleteOrphanedRevisions.php7
-rw-r--r--maintenance/deleteRevision.php59
-rw-r--r--maintenance/dev/includes/php.sh2
-rw-r--r--maintenance/dev/includes/router.php4
-rw-r--r--maintenance/dictionary/mediawiki.dic160
-rw-r--r--maintenance/doMaintenance.php28
-rw-r--r--maintenance/dumpBackup.php4
-rw-r--r--maintenance/dumpIterator.php22
-rw-r--r--maintenance/dumpLinks.php6
-rw-r--r--maintenance/dumpSisterSites.php2
-rw-r--r--maintenance/dumpTextPass.php5
-rw-r--r--maintenance/dumpUploads.php6
-rw-r--r--maintenance/edit.php21
-rw-r--r--maintenance/eraseArchivedFile.php2
-rw-r--r--maintenance/eval.php22
-rw-r--r--maintenance/fetchText.php20
-rw-r--r--maintenance/findHooks.php133
-rw-r--r--maintenance/findMissingFiles.php115
-rw-r--r--maintenance/fixDoubleRedirects.php17
-rw-r--r--maintenance/fixExtLinksProtocolRelative.php15
-rw-r--r--maintenance/fixSlaveDesync.php46
-rw-r--r--maintenance/fixTimestamps.php9
-rw-r--r--maintenance/fixUserRegistration.php14
-rw-r--r--maintenance/fuzz-tester.php2692
-rw-r--r--maintenance/generateJsonI18n.php287
-rw-r--r--maintenance/generateSitemap.php120
-rw-r--r--maintenance/getConfiguration.php12
-rw-r--r--maintenance/getSlaveServer.php1
-rw-r--r--maintenance/getText.php5
-rw-r--r--maintenance/importDump.php37
-rw-r--r--maintenance/importImages.inc33
-rw-r--r--maintenance/importImages.php124
-rw-r--r--maintenance/importSiteScripts.php4
-rw-r--r--maintenance/importTextFile.php110
-rw-r--r--maintenance/initEditCount.php2
-rw-r--r--maintenance/initSiteStats.php23
-rw-r--r--maintenance/install.php99
-rw-r--r--maintenance/interwiki.list89
-rw-r--r--maintenance/interwiki.sql90
-rw-r--r--maintenance/jsduck/CustomTags.rb116
-rw-r--r--maintenance/jsduck/MetaTags.rb69
-rw-r--r--maintenance/jsduck/categories.json55
-rw-r--r--maintenance/jsduck/config.json47
-rw-r--r--maintenance/jsduck/eg-iframe.html154
-rw-r--r--maintenance/lag.php4
-rw-r--r--maintenance/language/StatOutputs.php47
-rw-r--r--maintenance/language/checkDupeMessages.php3
-rw-r--r--maintenance/language/checkLanguage.inc262
-rw-r--r--maintenance/language/countMessages.php72
-rw-r--r--maintenance/language/generateCollationData.php19
-rw-r--r--maintenance/language/generateNormalizerDataAr.php (renamed from maintenance/language/generateNormalizerData.php)72
-rw-r--r--maintenance/language/generateNormalizerDataMl.php69
-rw-r--r--maintenance/language/generateUtf8Case.php129
-rw-r--r--maintenance/language/langmemusage.php2
-rw-r--r--maintenance/language/languages.inc209
-rw-r--r--maintenance/language/listVariants.php73
-rw-r--r--maintenance/language/messageTypes.inc872
-rw-r--r--maintenance/language/messages.inc4239
-rw-r--r--maintenance/language/rebuildLanguage.php126
-rw-r--r--maintenance/language/transstat.php41
-rw-r--r--maintenance/language/validate.php64
-rw-r--r--maintenance/language/writeMessagesArray.inc283
-rw-r--r--maintenance/language/zhtable/Makefile.py70
-rw-r--r--maintenance/language/zhtable/trad2simp_supp_unset.manual0
-rw-r--r--maintenance/language/zhtable/tradphrases.manual1
-rw-r--r--maintenance/locking/LockServerDaemon.php640
-rw-r--r--maintenance/mctest.php19
-rw-r--r--maintenance/mergeMessageFileList.php23
-rw-r--r--maintenance/minify.php3
-rw-r--r--maintenance/moveBatch.php10
-rw-r--r--maintenance/mssql/archives/named_constraints.sql38
-rw-r--r--maintenance/mssql/archives/patch-fa_major_mime-chemical.sql4
-rw-r--r--maintenance/mssql/archives/patch-img_major_mime-chemical.sql4
-rw-r--r--maintenance/mssql/archives/patch-oi_major_mime-chemical.sql4
-rw-r--r--maintenance/mssql/archives/patch-page_page_lang.sql1
-rw-r--r--maintenance/mssql/archives/patch-user_password_expires.sql1
-rw-r--r--maintenance/mssql/tables.sql1592
-rw-r--r--maintenance/mssql/update-keys.sql31
-rw-r--r--maintenance/mwdocgen.php4
-rw-r--r--maintenance/mwjsduck-gen10
-rw-r--r--maintenance/namespaceDupes.php101
-rw-r--r--maintenance/nextJobDB.php119
-rw-r--r--maintenance/nukeNS.php2
-rw-r--r--maintenance/oracle/alterSharedConstraints.php38
-rw-r--r--maintenance/oracle/archives/patch-logging_user_text_time_index.sql4
-rw-r--r--maintenance/oracle/archives/patch-logging_user_text_type_time_index.sql4
-rw-r--r--maintenance/oracle/archives/patch-page-page_lang.sql3
-rw-r--r--maintenance/oracle/archives/patch-page_links_updated.sql4
-rw-r--r--maintenance/oracle/archives/patch-rc_source.sql3
-rw-r--r--maintenance/oracle/archives/patch-user_password_expire.sql3
-rw-r--r--maintenance/oracle/archives/patch_16_17_schema_changes.sql2
-rw-r--r--maintenance/oracle/tables.sql21
-rw-r--r--maintenance/oracle/update-keys.sql29
-rw-r--r--maintenance/orphans.php36
-rw-r--r--maintenance/pageExists.php54
-rw-r--r--maintenance/parse.php22
-rw-r--r--maintenance/patchSql.php5
-rw-r--r--maintenance/populateBacklinkNamespace.php97
-rw-r--r--maintenance/populateBloomCache.php78
-rw-r--r--maintenance/populateCategory.php39
-rw-r--r--maintenance/populateFilearchiveSha1.php1
-rw-r--r--maintenance/populateImageSha1.php25
-rw-r--r--maintenance/populateLogSearch.php12
-rw-r--r--maintenance/populateLogUsertext.php2
-rw-r--r--maintenance/populateParentId.php15
-rw-r--r--maintenance/populateRecentChangesSource.php107
-rw-r--r--maintenance/populateRevisionLength.php111
-rw-r--r--maintenance/populateRevisionSha1.php32
-rw-r--r--maintenance/postgres/mediawiki_mysql2postgres.pl3
-rw-r--r--maintenance/postgres/tables.sql29
-rw-r--r--maintenance/postgres/update-keys.sql29
-rw-r--r--maintenance/preprocessDump.php8
-rw-r--r--maintenance/preprocessorFuzzTest.php23
-rw-r--r--maintenance/pruneFileCache.php8
-rw-r--r--maintenance/purgeChangedFiles.php18
-rw-r--r--maintenance/purgeChangedPages.php4
-rw-r--r--maintenance/purgeList.php13
-rw-r--r--maintenance/purgeOldText.inc78
-rw-r--r--maintenance/purgeParserCache.php5
-rw-r--r--maintenance/reassignEdits.php53
-rw-r--r--maintenance/rebuildFileCache.php17
-rw-r--r--maintenance/rebuildImages.php20
-rw-r--r--maintenance/rebuildLocalisationCache.php10
-rw-r--r--maintenance/rebuildall.php6
-rw-r--r--maintenance/rebuildrecentchanges.php97
-rw-r--r--maintenance/rebuildtextindex.php10
-rw-r--r--maintenance/refreshImageMetadata.php65
-rw-r--r--maintenance/refreshLinks.php24
-rw-r--r--maintenance/removeUnusedAccounts.php16
-rw-r--r--maintenance/renderDump.php5
-rw-r--r--maintenance/resetUserTokens.php22
-rw-r--r--maintenance/resources/update-oojs-ui.sh95
-rw-r--r--maintenance/resources/update-oojs.sh53
-rw-r--r--maintenance/rollbackEdits.php14
-rw-r--r--maintenance/runBatchedQuery.php4
-rw-r--r--maintenance/runJobs.php122
-rw-r--r--maintenance/runScript.php64
-rw-r--r--maintenance/showCacheStats.php41
-rw-r--r--maintenance/showJobs.php11
-rw-r--r--maintenance/showSiteStats.php7
-rw-r--r--maintenance/sql.php35
-rw-r--r--maintenance/sqlite.inc8
-rw-r--r--maintenance/sqlite.php8
-rw-r--r--maintenance/sqlite/archives/initial-indexes.sql4
-rw-r--r--maintenance/sqlite/archives/patch-drop-rc_cur_time.sql45
-rw-r--r--maintenance/sqlite/archives/patch-page-page_lang.sql3
-rw-r--r--maintenance/storage/checkStorage.php68
-rw-r--r--maintenance/storage/compressOld.php99
-rw-r--r--maintenance/storage/fixBug20757.php18
-rw-r--r--maintenance/storage/orphanStats.php17
-rw-r--r--maintenance/storage/recompressTracked.php73
-rw-r--r--maintenance/storage/resolveStubs.php13
-rw-r--r--maintenance/storage/testCompression.php6
-rw-r--r--maintenance/storage/trackBlobs.php4
-rw-r--r--maintenance/syncFileBackend.php31
-rw-r--r--maintenance/tables.sql73
-rw-r--r--maintenance/term/MWTerm.php6
-rw-r--r--maintenance/undelete.php2
-rw-r--r--maintenance/update-keys.sql29
-rw-r--r--maintenance/update.php53
-rw-r--r--maintenance/updateArticleCount.php10
-rw-r--r--maintenance/updateCollation.php20
-rw-r--r--maintenance/updateDoubleWidthSearch.php8
-rw-r--r--maintenance/updateRestrictions.php15
-rw-r--r--maintenance/updateSearchIndex.php14
-rw-r--r--maintenance/updateSpecialPages.php76
-rw-r--r--maintenance/userDupes.inc38
-rw-r--r--maintenance/userOptions.inc45
-rw-r--r--maintenance/userOptions.php2
-rw-r--r--maintenance/waitForSlave.php1
-rw-r--r--maintenance/wrapOldPasswords.php126
247 files changed, 6716 insertions, 13258 deletions
diff --git a/maintenance/7zip.inc b/maintenance/7zip.inc
index 590cad23..751a1311 100644
--- a/maintenance/7zip.inc
+++ b/maintenance/7zip.inc
@@ -3,7 +3,7 @@
* 7z stream wrapper
*
* Copyright © 2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,6 +36,7 @@ class SevenZipStream {
private function stripPath( $path ) {
$prefix = 'mediawiki.compress.7z://';
+
return substr( $path, strlen( $prefix ) );
}
@@ -91,4 +92,5 @@ class SevenZipStream {
return fseek( $this->stream, $offset, $whence );
}
}
+
stream_wrapper_register( 'mediawiki.compress.7z', 'SevenZipStream' );
diff --git a/maintenance/Maintenance.php b/maintenance/Maintenance.php
index 30e93c90..8d30df4c 100644
--- a/maintenance/Maintenance.php
+++ b/maintenance/Maintenance.php
@@ -49,7 +49,6 @@ $maintClass = false;
* @ingroup Maintenance
*/
abstract class Maintenance {
-
/**
* Constants for DB access type
* @see Maintenance::getDbType()
@@ -115,11 +114,11 @@ abstract class Maintenance {
public $fileHandle;
/**
- * List of all the core maintenance scripts. This is added
- * to scripts added by extensions in $wgMaintenanceScripts
- * and returned by getMaintenanceScripts()
+ * Accessible via getConfig()
+ *
+ * @var Config
*/
- protected static $mCoreScripts = null;
+ private $config;
/**
* Default constructor. Children should call this *first* if implementing
@@ -141,9 +140,16 @@ abstract class Maintenance {
* as a standalone class? It checks that the call stack only includes this
* function and "requires" (meaning was called from the file scope)
*
- * @return Boolean
+ * @return bool
*/
public static function shouldExecute() {
+ global $wgCommandLineMode;
+
+ if ( !function_exists( 'debug_backtrace' ) ) {
+ // If someone has a better idea...
+ return $wgCommandLineMode;
+ }
+
$bt = debug_backtrace();
$count = count( $bt );
if ( $count < 2 ) {
@@ -158,6 +164,7 @@ abstract class Maintenance {
return false; // previous calls should all be "requires"
}
}
+
return true;
}
@@ -170,14 +177,22 @@ abstract class Maintenance {
* 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?
- * @param $shortName String: character to use as short name
+ * @param string $name The name of the param (help, version, etc)
+ * @param string $description The description of the param to show on --help
+ * @param bool $required Is the param required?
+ * @param bool $withArg Is an argument required with this option?
+ * @param string $shortName Character to use as short name
*/
- protected function addOption( $name, $description, $required = false, $withArg = false, $shortName = false ) {
- $this->mParams[$name] = array( 'desc' => $description, 'require' => $required, 'withArg' => $withArg, 'shortName' => $shortName );
+ protected function addOption( $name, $description, $required = false,
+ $withArg = false, $shortName = false
+ ) {
+ $this->mParams[$name] = array(
+ 'desc' => $description,
+ 'require' => $required,
+ 'withArg' => $withArg,
+ 'shortName' => $shortName
+ );
+
if ( $shortName !== false ) {
$this->mShortParamsMap[$shortName] = $name;
}
@@ -185,8 +200,8 @@ abstract class Maintenance {
/**
* Checks to see if a particular param exists.
- * @param $name String: the name of the param
- * @return Boolean
+ * @param string $name The name of the param
+ * @return bool
*/
protected function hasOption( $name ) {
return isset( $this->mOptions[$name] );
@@ -194,9 +209,9 @@ abstract class Maintenance {
/**
* 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
+ * @param string $name The name of the param
+ * @param mixed $default Anything you want, default null
+ * @return mixed
*/
protected function getOption( $name, $default = null ) {
if ( $this->hasOption( $name ) ) {
@@ -204,15 +219,16 @@ abstract class Maintenance {
} 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
- * @param $arg String: name of the arg, like 'start'
- * @param $description String: short description of the arg
- * @param $required Boolean: is this required?
+ * @param string $arg Name of the arg, like 'start'
+ * @param string $description Short description of the arg
+ * @param bool $required Is this required?
*/
protected function addArg( $arg, $description, $required = true ) {
$this->mArgList[] = array(
@@ -224,7 +240,7 @@ abstract class Maintenance {
/**
* Remove an option. Useful for removing options that won't be used in your script.
- * @param $name String: the option to remove.
+ * @param string $name The option to remove.
*/
protected function deleteOption( $name ) {
unset( $this->mParams[$name] );
@@ -232,7 +248,7 @@ abstract class Maintenance {
/**
* Set the description text.
- * @param $text String: the text of the description
+ * @param string $text The text of the description
*/
protected function addDescription( $text ) {
$this->mDescription = $text;
@@ -240,8 +256,8 @@ abstract class Maintenance {
/**
* Does a given argument exist?
- * @param $argId Integer: the integer value (from zero) for the arg
- * @return Boolean
+ * @param int $argId The integer value (from zero) for the arg
+ * @return bool
*/
protected function hasArg( $argId = 0 ) {
return isset( $this->mArgs[$argId] );
@@ -249,8 +265,8 @@ abstract class Maintenance {
/**
* Get an argument.
- * @param $argId Integer: the integer value (from zero) for the arg
- * @param $default Mixed: the default if it doesn't exist
+ * @param int $argId The integer value (from zero) for the arg
+ * @param mixed $default The default if it doesn't exist
* @return mixed
*/
protected function getArg( $argId = 0, $default = null ) {
@@ -259,7 +275,7 @@ abstract class Maintenance {
/**
* Set the batch size.
- * @param $s Integer: the number of operations to do in a batch
+ * @param int $s The number of operations to do in a batch
*/
protected function setBatchSize( $s = 0 ) {
$this->mBatchSize = $s;
@@ -281,7 +297,7 @@ abstract class Maintenance {
/**
* Get the script's name
- * @return String
+ * @return string
*/
public function getName() {
return $this->mSelf;
@@ -289,10 +305,9 @@ abstract class Maintenance {
/**
* Return input from stdin.
- * @param $len Integer: the number of bytes to read. If null,
- * just return the handle. Maintenance::STDIN_ALL returns
- * the full length
- * @return Mixed
+ * @param int $len The number of bytes to read. If null, just return the handle.
+ * Maintenance::STDIN_ALL returns the full length
+ * @return mixed
*/
protected function getStdin( $len = null ) {
if ( $len == Maintenance::STDIN_ALL ) {
@@ -304,6 +319,7 @@ abstract class Maintenance {
}
$input = fgets( $f, $len );
fclose( $f );
+
return rtrim( $input );
}
@@ -317,9 +333,8 @@ abstract class Maintenance {
/**
* 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
- * @param $channel Mixed: unique identifier for the channel. See
- * function outputChanneled.
+ * @param string $out The text to show to the user
+ * @param mixed $channel Unique identifier for the channel. See function outputChanneled.
*/
protected function output( $out, $channel = null ) {
if ( $this->mQuiet ) {
@@ -337,8 +352,8 @@ abstract class Maintenance {
/**
* 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 Int: if > 0, go ahead and die out using this int as the code
+ * @param string $err The error to display
+ * @param int $die If > 0, go ahead and die out using this int as the code
*/
protected function error( $err, $die = 0 ) {
$this->outputChanneled( false );
@@ -370,13 +385,14 @@ abstract class Maintenance {
* Message outputter with channeled message support. Messages on the
* same channel are concatenated, but any intervening messages in another
* channel start a new line.
- * @param $msg String: the message without trailing newline
- * @param $channel string Channel identifier or null for no
+ * @param string $msg The message without trailing newline
+ * @param string $channel Channel identifier or null for no
* channel. Channel comparison uses ===.
*/
public function outputChanneled( $msg, $channel = null ) {
if ( $msg === false ) {
$this->cleanupChanneled();
+
return;
}
@@ -404,7 +420,7 @@ abstract class Maintenance {
* Maintenance::DB_NONE - For no DB access at all
* Maintenance::DB_STD - For normal DB access, default
* Maintenance::DB_ADMIN - For admin DB access
- * @return Integer
+ * @return int
*/
public function getDbType() {
return Maintenance::DB_STD;
@@ -422,10 +438,14 @@ abstract class Maintenance {
$this->addOption( 'conf', 'Location of LocalSettings.php, if not default', false, true );
$this->addOption( 'wiki', 'For specifying the wiki ID', false, true );
$this->addOption( 'globals', 'Output globals at the end of processing for debugging' );
- $this->addOption( 'memory-limit', 'Set a specific memory limit for the script, "max" for no limit or "default" to avoid changing it' );
+ $this->addOption(
+ 'memory-limit',
+ 'Set a specific memory limit for the script, '
+ . '"max" for no limit or "default" to avoid changing it'
+ );
$this->addOption( 'server', "The protocol and server name to use in URLs, e.g. " .
- "http://en.wikipedia.org. This is sometimes necessary because " .
- "server name detection may fail in command line scripts.", false, true );
+ "http://en.wikipedia.org. This is sometimes necessary because " .
+ "server name detection may fail in command line scripts.", false, true );
$this->addOption( 'profiler', 'Set to "text" or "trace" to show profiling output', false, true );
# Save generic options to display them separately in help
@@ -445,11 +465,31 @@ abstract class Maintenance {
}
/**
+ * @since 1.24
+ * @return Config
+ */
+ public function getConfig() {
+ if ( $this->config === null ) {
+ $this->config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+ }
+
+ return $this->config;
+ }
+
+ /**
+ * @since 1.24
+ * @param Config $config
+ */
+ public function setConfig( Config $config ) {
+ $this->config = $config;
+ }
+
+ /**
* Run 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
+ * @param string $maintClass A name of a child maintenance class
+ * @param string $classFile Full path of where the child is
+ * @return Maintenance
*/
public function runChild( $maintClass, $classFile = null ) {
// Make sure the class is loaded first
@@ -470,6 +510,7 @@ abstract class Maintenance {
if ( !is_null( $this->mDb ) ) {
$child->setDB( $this->mDb );
}
+
return $child;
}
@@ -570,9 +611,9 @@ abstract class Maintenance {
* $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
+ * @param string $self The name of the script, if any
+ * @param array $opts An array of options, in form of key=>value
+ * @param array $args 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
@@ -594,6 +635,7 @@ abstract class Maintenance {
# it's run again and again
if ( $this->mInputLoaded ) {
$this->loadSpecialVars();
+
return;
}
@@ -639,8 +681,9 @@ abstract class Maintenance {
}
} elseif ( substr( $arg, 0, 1 ) == '-' ) {
# Short options
- for ( $p = 1; $p < strlen( $arg ); $p++ ) {
- $option = $arg { $p };
+ $argLength = strlen( $arg );
+ for ( $p = 1; $p < $argLength; $p++ ) {
+ $option = $arg[$p];
if ( !isset( $this->mParams[$option] ) && isset( $this->mShortParamsMap[$option] ) ) {
$option = $this->mShortParamsMap[$option];
}
@@ -715,14 +758,14 @@ abstract class Maintenance {
/**
* Maybe show the help.
- * @param $force boolean Whether to force the help to show, default false
+ * @param bool $force Whether to force the help to show, default false
*/
protected function maybeHelp( $force = false ) {
if ( !$force && !$this->hasOption( 'help' ) ) {
return;
}
- $screenWidth = 80; // TODO: Caculate this!
+ $screenWidth = 80; // TODO: Calculate this!
$tab = " ";
$descWidth = $screenWidth - ( 2 * strlen( $tab ) );
@@ -766,7 +809,7 @@ abstract class Maintenance {
}
$this->output(
wordwrap( "$tab--$par: " . $info['desc'], $descWidth,
- "\n$tab$tab" ) . "\n"
+ "\n$tab$tab" ) . "\n"
);
}
$this->output( "\n" );
@@ -781,13 +824,12 @@ abstract class Maintenance {
}
$this->output(
wordwrap( "$tab--$par: " . $info['desc'], $descWidth,
- "\n$tab$tab" ) . "\n"
+ "\n$tab$tab" ) . "\n"
);
}
$this->output( "\n" );
}
-
// Script specific parameters not defined on construction by
// Maintenance::addDefaultParams()
$scriptSpecificParams = array_diff_key(
@@ -806,7 +848,7 @@ abstract class Maintenance {
}
$this->output(
wordwrap( "$tab--$par: " . $info['desc'], $descWidth,
- "\n$tab$tab" ) . "\n"
+ "\n$tab$tab" ) . "\n"
);
}
$this->output( "\n" );
@@ -881,7 +923,12 @@ abstract class Maintenance {
$this->afterFinalSetup();
$wgShowSQLErrors = true;
+
+ // @codingStandardsIgnoreStart Allow error supppression. wfSuppressWarnings()
+ // is not avaiable.
@set_time_limit( 0 );
+ // @codingStandardsIgnoreStart
+
$this->adjustMemoryLimit();
// Per-script profiling; useful for debugging
@@ -916,7 +963,7 @@ abstract class Maintenance {
/**
* Generic setup for most installs. Returns the location of LocalSettings
- * @return String
+ * @return string
*/
public function loadSettings() {
global $wgCommandLineMode, $IP;
@@ -939,16 +986,17 @@ abstract class Maintenance {
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" .
- "Use --conf to specify it.", true );
+ "must exist and be readable in the source directory.\n" .
+ "Use --conf to specify it.", true );
}
$wgCommandLineMode = true;
+
return $settingsFile;
}
/**
* Support function for cleaning up redundant text records
- * @param $delete Boolean: whether or not to actually delete the records
+ * @param bool $delete Whether or not to actually delete the records
* @author Rob Church <robchur@gmail.com>
*/
public function purgeRedundantText( $delete = true ) {
@@ -1009,52 +1057,6 @@ abstract class Maintenance {
}
/**
- * Get the list of available maintenance scripts. Note
- * that if you call this _before_ calling doMaintenance
- * you won't have any extensions in it yet
- * @return Array
- */
- public static function getMaintenanceScripts() {
- global $wgMaintenanceScripts;
- return $wgMaintenanceScripts + self::getCoreScripts();
- }
-
- /**
- * Return all of the core maintenance scripts
- * @return array
- */
- protected static function getCoreScripts() {
- if ( !self::$mCoreScripts ) {
- $paths = array(
- __DIR__,
- __DIR__ . '/language',
- __DIR__ . '/storage',
- );
- self::$mCoreScripts = array();
- foreach ( $paths as $p ) {
- $handle = opendir( $p );
- while ( ( $file = readdir( $handle ) ) !== false ) {
- if ( $file == 'Maintenance.php' ) {
- continue;
- }
- $file = $p . '/' . $file;
- if ( is_dir( $file ) || !strpos( $file, '.php' ) ||
- ( strpos( file_get_contents( $file ), '$maintClass' ) === false ) ) {
- continue;
- }
- require $file;
- $vars = get_defined_vars();
- if ( array_key_exists( 'maintClass', $vars ) ) {
- self::$mCoreScripts[$vars['maintClass']] = $file;
- }
- }
- closedir( $handle );
- }
- }
- return self::$mCoreScripts;
- }
-
- /**
* Returns a database to be used by current maintenance script. It can be set by setDB().
* If not set, wfGetDB() will be used.
* This function has the same parameters as wfGetDB()
@@ -1072,7 +1074,7 @@ abstract class Maintenance {
/**
* Sets database object to be returned by getDB().
*
- * @param $db DatabaseBase: Database object to be used
+ * @param DatabaseBase $db Database object to be used
*/
public function setDB( &$db ) {
$this->mDb = $db;
@@ -1080,7 +1082,7 @@ abstract class Maintenance {
/**
* Lock the search index
- * @param &$db DatabaseBase object
+ * @param DatabaseBase &$db
*/
private function lockSearchindex( &$db ) {
$write = array( 'searchindex' );
@@ -1090,7 +1092,7 @@ abstract class Maintenance {
/**
* Unlock the tables
- * @param &$db DatabaseBase object
+ * @param DatabaseBase &$db
*/
private function unlockSearchindex( &$db ) {
$db->unlockTables( __CLASS__ . '::' . __METHOD__ );
@@ -1099,7 +1101,7 @@ abstract class Maintenance {
/**
* Unlock and lock again
* Since the lock is low-priority, queued reads will be able to complete
- * @param &$db DatabaseBase object
+ * @param DatabaseBase &$db
*/
private function relockSearchindex( &$db ) {
$this->unlockSearchindex( $db );
@@ -1108,10 +1110,10 @@ abstract class Maintenance {
/**
* Perform a search index update with locking
- * @param $maxLockTime Integer: the maximum time to keep the search index locked.
- * @param $callback callback String: the function that will update the function.
- * @param $dbw DatabaseBase object
- * @param $results
+ * @param int $maxLockTime The maximum time to keep the search index locked.
+ * @param string $callback The function that will update the function.
+ * @param DatabaseBase $dbw
+ * @param array $results
*/
public function updateSearchIndex( $maxLockTime, $callback, $dbw, $results ) {
$lockTime = time();
@@ -1142,13 +1144,12 @@ abstract class Maintenance {
$this->unlockSearchindex( $dbw );
$this->output( "\n" );
}
-
}
/**
* Update the searchindex table for a given pageid
- * @param $dbw DatabaseBase a database write handle
- * @param $pageId Integer: the page ID to update.
+ * @param DatabaseBase $dbw A database write handle
+ * @param int $pageId The page ID to update.
* @return null|string
*/
public function updateSearchIndexForPage( $dbw, $pageId ) {
@@ -1164,6 +1165,7 @@ abstract class Maintenance {
$u->doUpdate();
$this->output( "\n" );
}
+
return $title;
}
@@ -1172,7 +1174,7 @@ abstract class Maintenance {
* We default as considering stdin a tty (for nice readline methods)
* but treating stout as not a tty to avoid color codes
*
- * @param $fd int File descriptor
+ * @param int $fd File descriptor
* @return bool
*/
public static function posix_isatty( $fd ) {
@@ -1185,8 +1187,8 @@ abstract class Maintenance {
/**
* Prompt the console for input
- * @param $prompt String what to begin the line with, like '> '
- * @return String response
+ * @param string $prompt What to begin the line with, like '> '
+ * @return string Response
*/
public static function readconsole( $prompt = '> ' ) {
static $isatty = null;
@@ -1210,14 +1212,15 @@ abstract class Maintenance {
return false;
}
$resp = trim( $st );
+
return $resp;
}
}
/**
* Emulate readline()
- * @param $prompt String what to begin the line with, like '> '
- * @return String
+ * @param string $prompt What to begin the line with, like '> '
+ * @return string
*/
private static function readlineEmulation( $prompt ) {
$bash = Installer::locateExecutableInDefaultPaths( array( 'bash' ) );
@@ -1245,6 +1248,7 @@ abstract class Maintenance {
return false;
}
print $prompt;
+
return fgets( STDIN, 1024 );
}
}
@@ -1254,6 +1258,7 @@ abstract class Maintenance {
*/
class FakeMaintenance extends Maintenance {
protected $mSelf = "FakeMaintenanceScript";
+
public function execute() {
return;
}
@@ -1274,10 +1279,11 @@ abstract class LoggedUpdateMaintenance extends Maintenance {
$db = $this->getDB( DB_MASTER );
$key = $this->getUpdateKey();
- if ( !$this->hasOption( 'force' ) &&
- $db->selectRow( 'updatelog', '1', array( 'ul_key' => $key ), __METHOD__ ) )
- {
+ if ( !$this->hasOption( 'force' )
+ && $db->selectRow( 'updatelog', '1', array( 'ul_key' => $key ), __METHOD__ )
+ ) {
$this->output( "..." . $this->updateSkippedMessage() . "\n" );
+
return true;
}
@@ -1285,44 +1291,45 @@ abstract class LoggedUpdateMaintenance extends Maintenance {
return false;
}
- if (
- $db->insert( 'updatelog', array( 'ul_key' => $key ), __METHOD__, 'IGNORE' ) )
- {
+ if ( $db->insert( 'updatelog', array( 'ul_key' => $key ), __METHOD__, 'IGNORE' ) ) {
return true;
} else {
$this->output( $this->updatelogFailedMessage() . "\n" );
+
return false;
}
}
/**
* Message to show that the update was done already and was just skipped
- * @return String
+ * @return string
*/
protected function updateSkippedMessage() {
$key = $this->getUpdateKey();
+
return "Update '{$key}' already logged as completed.";
}
/**
* Message to show the the update log was unable to log the completion of this update
- * @return String
+ * @return string
*/
protected function updatelogFailedMessage() {
$key = $this->getUpdateKey();
+
return "Unable to log update '{$key}' as completed.";
}
/**
* Do the actual work. All child classes will need to implement this.
* Return true to log the update as done or false (usually on failure).
- * @return Bool
+ * @return bool
*/
abstract protected function doDBUpdates();
/**
* Get the update key name to go in the update log table
- * @return String
+ * @return string
*/
abstract protected function getUpdateKey();
}
diff --git a/maintenance/README b/maintenance/README
index 5cb6f5f5..30bb6adb 100644
--- a/maintenance/README
+++ b/maintenance/README
@@ -51,7 +51,7 @@ installations.
edit.php
Edit a page to change its content
- findhooks.php
+ findHooks.php
Find hooks that aren't documented in docs/hooks.txt
importDump.php
@@ -60,9 +60,6 @@ installations.
importImages.php
Import images into the wiki
- importTextFile.php
- Import the contents of a text file into a wiki page
-
moveBatch.php
Move a batch of pages
diff --git a/maintenance/archives/patch-drop-rc_cur_time.sql b/maintenance/archives/patch-drop-rc_cur_time.sql
new file mode 100644
index 00000000..f1bc9e8b
--- /dev/null
+++ b/maintenance/archives/patch-drop-rc_cur_time.sql
@@ -0,0 +1,2 @@
+-- rc_cur_time is no longer used, delete the field
+ALTER TABLE /*$wgDBprefix*/recentchanges DROP COLUMN rc_cur_time; \ No newline at end of file
diff --git a/maintenance/archives/patch-fa_major_mime-chemical.sql b/maintenance/archives/patch-fa_major_mime-chemical.sql
new file mode 100644
index 00000000..be9b0ff5
--- /dev/null
+++ b/maintenance/archives/patch-fa_major_mime-chemical.sql
@@ -0,0 +1,3 @@
+ALTER TABLE /*$wgDBprefix*/filearchive
+ CHANGE fa_major_mime fa_major_mime ENUM('unknown','application','audio','image','text','video','message','model','multipart','chemical');
+
diff --git a/maintenance/archives/patch-hitcounter.sql b/maintenance/archives/patch-hitcounter.sql
index c87c9592..2d698f68 100644
--- a/maintenance/archives/patch-hitcounter.sql
+++ b/maintenance/archives/patch-hitcounter.sql
@@ -6,4 +6,4 @@
CREATE TABLE /*$wgDBprefix*/hitcounter (
hc_id INTEGER UNSIGNED NOT NULL
-) ENGINE=HEAP MAX_ROWS=25000;
+) ENGINE=MEMORY MAX_ROWS=25000;
diff --git a/maintenance/archives/patch-il_from_namespace.sql b/maintenance/archives/patch-il_from_namespace.sql
new file mode 100644
index 00000000..4c858f44
--- /dev/null
+++ b/maintenance/archives/patch-il_from_namespace.sql
@@ -0,0 +1,4 @@
+ALTER TABLE /*_*/imagelinks
+ ADD COLUMN il_from_namespace int NOT NULL default 0;
+
+CREATE INDEX /*i*/il_backlinks_namespace ON /*_*/imagelinks (il_to,il_from_namespace,il_from); \ No newline at end of file
diff --git a/maintenance/archives/patch-img_major_mime-chemical.sql b/maintenance/archives/patch-img_major_mime-chemical.sql
new file mode 100644
index 00000000..4bde446e
--- /dev/null
+++ b/maintenance/archives/patch-img_major_mime-chemical.sql
@@ -0,0 +1,3 @@
+ALTER TABLE /*$wgDBprefix*/image
+ CHANGE img_major_mime img_major_mime ENUM('unknown','application','audio','image','text','video','message','model','multipart','chemical');
+
diff --git a/maintenance/archives/patch-logging_user_text_time_index.sql b/maintenance/archives/patch-logging_user_text_time_index.sql
new file mode 100644
index 00000000..06f29861
--- /dev/null
+++ b/maintenance/archives/patch-logging_user_text_time_index.sql
@@ -0,0 +1 @@
+CREATE INDEX /*i*/log_user_text_time ON /*_*/logging (log_user_text, log_timestamp);
diff --git a/maintenance/archives/patch-logging_user_text_type_time_index.sql b/maintenance/archives/patch-logging_user_text_type_time_index.sql
new file mode 100644
index 00000000..2801bc86
--- /dev/null
+++ b/maintenance/archives/patch-logging_user_text_type_time_index.sql
@@ -0,0 +1 @@
+CREATE INDEX /*i*/log_user_text_type_time ON /*_*/logging (log_user_text, log_type, log_timestamp);
diff --git a/maintenance/archives/patch-mimesearch-indexes.sql b/maintenance/archives/patch-mimesearch-indexes.sql
index bd348c46..8d9426ea 100644
--- a/maintenance/archives/patch-mimesearch-indexes.sql
+++ b/maintenance/archives/patch-mimesearch-indexes.sql
@@ -1,4 +1,4 @@
--- Add indexes to the mime types in image for use on Special:MIMEsearch,
+-- Add indexes to the MIME types in image for use on Special:MIMEsearch,
-- changes a query like
--
-- SELECT img_name FROM image WHERE img_major_mime = "image" AND img_minor_mime = "svg";
diff --git a/maintenance/archives/patch-oi_major_mime-chemical.sql b/maintenance/archives/patch-oi_major_mime-chemical.sql
new file mode 100644
index 00000000..e3b4552d
--- /dev/null
+++ b/maintenance/archives/patch-oi_major_mime-chemical.sql
@@ -0,0 +1,3 @@
+ALTER TABLE /*$wgDBprefix*/oldimage
+ CHANGE oi_major_mime oi_major_mime ENUM('unknown','application','audio','image','text','video','message','model','multipart','chemical');
+
diff --git a/maintenance/archives/patch-page_lang.sql b/maintenance/archives/patch-page_lang.sql
new file mode 100644
index 00000000..c792b4ad
--- /dev/null
+++ b/maintenance/archives/patch-page_lang.sql
@@ -0,0 +1,2 @@
+ALTER TABLE /*$wgDBprefix*/page
+ ADD page_lang varbinary(35) DEFAULT NULL;
diff --git a/maintenance/archives/patch-page_links_updated.sql b/maintenance/archives/patch-page_links_updated.sql
new file mode 100644
index 00000000..18d9e2d9
--- /dev/null
+++ b/maintenance/archives/patch-page_links_updated.sql
@@ -0,0 +1,2 @@
+ALTER TABLE /*$wgDBprefix*/page
+ ADD page_links_updated varbinary(14) NULL default NULL;
diff --git a/maintenance/archives/patch-pl_from_namespace.sql b/maintenance/archives/patch-pl_from_namespace.sql
new file mode 100644
index 00000000..2f7ff046
--- /dev/null
+++ b/maintenance/archives/patch-pl_from_namespace.sql
@@ -0,0 +1,4 @@
+ALTER TABLE /*_*/pagelinks
+ ADD COLUMN pl_from_namespace int NOT NULL default 0;
+
+CREATE INDEX /*i*/pl_backlinks_namespace ON /*_*/pagelinks (pl_namespace,pl_title,pl_from_namespace,pl_from);
diff --git a/maintenance/archives/patch-pp_sortkey.sql b/maintenance/archives/patch-pp_sortkey.sql
new file mode 100644
index 00000000..b13b6055
--- /dev/null
+++ b/maintenance/archives/patch-pp_sortkey.sql
@@ -0,0 +1,8 @@
+-- Add a 'sortkey' field to page_props so pages can be efficiently
+-- queried by the numeric value of a property.
+
+ALTER TABLE /*_*/page_props
+ ADD pp_sortkey float DEFAULT NULL;
+
+CREATE UNIQUE INDEX /*i*/pp_propname_sortkey_page
+ ON /*_*/page_props ( pp_propname, pp_sortkey, pp_page );
diff --git a/maintenance/archives/patch-profiling.sql b/maintenance/archives/patch-profiling.sql
index 0a0e4e1a..6ad16224 100644
--- a/maintenance/archives/patch-profiling.sql
+++ b/maintenance/archives/patch-profiling.sql
@@ -7,6 +7,6 @@ CREATE TABLE /*_*/profiling (
pf_memory float NOT NULL default 0,
pf_name varchar(255) NOT NULL default '',
pf_server varchar(30) NOT NULL default ''
-) ENGINE=HEAP;
+) ENGINE=MEMORY;
CREATE UNIQUE INDEX /*i*/pf_name_server ON /*_*/profiling (pf_name, pf_server); \ No newline at end of file
diff --git a/maintenance/archives/patch-rc_source.sql b/maintenance/archives/patch-rc_source.sql
new file mode 100644
index 00000000..7dedd745
--- /dev/null
+++ b/maintenance/archives/patch-rc_source.sql
@@ -0,0 +1,16 @@
+-- first step of migrating recentchanges rc_type to rc_source
+ALTER TABLE /*$wgDBprefix*/recentchanges
+ ADD rc_source varbinary(16) NOT NULL default '';
+
+-- Populate rc_source field with the data from rc_type
+-- Large wiki's might prefer the PopulateRecentChangeSource maintenance
+-- script to batch updates into groups rather than all at once.
+UPDATE /*$wgDBprefix*/recentchanges
+ SET rc_source = CASE
+ WHEN rc_type = 0 THEN 'mw.edit'
+ WHEN rc_type = 1 THEN 'mw.new'
+ WHEN rc_type = 3 THEN 'mw.log'
+ WHEN rc_type = 5 THEN 'mw.external'
+ ELSE ''
+ END
+WHERE rc_source = '';
diff --git a/maintenance/archives/patch-restructure.sql b/maintenance/archives/patch-restructure.sql
deleted file mode 100644
index a5bc3e52..00000000
--- a/maintenance/archives/patch-restructure.sql
+++ /dev/null
@@ -1,146 +0,0 @@
--- The Great Restructuring of October 2004
--- Creates 'page', 'revision' tables and transforms the classic
--- cur+old into a separate page+revision+text structure.
---
--- The pre-conversion 'old' table is renamed to 'text' and used
--- without internal restructuring to avoid rebuilding the entire
--- table. (This can be done separately if desired.)
---
--- The pre-conversion 'cur' table is now redundant and can be
--- discarded when done.
-
-CREATE TABLE /*$wgDBprefix*/page (
- page_id int unsigned NOT NULL auto_increment,
- page_namespace tinyint NOT NULL,
- page_title varchar(255) binary NOT NULL,
- page_restrictions tinyblob NOT NULL,
- page_counter bigint unsigned NOT NULL default '0',
- page_is_redirect tinyint unsigned NOT NULL default '0',
- page_is_new tinyint unsigned NOT NULL default '0',
- page_random real unsigned NOT NULL,
- page_touched binary(14) NOT NULL default '',
- page_latest int unsigned NOT NULL,
- page_len int unsigned NOT NULL,
-
- PRIMARY KEY page_id (page_id),
- UNIQUE INDEX name_title (page_namespace,page_title),
- INDEX (page_random),
- INDEX (page_len)
-);
-
-CREATE TABLE /*$wgDBprefix*/revision (
- rev_id int unsigned NOT NULL auto_increment,
- rev_page int unsigned NOT NULL,
- rev_comment tinyblob NOT NULL,
- rev_user int unsigned NOT NULL default '0',
- rev_user_text varchar(255) binary NOT NULL default '',
- rev_timestamp binary(14) NOT NULL default '',
- rev_minor_edit tinyint unsigned NOT NULL default '0',
- rev_deleted tinyint unsigned NOT NULL default '0',
-
- PRIMARY KEY rev_page_id (rev_page, rev_id),
- UNIQUE INDEX rev_id (rev_id),
- INDEX rev_timestamp (rev_timestamp),
- INDEX page_timestamp (rev_page,rev_timestamp),
- INDEX user_timestamp (rev_user,rev_timestamp),
- INDEX usertext_timestamp (rev_user_text,rev_timestamp)
-);
-
--- If creating new 'text' table it would look like this:
---
--- CREATE TABLE /*$wgDBprefix*/text (
--- old_id int(8) unsigned NOT NULL auto_increment,
--- old_text mediumtext NOT NULL,
--- old_flags tinyblob NOT NULL,
---
--- PRIMARY KEY old_id (old_id)
--- );
-
-
--- Lock!
-LOCK TABLES /*$wgDBprefix*/page WRITE, /*$wgDBprefix*/revision WRITE, /*$wgDBprefix*/old WRITE, /*$wgDBprefix*/cur WRITE;
-
--- Save the last old_id value for later
-SELECT (@maxold:=MAX(old_id)) FROM /*$wgDBprefix*/old;
-
--- First, copy all current entries into the old table.
-INSERT
- INTO /*$wgDBprefix*/old
- (old_namespace,
- old_title,
- old_text,
- old_comment,
- old_user,
- old_user_text,
- old_timestamp,
- old_minor_edit,
- old_flags)
- SELECT
- cur_namespace,
- cur_title,
- cur_text,
- cur_comment,
- cur_user,
- cur_user_text,
- cur_timestamp,
- cur_minor_edit,
- ''
- FROM /*$wgDBprefix*/cur;
-
--- Now, copy all old data except the text into revisions
-INSERT
- INTO /*$wgDBprefix*/revision
- (rev_id,
- rev_page,
- rev_comment,
- rev_user,
- rev_user_text,
- rev_timestamp,
- rev_minor_edit)
- SELECT
- old_id,
- cur_id,
- old_comment,
- old_user,
- old_user_text,
- old_timestamp,
- old_minor_edit
- FROM /*$wgDBprefix*/old,/*$wgDBprefix*/cur
- WHERE old_namespace=cur_namespace
- AND old_title=cur_title;
-
--- And, copy the cur data into page
-INSERT
- INTO /*$wgDBprefix*/page
- (page_id,
- page_namespace,
- page_title,
- page_restrictions,
- page_counter,
- page_is_redirect,
- page_is_new,
- page_random,
- page_touched,
- page_latest)
- SELECT
- cur_id,
- cur_namespace,
- cur_title,
- cur_restrictions,
- cur_counter,
- cur_is_redirect,
- cur_is_new,
- cur_random,
- cur_touched,
- rev_id
- FROM /*$wgDBprefix*/cur,/*$wgDBprefix*/revision
- WHERE cur_id=rev_page
- AND rev_timestamp=cur_timestamp
- AND rev_id > @maxold;
-
-UNLOCK TABLES;
-
--- Keep the old table around as the text store.
--- Its extra fields will be ignored, but trimming them is slow
--- so we won't bother doing it for now.
-ALTER TABLE /*$wgDBprefix*/old RENAME TO /*$wgDBprefix*/text;
diff --git a/maintenance/archives/patch-tl_from_namespace.sql b/maintenance/archives/patch-tl_from_namespace.sql
new file mode 100644
index 00000000..8d6c76b8
--- /dev/null
+++ b/maintenance/archives/patch-tl_from_namespace.sql
@@ -0,0 +1,4 @@
+ALTER TABLE /*_*/templatelinks
+ ADD COLUMN tl_from_namespace int NOT NULL default 0;
+
+CREATE INDEX /*i*/tl_backlinks_namespace ON /*_*/templatelinks (tl_namespace,tl_title,tl_from_namespace,tl_from);
diff --git a/maintenance/archives/patch-uploadstash.sql b/maintenance/archives/patch-uploadstash.sql
index 14eaeab0..c1d93ef3 100644
--- a/maintenance/archives/patch-uploadstash.sql
+++ b/maintenance/archives/patch-uploadstash.sql
@@ -26,10 +26,10 @@ CREATE TABLE /*_*/uploadstash (
us_status varchar(50) not null,
- -- file properties from File::getPropsFromPath. these may prove unnecessary.
+ -- file properties from FSFile::getProps(). these may prove unnecessary.
--
us_size int unsigned NOT NULL,
- -- this hash comes from File::sha1Base36(), and is 31 characters
+ -- this hash comes from FSFile::getSha1Base36(), and is 31 characters
us_sha1 varchar(31) NOT NULL,
us_mime varchar(255),
-- Media type as defined by the MEDIATYPE_xxx constants, should duplicate definition in the image table
diff --git a/maintenance/archives/patch-user_password_expire.sql b/maintenance/archives/patch-user_password_expire.sql
new file mode 100644
index 00000000..3e716d33
--- /dev/null
+++ b/maintenance/archives/patch-user_password_expire.sql
@@ -0,0 +1,3 @@
+-- For setting a password expiration date for users
+ALTER TABLE /*$wgDBprefix*/user
+ ADD COLUMN user_password_expires varbinary(14) DEFAULT NULL;
diff --git a/maintenance/archives/patch-val_ip.sql b/maintenance/archives/patch-val_ip.sql
deleted file mode 100644
index 9214218d..00000000
--- a/maintenance/archives/patch-val_ip.sql
+++ /dev/null
@@ -1,4 +0,0 @@
--- Column added 2005-05-24
-
-ALTER TABLE /*$wgDBprefix*/validate
- ADD COLUMN val_ip varchar(20) NOT NULL default '';
diff --git a/maintenance/archives/patch-validate.sql b/maintenance/archives/patch-validate.sql
deleted file mode 100644
index 9701083c..00000000
--- a/maintenance/archives/patch-validate.sql
+++ /dev/null
@@ -1,13 +0,0 @@
--- For article validation
-
-DROP TABLE IF EXISTS /*$wgDBprefix*/validate;
-CREATE TABLE /*$wgDBprefix*/validate (
- `val_user` int(11) NOT NULL default '0',
- `val_page` int(11) unsigned NOT NULL default '0',
- `val_revision` int(11) unsigned NOT NULL default '0',
- `val_type` int(11) unsigned NOT NULL default '0',
- `val_value` int(11) default '0',
- `val_comment` varchar(255) NOT NULL default '',
- `val_ip` varchar(20) NOT NULL default '',
- KEY `val_user` (`val_user`,`val_revision`)
-) /*$wgDBTableOptions*/;
diff --git a/maintenance/archives/patch-watchlist-user-notificationtimestamp-index.sql b/maintenance/archives/patch-watchlist-user-notificationtimestamp-index.sql
new file mode 100644
index 00000000..22ae44f1
--- /dev/null
+++ b/maintenance/archives/patch-watchlist-user-notificationtimestamp-index.sql
@@ -0,0 +1,4 @@
+--
+-- Creates the wl_user_notificationtimestamp index for the watchlist table
+--
+CREATE INDEX /*i*/wl_user_notificationtimestamp ON /*_*/watchlist (wl_user, wl_notificationtimestamp);
diff --git a/maintenance/archives/upgradeLogging.php b/maintenance/archives/upgradeLogging.php
index 0749bbf6..aeadc93d 100644
--- a/maintenance/archives/upgradeLogging.php
+++ b/maintenance/archives/upgradeLogging.php
@@ -52,6 +52,7 @@ class UpdateLogging {
if ( $this->dbw->tableExists( 'logging_pre_1_10' ) ) {
echo "This script has already been run to completion\n";
+
return;
}
@@ -124,6 +125,8 @@ EOT;
/**
* Copy all rows from $srcTable to $dstTable
+ * @param string $srcTable
+ * @param string $dstTable
*/
function sync( $srcTable, $dstTable ) {
$batchSize = 1000;
@@ -158,7 +161,7 @@ EOT;
$srcRes = $this->dbw->select( $srcTable, '*', $conds, __METHOD__,
array( 'LIMIT' => $batchSize, 'ORDER BY' => 'log_timestamp' ) );
- if ( ! $srcRes->numRows() ) {
+ if ( !$srcRes->numRows() ) {
# All done
break;
}
@@ -205,6 +208,7 @@ EOT;
}
}
}
+
return $numRowsCopied;
}
}
diff --git a/maintenance/attachLatest.php b/maintenance/attachLatest.php
index 2cf277fe..fba6b92d 100644
--- a/maintenance/attachLatest.php
+++ b/maintenance/attachLatest.php
@@ -3,7 +3,7 @@
* Corrects wrong values in the `page_latest` field in the database.
*
* Copyright © 2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,19 +33,24 @@ require_once __DIR__ . '/Maintenance.php';
* @ingroup Maintenance
*/
class AttachLatest extends Maintenance {
-
public function __construct() {
parent::__construct();
$this->addOption( "fix", "Actually fix the entries, will dry run otherwise" );
+ $this->addOption( "regenerate-all",
+ "Regenerate the page_latest field for all records in table page" );
$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 );
+ $conds = array( 'page_latest' => 0 );
+ if ( $this->hasOption( 'regenerate-all' ) ) {
+ $conds = '';
+ }
$result = $dbw->select( 'page',
array( 'page_id', 'page_namespace', 'page_title' ),
- array( 'page_latest' => 0 ),
+ $conds,
__METHOD__ );
$n = 0;
@@ -64,7 +69,8 @@ class AttachLatest extends Maintenance {
$revision = Revision::loadFromTimestamp( $dbw, $title, $latestTime );
if ( is_null( $revision ) ) {
- $this->output( wfWikiID() . " $pageId [[$name]] latest time $latestTime, can't find revision id\n" );
+ $this->output( wfWikiID()
+ . " $pageId [[$name]] latest time $latestTime, can't find revision id\n" );
continue;
}
$id = $revision->getId();
diff --git a/maintenance/backup.inc b/maintenance/backup.inc
index 3dc94c88..222c538b 100644
--- a/maintenance/backup.inc
+++ b/maintenance/backup.inc
@@ -3,7 +3,7 @@
* Base classes for database dumpers
*
* Copyright © 2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,28 +37,30 @@ class DumpDBZip2Output extends DumpPipeOutput {
* @ingroup Dump Maintenance
*/
class BackupDumper {
- var $reportingInterval = 100;
- var $reporting = true;
- var $pageCount = 0;
- var $revCount = 0;
- var $server = null; // use default
- var $pages = null; // all pages
- var $skipHeader = false; // don't output <mediawiki> and <siteinfo>
- var $skipFooter = false; // don't output </mediawiki>
- var $startId = 0;
- var $endId = 0;
- var $revStartId = 0;
- var $revEndId = 0;
- var $sink = null; // Output filters
- var $stubText = false; // include rev_text_id instead of text; for 2-pass dump
- var $dumpUploads = false;
- var $dumpUploadFileContents = false;
- var $lastTime = 0;
- var $pageCountLast = 0;
- var $revCountLast = 0;
- var $ID = 0;
-
- var $outputTypes = array(), $filterTypes = array();
+ public $reporting = true;
+ public $pages = null; // all pages
+ public $skipHeader = false; // don't output <mediawiki> and <siteinfo>
+ public $skipFooter = false; // don't output </mediawiki>
+ public $startId = 0;
+ public $endId = 0;
+ public $revStartId = 0;
+ public $revEndId = 0;
+ public $dumpUploads = false;
+ public $dumpUploadFileContents = false;
+
+ protected $reportingInterval = 100;
+ protected $pageCount = 0;
+ protected $revCount = 0;
+ protected $server = null; // use default
+ protected $sink = null; // Output filters
+ protected $lastTime = 0;
+ protected $pageCountLast = 0;
+ protected $revCountLast = 0;
+
+ protected $outputTypes = array();
+ protected $filterTypes = array();
+
+ protected $ID = 0;
/**
* The dependency-injected database to use.
@@ -69,11 +71,12 @@ class BackupDumper {
*/
protected $forcedDb = null;
- /**
- * @var LoadBalancer
- */
+ /** @var LoadBalancer */
protected $lb;
+ // @todo Unused?
+ private $stubText = false; // include rev_text_id instead of text; for 2-pass dump
+
function __construct( $args ) {
$this->stderr = fopen( "php://stderr", "wt" );
@@ -92,16 +95,16 @@ class BackupDumper {
}
/**
- * @param $name String
- * @param $class String: name of output filter plugin class
+ * @param string $name
+ * @param string $class Name of output filter plugin class
*/
function registerOutput( $name, $class ) {
$this->outputTypes[$name] = $class;
}
/**
- * @param $name String
- * @param $class String: name of filter plugin class
+ * @param string $name
+ * @param string $class Name of filter plugin class
*/
function registerFilter( $name, $class ) {
$this->filterTypes[$name] = $class;
@@ -110,9 +113,9 @@ class BackupDumper {
/**
* Load a plugin and register it
*
- * @param $class String: name of plugin class; must have a static 'register'
- * method that takes a BackupDumper as a parameter.
- * @param $file String: full or relative path to the PHP file to load, or empty
+ * @param string $class Name of plugin class; must have a static 'register'
+ * method that takes a BackupDumper as a parameter.
+ * @param string $file Full or relative path to the PHP file to load, or empty
*/
function loadPlugin( $class, $file ) {
if ( $file != '' ) {
@@ -123,8 +126,8 @@ class BackupDumper {
}
/**
- * @param $args Array
- * @return Array
+ * @param array $args
+ * @return array
*/
function processArgs( $args ) {
$sink = null;
@@ -132,50 +135,53 @@ class BackupDumper {
foreach ( $args as $arg ) {
$matches = array();
if ( preg_match( '/^--(.+?)(?:=(.+?)(?::(.+?))?)?$/', $arg, $matches ) ) {
- @list( /* $full */ , $opt, $val, $param ) = $matches;
+ wfSuppressWarnings();
+ list( /* $full */, $opt, $val, $param ) = $matches;
+ wfRestoreWarnings();
+
switch ( $opt ) {
- case "plugin":
- $this->loadPlugin( $val, $param );
- break;
- case "output":
- if ( !is_null( $sink ) ) {
- $sinks[] = $sink;
- }
- if ( !isset( $this->outputTypes[$val] ) ) {
- $this->fatalError( "Unrecognized output sink type '$val'" );
- }
- $type = $this->outputTypes[$val];
- $sink = new $type( $param );
- break;
- case "filter":
- if ( is_null( $sink ) ) {
- $sink = new DumpOutput();
- }
- if ( !isset( $this->filterTypes[$val] ) ) {
- $this->fatalError( "Unrecognized filter type '$val'" );
- }
- $type = $this->filterTypes[$val];
- $filter = new $type( $sink, $param );
-
- // references are lame in php...
- unset( $sink );
- $sink = $filter;
-
- break;
- case "report":
- $this->reportingInterval = intval( $val );
- break;
- case "server":
- $this->server = $val;
- break;
- case "force-normal":
- if ( !function_exists( 'utf8_normalize' ) ) {
- $this->fatalError( "UTF-8 normalization extension not loaded. " .
- "Install or remove --force-normal parameter to use slower code." );
- }
- break;
- default:
- $this->processOption( $opt, $val, $param );
+ case "plugin":
+ $this->loadPlugin( $val, $param );
+ break;
+ case "output":
+ if ( !is_null( $sink ) ) {
+ $sinks[] = $sink;
+ }
+ if ( !isset( $this->outputTypes[$val] ) ) {
+ $this->fatalError( "Unrecognized output sink type '$val'" );
+ }
+ $type = $this->outputTypes[$val];
+ $sink = new $type( $param );
+ break;
+ case "filter":
+ if ( is_null( $sink ) ) {
+ $sink = new DumpOutput();
+ }
+ if ( !isset( $this->filterTypes[$val] ) ) {
+ $this->fatalError( "Unrecognized filter type '$val'" );
+ }
+ $type = $this->filterTypes[$val];
+ $filter = new $type( $sink, $param );
+
+ // references are lame in php...
+ unset( $sink );
+ $sink = $filter;
+
+ break;
+ case "report":
+ $this->reportingInterval = intval( $val );
+ break;
+ case "server":
+ $this->server = $val;
+ break;
+ case "force-normal":
+ if ( !function_exists( 'utf8_normalize' ) ) {
+ $this->fatalError( "UTF-8 normalization extension not loaded. " .
+ "Install or remove --force-normal parameter to use slower code." );
+ }
+ break;
+ default:
+ $this->processOption( $opt, $val, $param );
}
}
}
@@ -223,8 +229,8 @@ class BackupDumper {
} else {
$exporter->allLogs();
}
- # Page dumps: all or by page ID range
} elseif ( is_null( $this->pages ) ) {
+ # Page dumps: all or by page ID range
if ( $this->startId || $this->endId ) {
$exporter->pagesByRange( $this->startId, $this->endId );
} elseif ( $this->revStartId || $this->revEndId ) {
@@ -232,8 +238,8 @@ class BackupDumper {
} else {
$exporter->allPages();
}
- # Dump of specific pages
} else {
+ # Dump of specific pages
$exporter->pagesByName( $this->pages );
}
@@ -248,7 +254,7 @@ class BackupDumper {
* Initialise starting time and maximum revision count.
* We'll make ETA calculations based an progress, assuming relatively
* constant per-revision rate.
- * @param $history Integer: WikiExporter::CURRENT or WikiExporter::FULL
+ * @param int $history WikiExporter::CURRENT or WikiExporter::FULL
*/
function initProgress( $history = WikiExporter::FULL ) {
$table = ( $history == WikiExporter::CURRENT ) ? 'page' : 'revision';
@@ -276,7 +282,7 @@ class BackupDumper {
}
$this->lb = wfGetLBFactory()->newMainLB();
- $db = $this->lb->getConnection( DB_SLAVE, 'backup' );
+ $db = $this->lb->getConnection( DB_SLAVE, 'dump' );
// Discourage the server from disconnecting us if it takes a long time
// to read out the big ol' batch query.
@@ -289,9 +295,8 @@ class BackupDumper {
* Force the dump to use the provided database connection for database
* operations, wherever possible.
*
- * @param $db DatabaseBase|null: (Optional) the database connection to
- * use. If null, resort to use the globally provided ways to
- * get database connections.
+ * @param DatabaseBase|null $db (Optional) the database connection to use. If null, resort to
+ * use the globally provided ways to get database connections.
*/
function setDb( DatabaseBase $db = null ) {
$this->forcedDb = $db;
@@ -305,6 +310,7 @@ class BackupDumper {
function backupServer() {
global $wgDBserver;
+
return $this->server
? $this->server
: $wgDBserver;
@@ -352,8 +358,13 @@ class BackupDumper {
$pageRatePart = '-';
$revRatePart = '-';
}
- $this->progress( sprintf( "%s: %s (ID %d) %d pages (%0.1f|%0.1f/sec all|curr), %d revs (%0.1f|%0.1f/sec all|curr), ETA %s [max %d]",
- $now, wfWikiID(), $this->ID, $this->pageCount, $pageRate, $pageRatePart, $this->revCount, $revRate, $revRatePart, $etats, $this->maxCount ) );
+ $this->progress( sprintf(
+ "%s: %s (ID %d) %d pages (%0.1f|%0.1f/sec all|curr), "
+ . "%d revs (%0.1f|%0.1f/sec all|curr), ETA %s [max %d]",
+ $now, wfWikiID(), $this->ID, $this->pageCount, $pageRate,
+ $pageRatePart, $this->revCount, $revRate, $revRatePart, $etats,
+ $this->maxCount
+ ) );
$this->lastTime = $nowts;
$this->revCountLast = $this->revCount;
}
diff --git a/maintenance/backupPrefetch.inc b/maintenance/backupPrefetch.inc
index 04352b9b..7bfb7345 100644
--- a/maintenance/backupPrefetch.inc
+++ b/maintenance/backupPrefetch.inc
@@ -3,7 +3,7 @@
* Helper class for the --prefetch option of dumpTextPass.php
*
* Copyright © 2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -40,21 +40,20 @@
* @ingroup Maintenance
*/
class BaseDump {
- var $reader = null;
- var $atEnd = false;
- var $atPageEnd = false;
- var $lastPage = 0;
- var $lastRev = 0;
- var $infiles = null;
-
- function BaseDump( $infile ) {
+ protected $reader = null;
+ protected $atEnd = false;
+ protected $atPageEnd = false;
+ protected $lastPage = 0;
+ protected $lastRev = 0;
+ protected $infiles = null;
+
+ public function __construct( $infile ) {
$this->infiles = explode( ';', $infile );
$this->reader = new XMLReader();
$infile = array_shift( $this->infiles );
if ( defined( 'LIBXML_PARSEHUGE' ) ) {
$this->reader->open( $infile, null, LIBXML_PARSEHUGE );
- }
- else {
+ } else {
$this->reader->open( $infile );
}
}
@@ -64,9 +63,9 @@ class BaseDump {
* from the dump stream. May return null if the page is
* unavailable.
*
- * @param $page Integer: ID number of page to read
- * @param $rev Integer: ID number of revision to read
- * @return string or null
+ * @param int $page ID number of page to read
+ * @param int $rev ID number of revision to read
+ * @return string|null
*/
function prefetch( $page, $rev ) {
$page = intval( $page );
@@ -76,18 +75,24 @@ class BaseDump {
$this->nextPage();
}
if ( $this->lastPage > $page || $this->atEnd ) {
- $this->debug( "BaseDump::prefetch already past page $page looking for rev $rev [$this->lastPage, $this->lastRev]" );
+ $this->debug( "BaseDump::prefetch already past page $page "
+ . "looking for rev $rev [$this->lastPage, $this->lastRev]" );
+
return null;
}
while ( $this->lastRev < $rev && !$this->atEnd && !$this->atPageEnd ) {
- $this->debug( "BaseDump::prefetch at page $this->lastPage, rev $this->lastRev, looking for $page, $rev" );
+ $this->debug( "BaseDump::prefetch at page $this->lastPage, rev $this->lastRev, "
+ . "looking for $page, $rev" );
$this->nextRev();
}
if ( $this->lastRev == $rev && !$this->atEnd ) {
$this->debug( "BaseDump::prefetch hit on $page, $rev [$this->lastPage, $this->lastRev]" );
+
return $this->nextText();
} else {
- $this->debug( "BaseDump::prefetch already past rev $rev on page $page [$this->lastPage, $this->lastRev]" );
+ $this->debug( "BaseDump::prefetch already past rev $rev on page $page "
+ . "[$this->lastPage, $this->lastRev]" );
+
return null;
}
}
@@ -137,13 +142,14 @@ class BaseDump {
*/
function nextText() {
$this->skipTo( 'text' );
+
return strval( $this->nodeContents() );
}
/**
* @access private
- * @param $name string
- * @param $parent string
+ * @param string $name
+ * @param string $parent
* @return bool|null
*/
function skipTo( $name, $parent = 'page' ) {
@@ -151,16 +157,20 @@ class BaseDump {
return false;
}
while ( $this->reader->read() ) {
- if ( $this->reader->nodeType == XMLReader::ELEMENT &&
- $this->reader->name == $name ) {
+ if ( $this->reader->nodeType == XMLReader::ELEMENT
+ && $this->reader->name == $name
+ ) {
return true;
}
- if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
- $this->reader->name == $parent ) {
+ if ( $this->reader->nodeType == XMLReader::END_ELEMENT
+ && $this->reader->name == $parent
+ ) {
$this->debug( "BaseDump::skipTo found </$parent> searching for <$name>" );
+
return false;
}
}
+
return $this->close();
}
@@ -169,7 +179,7 @@ class BaseDump {
* Fetches text contents of the current element, assuming
* no sub-elements or such scary things.
*
- * @return String
+ * @return string
* @access private
*/
function nodeContents() {
@@ -182,15 +192,16 @@ class BaseDump {
$buffer = "";
while ( $this->reader->read() ) {
switch ( $this->reader->nodeType ) {
- case XMLReader::TEXT:
-// case XMLReader::WHITESPACE:
- case XMLReader::SIGNIFICANT_WHITESPACE:
- $buffer .= $this->reader->value;
- break;
- case XMLReader::END_ELEMENT:
- return $buffer;
+ case XMLReader::TEXT:
+ //case XMLReader::WHITESPACE:
+ case XMLReader::SIGNIFICANT_WHITESPACE:
+ $buffer .= $this->reader->value;
+ break;
+ case XMLReader::END_ELEMENT:
+ return $buffer;
}
}
+
return $this->close();
}
@@ -201,6 +212,7 @@ class BaseDump {
function close() {
$this->reader->close();
$this->atEnd = true;
+
return null;
}
}
diff --git a/maintenance/backupTextPass.inc b/maintenance/backupTextPass.inc
index c515c6fe..5f776373 100644
--- a/maintenance/backupTextPass.inc
+++ b/maintenance/backupTextPass.inc
@@ -3,7 +3,7 @@
* BackupDumper that postprocesses XML dumps from dumpBackup.php to add page text
*
* Copyright (C) 2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,59 +30,60 @@ require_once __DIR__ . '/backup.inc';
* @ingroup Maintenance
*/
class TextPassDumper extends BackupDumper {
- var $prefetch = null;
- var $input = "php://stdin";
- var $history = WikiExporter::FULL;
- var $fetchCount = 0;
- var $prefetchCount = 0;
- var $prefetchCountLast = 0;
- var $fetchCountLast = 0;
+ public $prefetch = null;
- var $maxFailures = 5;
- var $maxConsecutiveFailedTextRetrievals = 200;
- var $failureTimeout = 5; // Seconds to sleep after db failure
+ // when we spend more than maxTimeAllowed seconds on this run, we continue
+ // processing until we write out the next complete page, then save output file(s),
+ // rename it/them and open new one(s)
+ public $maxTimeAllowed = 0; // 0 = no limit
- var $php = "php";
- var $spawn = false;
+ protected $input = "php://stdin";
+ protected $history = WikiExporter::FULL;
+ protected $fetchCount = 0;
+ protected $prefetchCount = 0;
+ protected $prefetchCountLast = 0;
+ protected $fetchCountLast = 0;
+
+ protected $maxFailures = 5;
+ protected $maxConsecutiveFailedTextRetrievals = 200;
+ protected $failureTimeout = 5; // Seconds to sleep after db failure
+
+ protected $php = "php";
+ protected $spawn = false;
/**
* @var bool|resource
*/
- var $spawnProc = false;
+ protected $spawnProc = false;
/**
* @var bool|resource
*/
- var $spawnWrite = false;
+ protected $spawnWrite = false;
/**
* @var bool|resource
*/
- var $spawnRead = false;
+ protected $spawnRead = false;
/**
* @var bool|resource
*/
- var $spawnErr = false;
+ protected $spawnErr = false;
- var $xmlwriterobj = false;
+ protected $xmlwriterobj = false;
- // when we spend more than maxTimeAllowed seconds on this run, we continue
- // processing until we write out the next complete page, then save output file(s),
- // rename it/them and open new one(s)
- var $maxTimeAllowed = 0; // 0 = no limit
- var $timeExceeded = false;
- var $firstPageWritten = false;
- var $lastPageWritten = false;
- var $checkpointJustWritten = false;
- var $checkpointFiles = array();
+ protected $timeExceeded = false;
+ protected $firstPageWritten = false;
+ protected $lastPageWritten = false;
+ protected $checkpointJustWritten = false;
+ protected $checkpointFiles = array();
/**
* @var DatabaseBase
*/
protected $db;
-
/**
* Drop the database connection $this->db and try to get a new one.
*
@@ -103,6 +104,7 @@ class TextPassDumper extends BackupDumper {
if ( $this->forcedDb !== null ) {
$this->db = $this->forcedDb;
+
return;
}
@@ -120,19 +122,19 @@ class TextPassDumper extends BackupDumper {
try {
$this->lb = wfGetLBFactory()->newMainLB();
} catch ( Exception $e ) {
- throw new MWException( __METHOD__ . " rotating DB failed to obtain new load balancer (" . $e->getMessage() . ")" );
+ throw new MWException( __METHOD__
+ . " rotating DB failed to obtain new load balancer (" . $e->getMessage() . ")" );
}
-
// 2. The Connection, through the load balancer.
try {
- $this->db = $this->lb->getConnection( DB_SLAVE, 'backup' );
+ $this->db = $this->lb->getConnection( DB_SLAVE, 'dump' );
} catch ( Exception $e ) {
- throw new MWException( __METHOD__ . " rotating DB failed to obtain new database (" . $e->getMessage() . ")" );
+ throw new MWException( __METHOD__
+ . " rotating DB failed to obtain new database (" . $e->getMessage() . ")" );
}
}
-
function initProgress( $history = WikiExporter::FULL ) {
parent::initProgress();
$this->timeOfCheckpoint = $this->startTime;
@@ -184,31 +186,31 @@ class TextPassDumper extends BackupDumper {
$url = $this->processFileOpt( $val, $param );
switch ( $opt ) {
- case 'prefetch':
- require_once "$IP/maintenance/backupPrefetch.inc";
- $this->prefetch = new BaseDump( $url );
- break;
- case 'stub':
- $this->input = $url;
- break;
- case 'maxtime':
- $this->maxTimeAllowed = intval( $val ) * 60;
- break;
- case 'checkpointfile':
- $this->checkpointFiles[] = $val;
- break;
- case 'current':
- $this->history = WikiExporter::CURRENT;
- break;
- case 'full':
- $this->history = WikiExporter::FULL;
- break;
- case 'spawn':
- $this->spawn = true;
- if ( $val ) {
- $this->php = $val;
- }
- break;
+ case 'prefetch':
+ require_once "$IP/maintenance/backupPrefetch.inc";
+ $this->prefetch = new BaseDump( $url );
+ break;
+ case 'stub':
+ $this->input = $url;
+ break;
+ case 'maxtime':
+ $this->maxTimeAllowed = intval( $val ) * 60;
+ break;
+ case 'checkpointfile':
+ $this->checkpointFiles[] = $val;
+ break;
+ case 'current':
+ $this->history = WikiExporter::CURRENT;
+ break;
+ case 'full':
+ $this->history = WikiExporter::FULL;
+ break;
+ case 'spawn':
+ $this->spawn = true;
+ if ( $val ) {
+ $this->php = $val;
+ }
+ break;
}
}
@@ -234,6 +236,7 @@ class TextPassDumper extends BackupDumper {
$newFileURIs[] = $newURI;
}
$val = implode( ';', $newFileURIs );
+
return $val;
}
@@ -243,6 +246,7 @@ class TextPassDumper extends BackupDumper {
function showReport() {
if ( !$this->prefetch ) {
parent::showReport();
+
return;
}
@@ -279,14 +283,19 @@ class TextPassDumper extends BackupDumper {
}
$pageRatePart = $this->pageCountPart / $deltaPart;
$revRatePart = $this->revCountPart / $deltaPart;
-
} else {
$fetchRatePart = '-';
$pageRatePart = '-';
$revRatePart = '-';
}
- $this->progress( sprintf( "%s: %s (ID %d) %d pages (%0.1f|%0.1f/sec all|curr), %d revs (%0.1f|%0.1f/sec all|curr), %0.1f%%|%0.1f%% prefetched (all|curr), ETA %s [max %d]",
- $now, wfWikiID(), $this->ID, $this->pageCount, $pageRate, $pageRatePart, $this->revCount, $revRate, $revRatePart, $fetchRate, $fetchRatePart, $etats, $this->maxCount ) );
+ $this->progress( sprintf(
+ "%s: %s (ID %d) %d pages (%0.1f|%0.1f/sec all|curr), "
+ . "%d revs (%0.1f|%0.1f/sec all|curr), %0.1f%%|%0.1f%% "
+ . "prefetched (all|curr), ETA %s [max %d]",
+ $now, wfWikiID(), $this->ID, $this->pageCount, $pageRate,
+ $pageRatePart, $this->revCount, $revRate, $revRatePart,
+ $fetchRate, $fetchRatePart, $etats, $this->maxCount
+ ) );
$this->lastTime = $nowts;
$this->revCountLast = $this->revCount;
$this->prefetchCountLast = $this->prefetchCount;
@@ -299,35 +308,43 @@ class TextPassDumper extends BackupDumper {
}
function checkIfTimeExceeded() {
- if ( $this->maxTimeAllowed && ( $this->lastTime - $this->timeOfCheckpoint > $this->maxTimeAllowed ) ) {
+ if ( $this->maxTimeAllowed
+ && ( $this->lastTime - $this->timeOfCheckpoint > $this->maxTimeAllowed )
+ ) {
return true;
}
+
return false;
}
function finalOptionCheck() {
- if ( ( $this->checkpointFiles && ! $this->maxTimeAllowed ) ||
- ( $this->maxTimeAllowed && !$this->checkpointFiles ) ) {
+ if ( ( $this->checkpointFiles && !$this->maxTimeAllowed )
+ || ( $this->maxTimeAllowed && !$this->checkpointFiles )
+ ) {
throw new MWException( "Options checkpointfile and maxtime must be specified together.\n" );
}
foreach ( $this->checkpointFiles as $checkpointFile ) {
- $count = substr_count ( $checkpointFile, "%s" );
+ $count = substr_count( $checkpointFile, "%s" );
if ( $count != 2 ) {
- throw new MWException( "Option checkpointfile must contain two '%s' for substitution of first and last pageids, count is $count instead, file is $checkpointFile.\n" );
+ throw new MWException( "Option checkpointfile must contain two '%s' "
+ . "for substitution of first and last pageids, count is $count instead, "
+ . "file is $checkpointFile.\n" );
}
}
if ( $this->checkpointFiles ) {
$filenameList = (array)$this->egress->getFilenames();
if ( count( $filenameList ) != count( $this->checkpointFiles ) ) {
- throw new MWException( "One checkpointfile must be specified for each output option, if maxtime is used.\n" );
+ throw new MWException( "One checkpointfile must be specified "
+ . "for each output option, if maxtime is used.\n" );
}
}
}
/**
* @throws MWException Failure to parse XML input
- * @return true
+ * @param string $input
+ * @return bool
*/
function readDump( $input ) {
$this->buffer = "";
@@ -341,7 +358,11 @@ class TextPassDumper extends BackupDumper {
$parser = xml_parser_create( "UTF-8" );
xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
- xml_set_element_handler( $parser, array( &$this, 'startElement' ), array( &$this, 'endElement' ) );
+ xml_set_element_handler(
+ $parser,
+ array( &$this, 'startElement' ),
+ array( &$this, 'endElement' )
+ );
xml_set_character_data_handler( $parser, array( &$this, 'characterData' ) );
$offset = 0; // for context extraction on error reporting
@@ -359,7 +380,7 @@ class TextPassDumper extends BackupDumper {
'XML import parse failure',
xml_get_current_line_number( $parser ),
xml_get_current_column_number( $parser ),
- $byte . ( is_null( $chunk ) ? null : ( '; "' . substr( $chunk, $byte -$offset, 16 ) . '"' ) ),
+ $byte . ( is_null( $chunk ) ? null : ( '; "' . substr( $chunk, $byte - $offset, 16 ) . '"' ) ),
xml_error_string( xml_get_error_code( $parser ) ) )->escaped();
xml_parser_free( $parser );
@@ -378,15 +399,16 @@ class TextPassDumper extends BackupDumper {
# there's no pageID 0 so we use that. the caller is responsible
# for deciding what to do with a file containing only the
# siteinfo information and the mw tags.
- if ( ! $this->firstPageWritten ) {
+ if ( !$this->firstPageWritten ) {
$firstPageID = str_pad( 0, 9, "0", STR_PAD_LEFT );
$lastPageID = str_pad( 0, 9, "0", STR_PAD_LEFT );
- }
- else {
+ } else {
$firstPageID = str_pad( $this->firstPageWritten, 9, "0", STR_PAD_LEFT );
$lastPageID = str_pad( $this->lastPageWritten, 9, "0", STR_PAD_LEFT );
}
- for ( $i = 0; $i < count( $filenameList ); $i++ ) {
+
+ $filenameCount = count( $filenameList );
+ for ( $i = 0; $i < $filenameCount; $i++ ) {
$checkpointNameFilledIn = sprintf( $this->checkpointFiles[$i], $firstPageID, $lastPageID );
$fileinfo = pathinfo( $filenameList[$i] );
$newFilenames[] = $fileinfo['dirname'] . '/' . $checkpointNameFilledIn;
@@ -408,7 +430,7 @@ class TextPassDumper extends BackupDumper {
* $this->maxConsecutiveFailedTextRetrievals consecutive calls to getText, MWException
* is thrown.
*
- * @param $id string The revision id to get the text for
+ * @param string $id The revision id to get the text for
*
* @return string The revision text for $id, or ""
* @throws MWException
@@ -420,8 +442,8 @@ class TextPassDumper extends BackupDumper {
$text = false; // The candidate for a good text. false if no proper value.
$failures = 0; // The number of times, this invocation of getText already failed.
- static $consecutiveFailedTextRetrievals = 0; // The number of times getText failed without
- // yielding a good text in between.
+ // The number of times getText failed without yielding a good text in between.
+ static $consecutiveFailedTextRetrievals = 0;
$this->fetchCount++;
@@ -478,7 +500,7 @@ class TextPassDumper extends BackupDumper {
// Step 2: Checking for plausibility and return the text if it is
// plausible
$revID = intval( $this->thisRev );
- if ( ! isset( $this->db ) ) {
+ if ( !isset( $this->db ) ) {
throw new MWException( "No database available" );
}
@@ -497,9 +519,7 @@ class TextPassDumper extends BackupDumper {
$revLength = $row->rev_len;
}
}
-
- }
- else {
+ } else {
$revLength = $this->db->selectField( 'revision', 'rev_len', array( 'rev_id' => $revID ) );
}
@@ -507,12 +527,12 @@ class TextPassDumper extends BackupDumper {
if ( $tryIsPrefetch ) {
$this->prefetchCount++;
}
+
return $text;
}
$text = false;
throw new MWException( "Received text is unplausible for id " . $id );
-
} catch ( Exception $e ) {
$msg = "getting/checking text " . $id . " failed (" . $e->getMessage() . ")";
if ( $failures + 1 < $this->maxFailures ) {
@@ -525,7 +545,7 @@ class TextPassDumper extends BackupDumper {
$failures++;
// A failure in a prefetch hit does not warrant resetting db connection etc.
- if ( ! $tryIsPrefetch ) {
+ if ( !$tryIsPrefetch ) {
// After backing off for some time, we try to reboot the whole process as
// much as possible to not carry over failures from one part to the other
// parts
@@ -556,16 +576,15 @@ class TextPassDumper extends BackupDumper {
return "";
}
-
/**
* May throw a database error if, say, the server dies during query.
- * @param $id
+ * @param int $id
* @return bool|string
* @throws MWException
*/
private function getTextDb( $id ) {
global $wgContLang;
- if ( ! isset( $this->db ) ) {
+ if ( !isset( $this->db ) ) {
throw new MWException( __METHOD__ . "No database available" );
}
$row = $this->db->selectRow( 'text',
@@ -578,6 +597,7 @@ class TextPassDumper extends BackupDumper {
}
$stripped = str_replace( "\r", "", $text );
$normalized = $wgContLang->normalize( $stripped );
+
return $normalized;
}
@@ -589,6 +609,7 @@ class TextPassDumper extends BackupDumper {
}
$text = $this->getTextSpawnedOnce( $id );
wfRestoreWarnings();
+
return $text;
}
@@ -603,8 +624,7 @@ class TextPassDumper extends BackupDumper {
"$IP/../multiversion/MWScript.php",
"fetchText.php",
'--wiki', wfWikiID() ) ) );
- }
- else {
+ } else {
$cmd = implode( " ",
array_map( 'wfEscapeShellArg',
array(
@@ -623,11 +643,12 @@ class TextPassDumper extends BackupDumper {
if ( !$this->spawnProc ) {
// shit
$this->progress( "Subprocess spawn failed." );
+
return false;
}
list(
$this->spawnWrite, // -> stdin
- $this->spawnRead, // <- stdout
+ $this->spawnRead, // <- stdout
) = $pipes;
return true;
@@ -705,12 +726,14 @@ class TextPassDumper extends BackupDumper {
$gotbytes = strlen( $text );
if ( $gotbytes != $nbytes ) {
$this->progress( "Expected $nbytes bytes from database subprocess, got $gotbytes " );
+
return false;
}
// Do normalization in the dump thread...
$stripped = str_replace( "\r", "", $text );
$normalized = $wgContLang->normalize( $stripped );
+
return $normalized;
}
@@ -758,7 +781,7 @@ class TextPassDumper extends BackupDumper {
$this->buffer = "";
$this->thisRev = "";
} elseif ( $name == 'page' ) {
- if ( ! $this->firstPageWritten ) {
+ if ( !$this->firstPageWritten ) {
$this->firstPageWritten = trim( $this->thisPage );
}
$this->lastPageWritten = trim( $this->thisPage );
@@ -779,7 +802,8 @@ class TextPassDumper extends BackupDumper {
$newFilenames = array();
$firstPageID = str_pad( $this->firstPageWritten, 9, "0", STR_PAD_LEFT );
$lastPageID = str_pad( $this->lastPageWritten, 9, "0", STR_PAD_LEFT );
- for ( $i = 0; $i < count( $filenameList ); $i++ ) {
+ $filenamesCount = count( $filenameList );
+ for ( $i = 0; $i < $filenamesCount; $i++ ) {
$checkpointNameFilledIn = sprintf( $this->checkpointFiles[$i], $firstPageID, $lastPageID );
$fileinfo = pathinfo( $filenameList[$i] );
$newFilenames[] = $fileinfo['dirname'] . '/' . $checkpointNameFilledIn;
@@ -790,13 +814,11 @@ class TextPassDumper extends BackupDumper {
$this->timeOfCheckpoint = $this->lastTime;
$this->firstPageWritten = false;
$this->checkpointJustWritten = true;
- }
- else {
+ } else {
$this->egress->writeClosePage( $this->buffer );
$this->buffer = "";
$this->thisPage = "";
}
-
} elseif ( $name == 'mediawiki' ) {
$this->egress->writeCloseStream( $this->buffer );
$this->buffer = "";
diff --git a/maintenance/benchmarks/Benchmarker.php b/maintenance/benchmarks/Benchmarker.php
index dd558f32..3f8a8990 100644
--- a/maintenance/benchmarks/Benchmarker.php
+++ b/maintenance/benchmarks/Benchmarker.php
@@ -46,38 +46,38 @@ abstract class Benchmarker extends Maintenance {
$bench_number = 0;
$count = $this->getOption( 'count', 100 );
- foreach( $benchs as $bench ) {
+ foreach ( $benchs as $bench ) {
// handle empty args
- if( !array_key_exists( 'args', $bench ) ) {
+ if ( !array_key_exists( 'args', $bench ) ) {
$bench['args'] = array();
}
$bench_number++;
$start = microtime( true );
- for( $i = 0; $i < $count; $i++ ) {
+ for ( $i = 0; $i < $count; $i++ ) {
call_user_func_array( $bench['function'], $bench['args'] );
}
$delta = microtime( true ) - $start;
// function passed as a callback
- if( is_array( $bench['function'] ) ) {
+ if ( is_array( $bench['function'] ) ) {
$ret = get_class( $bench['function'][0] ) . '->' . $bench['function'][1];
$bench['function'] = $ret;
}
$this->results[$bench_number] = array(
- 'function' => $bench['function'],
+ 'function' => $bench['function'],
'arguments' => $bench['args'],
- 'count' => $count,
- 'delta' => $delta,
- 'average' => $delta / $count,
- );
+ 'count' => $count,
+ 'delta' => $delta,
+ 'average' => $delta / $count,
+ );
}
}
public function getFormattedResults() {
$ret = '';
- foreach( $this->results as $res ) {
+ foreach ( $this->results as $res ) {
// show function with args
$ret .= sprintf( "%s times: function %s(%s) :\n",
$res['count'],
@@ -89,6 +89,7 @@ abstract class Benchmarker extends Maintenance {
$res['average'] * 1000
);
}
+
return $ret;
}
}
diff --git a/maintenance/benchmarks/bench_HTTP_HTTPS.php b/maintenance/benchmarks/bench_HTTP_HTTPS.php
index 6f800fb3..bb7499b7 100644
--- a/maintenance/benchmarks/bench_HTTP_HTTPS.php
+++ b/maintenance/benchmarks/bench_HTTP_HTTPS.php
@@ -31,8 +31,7 @@ require_once __DIR__ . '/Benchmarker.php';
*
* @ingroup Benchmark
*/
-class bench_HTTP_HTTPS extends Benchmarker {
-
+class BenchHttpHttps extends Benchmarker {
public function __construct() {
parent::__construct();
$this->mDescription = "Benchmark HTTP request vs HTTPS request.";
@@ -42,7 +41,7 @@ class bench_HTTP_HTTPS extends Benchmarker {
$this->bench( array(
array( 'function' => array( $this, 'getHTTP' ) ),
array( 'function' => array( $this, 'getHTTPS' ) ),
- ));
+ ) );
print $this->getFormattedResults();
}
@@ -61,5 +60,5 @@ class bench_HTTP_HTTPS extends Benchmarker {
}
}
-$maintClass = 'bench_HTTP_HTTPS';
+$maintClass = 'BenchHttpHttps';
require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/benchmarks/bench_delete_truncate.php b/maintenance/benchmarks/bench_delete_truncate.php
index 3eff534b..8ae4f030 100644
--- a/maintenance/benchmarks/bench_delete_truncate.php
+++ b/maintenance/benchmarks/bench_delete_truncate.php
@@ -29,7 +29,6 @@ require_once __DIR__ . '/Benchmarker.php';
* @ingroup Benchmark
*/
class BenchmarkDeleteTruncate extends Benchmarker {
-
public function __construct() {
parent::__construct();
$this->mDescription = "Benchmarks SQL DELETE vs SQL TRUNCATE.";
@@ -70,20 +69,20 @@ class BenchmarkDeleteTruncate extends Benchmarker {
}
/**
- * @param $dbw DatabaseBase
+ * @param DatabaseBase $dbw
* @return void
*/
private function insertData( $dbw ) {
$range = range( 0, 1024 );
$data = array();
- foreach( $range as $r ) {
+ foreach ( $range as $r ) {
$data[] = array( 'text' => $r );
}
$dbw->insert( 'test', $data, __METHOD__ );
}
/**
- * @param $dbw DatabaseBase
+ * @param DatabaseBase $dbw
* @return void
*/
private function delete( $dbw ) {
@@ -91,7 +90,7 @@ class BenchmarkDeleteTruncate extends Benchmarker {
}
/**
- * @param $dbw DatabaseBase
+ * @param DatabaseBase $dbw
* @return void
*/
private function truncate( $dbw ) {
diff --git a/maintenance/benchmarks/bench_if_switch.php b/maintenance/benchmarks/bench_if_switch.php
index 80fd9623..698a0f0a 100644
--- a/maintenance/benchmarks/bench_if_switch.php
+++ b/maintenance/benchmarks/bench_if_switch.php
@@ -31,8 +31,7 @@ require_once __DIR__ . '/Benchmarker.php';
*
* @ingroup Maintenance
*/
-class bench_if_switch extends Benchmarker {
-
+class BenchIfSwitch extends Benchmarker {
public function __construct() {
parent::__construct();
$this->mDescription = "Benchmark if elseif... versus switch case.";
@@ -42,55 +41,71 @@ class bench_if_switch extends Benchmarker {
$this->bench( array(
array( 'function' => array( $this, 'doElseIf' ) ),
array( 'function' => array( $this, 'doSwitch' ) ),
- ));
+ ) );
print $this->getFormattedResults();
}
// bench function 1
function doElseIf() {
$a = 'z';
- if( $a == 'a') {}
- elseif( $a == 'b') {}
- elseif( $a == 'c') {}
- elseif( $a == 'd') {}
- elseif( $a == 'e') {}
- elseif( $a == 'f') {}
- elseif( $a == 'g') {}
- elseif( $a == 'h') {}
- elseif( $a == 'i') {}
- elseif( $a == 'j') {}
- elseif( $a == 'k') {}
- elseif( $a == 'l') {}
- elseif( $a == 'm') {}
- elseif( $a == 'n') {}
- elseif( $a == 'o') {}
- elseif( $a == 'p') {}
- else {}
+ if ( $a == 'a' ) {
+ } elseif ( $a == 'b' ) {
+ } elseif ( $a == 'c' ) {
+ } elseif ( $a == 'd' ) {
+ } elseif ( $a == 'e' ) {
+ } elseif ( $a == 'f' ) {
+ } elseif ( $a == 'g' ) {
+ } elseif ( $a == 'h' ) {
+ } elseif ( $a == 'i' ) {
+ } elseif ( $a == 'j' ) {
+ } elseif ( $a == 'k' ) {
+ } elseif ( $a == 'l' ) {
+ } elseif ( $a == 'm' ) {
+ } elseif ( $a == 'n' ) {
+ } elseif ( $a == 'o' ) {
+ } elseif ( $a == 'p' ) {
+ } else {
+ }
}
// bench function 2
function doSwitch() {
$a = 'z';
- switch( $a ) {
- case 'b': break;
- case 'c': break;
- case 'd': break;
- case 'e': break;
- case 'f': break;
- case 'g': break;
- case 'h': break;
- case 'i': break;
- case 'j': break;
- case 'k': break;
- case 'l': break;
- case 'm': break;
- case 'n': break;
- case 'o': break;
- case 'p': break;
+ switch ( $a ) {
+ case 'b':
+ break;
+ case 'c':
+ break;
+ case 'd':
+ break;
+ case 'e':
+ break;
+ case 'f':
+ break;
+ case 'g':
+ break;
+ case 'h':
+ break;
+ case 'i':
+ break;
+ case 'j':
+ break;
+ case 'k':
+ break;
+ case 'l':
+ break;
+ case 'm':
+ break;
+ case 'n':
+ break;
+ case 'o':
+ break;
+ case 'p':
+ break;
default:
}
}
}
-$maintClass = 'bench_if_switch';
+$maintClass = 'BenchIfSwitch';
require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/benchmarks/bench_strtr_str_replace.php b/maintenance/benchmarks/bench_strtr_str_replace.php
index bd21b186..44c8e032 100644
--- a/maintenance/benchmarks/bench_strtr_str_replace.php
+++ b/maintenance/benchmarks/bench_strtr_str_replace.php
@@ -38,8 +38,7 @@ function bfNormalizeTitleStrReplace( $str ) {
*
* @ingroup Benchmark
*/
-class bench_strtr_str_replace extends Benchmarker {
-
+class BenchStrtrStrReplace extends Benchmarker {
public function __construct() {
parent::__construct();
$this->mDescription = "Benchmark for strtr() vs str_replace().";
@@ -51,7 +50,7 @@ class bench_strtr_str_replace extends Benchmarker {
array( 'function' => array( $this, 'benchstr_replace' ) ),
array( 'function' => array( $this, 'benchstrtr_indirect' ) ),
array( 'function' => array( $this, 'benchstr_replace_indirect' ) ),
- ));
+ ) );
print $this->getFormattedResults();
}
@@ -60,10 +59,9 @@ class bench_strtr_str_replace extends Benchmarker {
}
function benchstr_replace() {
- str_replace( "_", " ", "[[MediaWiki:Some_random_test_page]]");
+ str_replace( "_", " ", "[[MediaWiki:Some_random_test_page]]" );
}
-
function benchstrtr_indirect() {
bfNormalizeTitleStrTr( "[[MediaWiki:Some_random_test_page]]" );
}
@@ -71,8 +69,7 @@ class bench_strtr_str_replace extends Benchmarker {
function benchstr_replace_indirect() {
bfNormalizeTitleStrReplace( "[[MediaWiki:Some_random_test_page]]" );
}
-
}
-$maintClass = 'bench_strtr_str_replace';
+$maintClass = 'BenchStrtrStrReplace';
require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/benchmarks/bench_utf8_title_check.php b/maintenance/benchmarks/bench_utf8_title_check.php
index 078293eb..b742f666 100644
--- a/maintenance/benchmarks/bench_utf8_title_check.php
+++ b/maintenance/benchmarks/bench_utf8_title_check.php
@@ -29,8 +29,7 @@ require_once __DIR__ . '/Benchmarker.php';
*
* @ingroup Benchmark
*/
-class bench_utf8_title_check extends Benchmarker {
-
+class BenchUtf8TitleCheck extends Benchmarker {
private $canRun;
private $data;
@@ -38,6 +37,7 @@ class bench_utf8_title_check extends Benchmarker {
public function __construct() {
parent::__construct();
+ // @codingStandardsIgnoreStart Ignore long line warnings.
$this->data = array(
"",
"United States of America", // 7bit ASCII
@@ -59,11 +59,13 @@ class bench_utf8_title_check extends Benchmarker {
. "Sara%20Sidle%7CSofia%20Curtis%7CS%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e%7CWallace%20Langham%7C"
. "Warrick%20Brown%7CWendy%20Simms%7C%C3%89tats-Unis"
);
+ // @codingStandardsIgnoreEnd
- $this->canRun = function_exists ( 'mb_check_encoding' );
+ $this->canRun = function_exists( 'mb_check_encoding' );
if ( $this->canRun ) {
- $this->mDescription = "Benchmark for using a regexp vs. mb_check_encoding to check for UTF-8 encoding.";
+ $this->mDescription = "Benchmark for using a regexp vs. mb_check_encoding " .
+ "to check for UTF-8 encoding.";
mb_internal_encoding( 'UTF-8' );
} else {
$this->mDescription = "CANNOT RUN benchmark using mb_check_encoding: function not available.";
@@ -75,22 +77,22 @@ class bench_utf8_title_check extends Benchmarker {
return;
}
$benchmarks = array();
- foreach ($this->data as $val) {
+ foreach ( $this->data as $val ) {
$benchmarks[] = array(
'function' => array( $this, 'use_regexp' ),
- 'args' => array( rawurldecode ( $val ) )
+ 'args' => array( rawurldecode( $val ) )
);
$benchmarks[] = array(
'function' => array( $this, 'use_regexp_non_capturing' ),
- 'args' => array( rawurldecode ( $val ) )
+ 'args' => array( rawurldecode( $val ) )
);
$benchmarks[] = array(
'function' => array( $this, 'use_regexp_once_only' ),
- 'args' => array( rawurldecode ( $val ) )
+ 'args' => array( rawurldecode( $val ) )
);
$benchmarks[] = array(
'function' => array( $this, 'use_mb_check_encoding' ),
- 'args' => array( rawurldecode ( $val ) )
+ 'args' => array( rawurldecode( $val ) )
);
}
$this->bench( $benchmarks );
@@ -101,26 +103,25 @@ class bench_utf8_title_check extends Benchmarker {
function use_regexp( $s ) {
$this->isutf8 = preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
- '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s );
+ '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s );
}
function use_regexp_non_capturing( $s ) {
// Same as above with a non-capturing subgroup.
$this->isutf8 = preg_match( '/^(?:[\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
- '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s );
+ '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s );
}
function use_regexp_once_only( $s ) {
// Same as above with a once-only subgroup.
$this->isutf8 = preg_match( '/^(?>[\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
- '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s );
+ '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s );
}
function use_mb_check_encoding( $s ) {
$this->isutf8 = mb_check_encoding( $s, 'UTF-8' );
}
-
}
-$maintClass = 'bench_utf8_title_check';
+$maintClass = 'BenchUtf8TitleCheck';
require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/benchmarks/bench_wfBaseConvert.php b/maintenance/benchmarks/bench_wfBaseConvert.php
index f8a21562..b4be12bc 100644
--- a/maintenance/benchmarks/bench_wfBaseConvert.php
+++ b/maintenance/benchmarks/bench_wfBaseConvert.php
@@ -29,8 +29,7 @@ require_once __DIR__ . '/Benchmarker.php';
*
* @ingroup Benchmark
*/
-class bench_wfBaseConvert extends Benchmarker {
-
+class BenchWfBaseConvert extends Benchmarker {
public function __construct() {
parent::__construct();
$this->mDescription = "Benchmark for wfBaseConvert.";
@@ -58,7 +57,7 @@ class bench_wfBaseConvert extends Benchmarker {
'function' => 'wfBaseConvert',
'args' => array( $number, $inbase, $outbase, 0, true, 'gmp' )
),
- ));
+ ) );
$this->output( $this->getFormattedResults() );
}
@@ -66,12 +65,13 @@ class bench_wfBaseConvert extends Benchmarker {
protected static function makeRandomNumber( $base, $length ) {
$baseChars = "0123456789abcdefghijklmnopqrstuvwxyz";
$res = "";
- for( $i = 0; $i < $length; $i++ ) {
- $res .= $baseChars[mt_rand(0, $base - 1)];
+ for ( $i = 0; $i < $length; $i++ ) {
+ $res .= $baseChars[mt_rand( 0, $base - 1 )];
}
+
return $res;
}
}
-$maintClass = 'bench_wfBaseConvert';
+$maintClass = 'BenchWfBaseConvert';
require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/benchmarks/bench_wfIsWindows.php b/maintenance/benchmarks/bench_wfIsWindows.php
index 1cd2016b..8446694b 100644
--- a/maintenance/benchmarks/bench_wfIsWindows.php
+++ b/maintenance/benchmarks/bench_wfIsWindows.php
@@ -31,8 +31,7 @@ require_once __DIR__ . '/Benchmarker.php';
*
* @ingroup Benchmark
*/
-class bench_wfIsWindows extends Benchmarker {
-
+class BenchWfIsWindows extends Benchmarker {
public function __construct() {
parent::__construct();
$this->mDescription = "Benchmark for wfIsWindows.";
@@ -42,12 +41,12 @@ class bench_wfIsWindows extends Benchmarker {
$this->bench( array(
array( 'function' => array( $this, 'wfIsWindows' ) ),
array( 'function' => array( $this, 'wfIsWindowsCached' ) ),
- ));
+ ) );
print $this->getFormattedResults();
}
static function is_win() {
- return substr( php_uname(), 0, 7 ) == 'Windows' ;
+ return substr( php_uname(), 0, 7 ) == 'Windows';
}
// bench function 1
@@ -58,12 +57,13 @@ class bench_wfIsWindows extends Benchmarker {
// bench function 2
function wfIsWindowsCached() {
static $isWindows = null;
- if( $isWindows == null ) {
+ if ( $isWindows == null ) {
$isWindows = self::is_win();
}
+
return $isWindows;
}
}
-$maintClass = 'bench_wfIsWindows';
+$maintClass = 'BenchWfIsWindows';
require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/benchmarks/benchmarkHooks.php b/maintenance/benchmarks/benchmarkHooks.php
index 3f5d6db0..fb25b9d9 100644
--- a/maintenance/benchmarks/benchmarkHooks.php
+++ b/maintenance/benchmarks/benchmarkHooks.php
@@ -29,7 +29,6 @@ require_once __DIR__ . '/Benchmarker.php';
* @ingroup Benchmark
*/
class BenchmarkHooks extends Benchmarker {
-
public function __construct() {
parent::__construct();
$this->mDescription = 'Benchmark MediaWiki Hooks.';
@@ -46,13 +45,13 @@ class BenchmarkHooks extends Benchmarker {
$time = $this->benchHooks();
$this->output( 'Loaded (one) hook: ' . $time . "\n" );
- for( $i = 0; $i < 9; $i++ ) {
+ for ( $i = 0; $i < 9; $i++ ) {
$wgHooks['Test'][] = array( $this, 'test' );
}
$time = $this->benchHooks();
$this->output( 'Loaded (ten) hook: ' . $time . "\n" );
- for( $i = 0; $i < 90; $i++ ) {
+ for ( $i = 0; $i < 90; $i++ ) {
$wgHooks['Test'][] = array( $this, 'test' );
}
$time = $this->benchHooks();
@@ -61,7 +60,7 @@ class BenchmarkHooks extends Benchmarker {
}
/**
- * @param $trials int
+ * @param int $trials
* @return string
*/
private function benchHooks( $trials = 10 ) {
@@ -71,6 +70,7 @@ class BenchmarkHooks extends Benchmarker {
}
$delta = microtime( true ) - $start;
$pertrial = $delta / $trials;
+
return sprintf( "Took %6.3fms",
$pertrial * 1000 );
}
diff --git a/maintenance/benchmarks/benchmarkParse.php b/maintenance/benchmarks/benchmarkParse.php
new file mode 100644
index 00000000..ce38dad6
--- /dev/null
+++ b/maintenance/benchmarks/benchmarkParse.php
@@ -0,0 +1,174 @@
+<?php
+/**
+ * Benchmark script for parse operations
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Tim Starling <tstarling@wikimedia.org>
+ * @ingroup Benchmark
+ */
+
+require __DIR__ . '/../Maintenance.php';
+
+/**
+ * Maintenance script to benchmark how long it takes to parse a given title at an optionally
+ * specified timestamp
+ *
+ * @since 1.23
+ */
+class BenchmarkParse extends Maintenance {
+ /** @var string MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS) */
+ private $templateTimestamp = null;
+
+ /** @var array Cache that maps a Title DB key to revision ID for the requested timestamp */
+ private $idCache = array();
+
+ function __construct() {
+ parent::__construct();
+ $this->addDescription( 'Benchmark parse operation' );
+ $this->addArg( 'title', 'The name of the page to parse' );
+ $this->addOption( 'warmup', 'Repeat the parse operation this number of times to warm the cache',
+ false, true );
+ $this->addOption( 'loops', 'Number of times to repeat parse operation post-warmup',
+ false, true );
+ $this->addOption( 'page-time',
+ 'Use the version of the page which was current at the given time',
+ false, true );
+ $this->addOption( 'tpl-time',
+ 'Use templates which were current at the given time (except that moves and ' .
+ 'deletes are not handled properly)',
+ false, true );
+ }
+
+ function execute() {
+ if ( $this->hasOption( 'tpl-time' ) ) {
+ $this->templateTimestamp = wfTimestamp( TS_MW, strtotime( $this->getOption( 'tpl-time' ) ) );
+ Hooks::register( 'BeforeParserFetchTemplateAndtitle', array( $this, 'onFetchTemplate' ) );
+ }
+
+ $title = Title::newFromText( $this->getArg() );
+ if ( !$title ) {
+ $this->error( "Invalid title" );
+ exit( 1 );
+ }
+
+ if ( $this->hasOption( 'page-time' ) ) {
+ $pageTimestamp = wfTimestamp( TS_MW, strtotime( $this->getOption( 'page-time' ) ) );
+ $id = $this->getRevIdForTime( $title, $pageTimestamp );
+ if ( !$id ) {
+ $this->error( "The page did not exist at that time" );
+ exit( 1 );
+ }
+
+ $revision = Revision::newFromId( $id );
+ } else {
+ $revision = Revision::newFromTitle( $title );
+ }
+
+ if ( !$revision ) {
+ $this->error( "Unable to load revision, incorrect title?" );
+ exit( 1 );
+ }
+
+ $warmup = $this->getOption( 'warmup', 1 );
+ for ( $i = 0; $i < $warmup; $i++ ) {
+ $this->runParser( $revision );
+ }
+
+ $loops = $this->getOption( 'loops', 1 );
+ if ( $loops < 1 ) {
+ $this->error( 'Invalid number of loops specified', true );
+ }
+ $startUsage = getrusage();
+ $startTime = microtime( true );
+ for ( $i = 0; $i < $loops; $i++ ) {
+ $this->runParser( $revision );
+ }
+ $endUsage = getrusage();
+ $endTime = microtime( true );
+
+ printf( "CPU time = %.3f s, wall clock time = %.3f s\n",
+ // CPU time
+ ( $endUsage['ru_utime.tv_sec'] + $endUsage['ru_utime.tv_usec'] * 1e-6
+ - $startUsage['ru_utime.tv_sec'] - $startUsage['ru_utime.tv_usec'] * 1e-6 ) / $loops,
+ // Wall clock time
+ ( $endTime - $startTime ) / $loops
+ );
+ }
+
+ /**
+ * Fetch the ID of the revision of a Title that occurred
+ *
+ * @param Title $title
+ * @param string $timestamp
+ * @return bool|string Revision ID, or false if not found or error
+ */
+ function getRevIdForTime( Title $title, $timestamp ) {
+ $dbr = wfGetDB( DB_SLAVE );
+
+ $id = $dbr->selectField(
+ array( 'revision', 'page' ),
+ 'rev_id',
+ array(
+ 'page_namespace' => $title->getNamespace(),
+ 'page_title' => $title->getDBkey(),
+ 'rev_timestamp <= ' . $dbr->addQuotes( $timestamp )
+ ),
+ __METHOD__,
+ array( 'ORDER BY' => 'rev_timestamp DESC', 'LIMIT' => 1 ),
+ array( 'revision' => array( 'INNER JOIN', 'rev_page=page_id' ) )
+ );
+
+ return $id;
+ }
+
+ /**
+ * Parse the text from a given Revision
+ *
+ * @param Revision $revision
+ */
+ function runParser( Revision $revision ) {
+ $content = $revision->getContent();
+ $content->getParserOutput( $revision->getTitle(), $revision->getId() );
+ }
+
+ /**
+ * Hook into the parser's revision ID fetcher. Make sure that the parser only
+ * uses revisions around the specified timestamp.
+ *
+ * @param Parser $parser
+ * @param Title $title
+ * @param bool &$skip
+ * @param string|bool &$id
+ * @return bool
+ */
+ function onFetchTemplate( Parser $parser, Title $title, &$skip, &$id ) {
+ $pdbk = $title->getPrefixedDBkey();
+ if ( !isset( $this->idCache[$pdbk] ) ) {
+ $proposedId = $this->getRevIdForTime( $title, $this->templateTimestamp );
+ $this->idCache[$pdbk] = $proposedId;
+ }
+ if ( $this->idCache[$pdbk] !== false ) {
+ $id = $this->idCache[$pdbk];
+ }
+
+ return true;
+ }
+}
+
+$maintClass = 'BenchmarkParse';
+require RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/benchmarks/benchmarkPurge.php b/maintenance/benchmarks/benchmarkPurge.php
index fd863d52..42c1eb78 100644
--- a/maintenance/benchmarks/benchmarkPurge.php
+++ b/maintenance/benchmarks/benchmarkPurge.php
@@ -29,7 +29,6 @@ require_once __DIR__ . '/Benchmarker.php';
* @ingroup Benchmark
*/
class BenchmarkPurge extends Benchmarker {
-
public function __construct() {
parent::__construct();
$this->mDescription = "Benchmark the Squid purge functions.";
@@ -57,8 +56,8 @@ class BenchmarkPurge extends Benchmarker {
/**
* 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?
+ * @param array $urls A bunch of URLs to purge
+ * @param int $trials How many times to run the test?
* @return string
*/
private function benchSquid( $urls, $trials = 1 ) {
@@ -69,13 +68,14 @@ class BenchmarkPurge extends Benchmarker {
$delta = microtime( true ) - $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
+ * @param int $length How many urls to add to the array
* @return array
*/
private function randomUrlList( $length ) {
@@ -83,6 +83,7 @@ class BenchmarkPurge extends Benchmarker {
for ( $i = 0; $i < $length; $i++ ) {
$list[] = $this->randomUrl();
}
+
return $list;
}
@@ -93,6 +94,7 @@ class BenchmarkPurge extends Benchmarker {
*/
private function randomUrl() {
global $wgServer, $wgArticlePath;
+
return $wgServer . str_replace( '$1', $this->randomTitle(), $wgArticlePath );
}
@@ -107,6 +109,7 @@ class BenchmarkPurge extends Benchmarker {
for ( $i = 0; $i < $length; $i++ ) {
$str .= chr( mt_rand( ord( 'a' ), ord( 'z' ) ) );
}
+
return ucfirst( $str );
}
}
diff --git a/maintenance/cdb.php b/maintenance/cdb.php
index d42f9f7a..86c686b4 100644
--- a/maintenance/cdb.php
+++ b/maintenance/cdb.php
@@ -52,7 +52,7 @@ do {
$bad = false;
$showhelp = false;
$quit = false;
- static $fileHandle;
+ static $fileHandle = false;
$line = Maintenance::readconsole();
if ( $line === false ) {
@@ -75,7 +75,11 @@ do {
}
$file = $args[0];
print "Loading cdb file $file...";
- $fileHandle = CdbReader::open( $file );
+ try {
+ $fileHandle = CdbReader::open( $file );
+ } catch ( CdbException $e ) {
+ }
+
if ( !$fileHandle ) {
print "not a cdb file or unable to read it\n";
} else {
@@ -91,7 +95,12 @@ do {
print "Need to specify a key, Luke\n";
break;
}
- $res = $fileHandle->get( $args[0] );
+ try {
+ $res = $fileHandle->get( $args[0] );
+ } catch ( CdbException $e ) {
+ print "Unable to read key from file\n";
+ break;
+ }
if ( $res === false ) {
print "No such key/value pair\n";
} elseif ( is_string( $res ) ) {
diff --git a/maintenance/checkBadRedirects.php b/maintenance/checkBadRedirects.php
index a96e9b80..fec92910 100644
--- a/maintenance/checkBadRedirects.php
+++ b/maintenance/checkBadRedirects.php
@@ -44,7 +44,7 @@ class CheckBadRedirects extends Maintenance {
$count = $result->numRows();
$this->output( "Found $count redirects.\n" .
- "Checking for bad redirects:\n\n" );
+ "Checking for bad redirects:\n\n" );
foreach ( $result as $row ) {
$title = Title::makeTitle( $row->page_namespace, $row->page_title );
diff --git a/maintenance/checkImages.php b/maintenance/checkImages.php
index e6aea537..3921c079 100644
--- a/maintenance/checkImages.php
+++ b/maintenance/checkImages.php
@@ -73,13 +73,13 @@ class CheckImages extends Maintenance {
}
if ( $stat['size'] != $row->img_size ) {
- $this->output( "{$row->img_name}: size mismatch DB={$row->img_size}, actual={$stat['size']}\n" );
+ $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" );
diff --git a/maintenance/checkLess.php b/maintenance/checkLess.php
index d02d8a7b..b97e1b0b 100644
--- a/maintenance/checkLess.php
+++ b/maintenance/checkLess.php
@@ -22,49 +22,33 @@
*/
require_once __DIR__ . '/Maintenance.php';
+require_once 'PHPUnit/Autoload.php';
/**
* @ingroup Maintenance
*/
class CheckLess extends Maintenance {
+
public function __construct() {
parent::__construct();
- $this->mDescription = 'Checks LESS files for errors';
+ $this->mDescription =
+ 'Checks LESS files for errors by running the LessTestSuite PHPUnit test suite';
}
public function execute() {
- $result = false;
- $resourceLoader = new ResourceLoader();
- foreach ( $resourceLoader->getModuleNames() as $name ) {
- /** @var ResourceLoaderFileModule $module */
- $module = $resourceLoader->getModule( $name );
- if ( !$module || !$module instanceof ResourceLoaderFileModule ) {
- continue;
- }
+ global $IP;
+
+ // NOTE (phuedx, 2014-03-26) wgAutoloadClasses isn't set up
+ // by either of the dependencies at the top of the file, so
+ // require it here.
+ require_once __DIR__ . '/../tests/TestsAutoLoader.php';
- $hadErrors = false;
- foreach ( $module->getAllStyleFiles() as $file ) {
- if ( $module->getStyleSheetLang( $file ) !== 'less' ) {
- continue;
- }
- try {
- $compiler = ResourceLoader::getLessCompiler();
- $compiler->compileFile( $file );
- } catch ( Exception $e ) {
- if ( !$hadErrors ) {
- $this->error( "Errors checking module $name:\n" );
- $hadErrors = true;
- }
- $this->error( $e->getMessage() . "\n" );
- $result = true;
- }
- }
- }
- if ( !$result ) {
- $this->output( "No errors found\n" );
- } else {
- die( 1 );
- }
+ $textUICommand = new PHPUnit_TextUI_Command();
+ $argv = array(
+ "$IP/tests/phpunit/phpunit.php",
+ "$IP/tests/phpunit/suites/LessTestSuite.php"
+ );
+ $textUICommand->run( $argv );
}
}
diff --git a/maintenance/checkSyntax.php b/maintenance/checkSyntax.php
index dc8626df..d1c2edd0 100644
--- a/maintenance/checkSyntax.php
+++ b/maintenance/checkSyntax.php
@@ -38,10 +38,23 @@ class CheckSyntax extends Maintenance {
parent::__construct();
$this->mDescription = "Check syntax for all PHP files in MediaWiki";
$this->addOption( 'with-extensions', 'Also recurse the extensions folder' );
- $this->addOption( 'path', 'Specific path (file or directory) to check, either with absolute path or relative to the root of this MediaWiki installation',
- false, true );
- $this->addOption( 'list-file', 'Text file containing list of files or directories to check', false, true );
- $this->addOption( 'modified', 'Check only files that were modified (requires Git command-line client)' );
+ $this->addOption(
+ 'path',
+ 'Specific path (file or directory) to check, either with absolute path or '
+ . 'relative to the root of this MediaWiki installation',
+ false,
+ true
+ );
+ $this->addOption(
+ 'list-file',
+ 'Text file containing list of files or directories to check',
+ false,
+ true
+ );
+ $this->addOption(
+ 'modified',
+ 'Check only files that were modified (requires Git command-line client)'
+ );
$this->addOption( 'syntax-only', 'Check for syntax validity only, skip code style warnings' );
}
@@ -53,7 +66,8 @@ class CheckSyntax extends Maintenance {
$this->buildFileList();
// ParseKit is broken on PHP 5.3+, disabled until this is fixed
- $useParseKit = function_exists( 'parsekit_compile_file' ) && version_compare( PHP_VERSION, '5.3', '<' );
+ $useParseKit = function_exists( 'parsekit_compile_file' )
+ && version_compare( PHP_VERSION, '5.3', '<' );
$str = 'Checking syntax (using ' . ( $useParseKit ?
'parsekit' : ' php -l, this can take a long time' ) . ")\n";
@@ -82,7 +96,7 @@ class CheckSyntax extends Maintenance {
$this->mIgnorePaths = array(
// Compat stuff, explodes on PHP 5.3
"includes/NamespaceCompat.php$",
- );
+ );
$this->mNoStyleCheckPaths = array(
// Third-party code we don't care about
@@ -96,13 +110,14 @@ class CheckSyntax extends Maintenance {
"QPoll/Excel/",
"/geshi/",
"/smarty/",
- );
+ );
if ( $this->hasOption( 'path' ) ) {
$path = $this->getOption( 'path' );
if ( !$this->addPath( $path ) ) {
$this->error( "Error: can't find file or directory $path\n", true );
}
+
return; // process only this path
} elseif ( $this->hasOption( 'list-file' ) ) {
$file = $this->getOption( 'list-file' );
@@ -117,6 +132,7 @@ class CheckSyntax extends Maintenance {
$this->addPath( $path );
}
fclose( $f );
+
return;
} elseif ( $this->hasOption( 'modified' ) ) {
$this->output( "Retrieving list from Git... " );
@@ -127,6 +143,7 @@ class CheckSyntax extends Maintenance {
$this->mFiles[] = $file;
}
}
+
return;
}
@@ -153,17 +170,14 @@ class CheckSyntax extends Maintenance {
if ( file_exists( "$IP/LocalSettings.php" ) ) {
$this->mFiles[] = "$IP/LocalSettings.php";
}
- if ( file_exists( "$IP/AdminSettings.php" ) ) {
- $this->mFiles[] = "$IP/AdminSettings.php";
- }
$this->output( 'done.', 'listfiles' );
}
/**
* Returns a list of tracked files in a Git work tree differing from the master branch.
- * @param $path string: Path to the repository
- * @return array: Resulting list of changed files
+ * @param string $path Path to the repository
+ * @return array Resulting list of changed files
*/
private function getGitModifiedFiles( $path ) {
@@ -215,7 +229,7 @@ class CheckSyntax extends Maintenance {
/**
* Returns true if $file is of a type we can check
- * @param $file string
+ * @param string $file
* @return bool
*/
private function isSuitableFile( $file ) {
@@ -230,22 +244,24 @@ class CheckSyntax extends Maintenance {
return false;
}
}
+
return true;
}
/**
* Add given path to file list, searching it in include path if needed
- * @param $path string
+ * @param string $path
* @return bool
*/
private function addPath( $path ) {
global $IP;
+
return $this->addFileOrDir( $path ) || $this->addFileOrDir( "$IP/$path" );
}
/**
* Add given file to file list, or, if it's a directory, add its content
- * @param $path string
+ * @param string $path
* @return bool
*/
private function addFileOrDir( $path ) {
@@ -256,13 +272,14 @@ class CheckSyntax extends Maintenance {
} else {
return false;
}
+
return true;
}
/**
* Add all suitable files in given directory or its subdirectories to the file list
*
- * @param $dir String: directory to process
+ * @param string $dir Directory to process
*/
private function addDirectoryContent( $dir ) {
$iterator = new RecursiveIteratorIterator(
@@ -279,8 +296,8 @@ class CheckSyntax extends Maintenance {
/**
* Check a file for syntax errors using Parsekit. Shamelessly stolen
* from tools/lint.php by TimStarling
- * @param $file String Path to a file to check for syntax errors
- * @return boolean
+ * @param string $file Path to a file to check for syntax errors
+ * @return bool
*/
private function checkFileWithParsekit( $file ) {
static $okErrors = array(
@@ -302,21 +319,24 @@ class CheckSyntax extends Maintenance {
$this->mFailures[$file] = $errors;
}
}
+
return $ret;
}
/**
* Check a file for syntax errors using php -l
- * @param $file String Path to a file to check for syntax errors
- * @return boolean
+ * @param string $file Path to a file to check for syntax errors
+ * @return bool
*/
private function checkFileWithCli( $file ) {
$res = exec( 'php -l ' . wfEscapeShellArg( $file ) );
if ( strpos( $res, 'No syntax errors detected' ) === false ) {
$this->mFailures[$file] = $res;
$this->output( $res . "\n" );
+
return false;
}
+
return true;
}
@@ -324,8 +344,7 @@ class CheckSyntax extends Maintenance {
* Check a file for non-fatal coding errors, such as byte-order marks in the beginning
* or pointless ?> closing tags at the end.
*
- * @param $file String String Path to a file to check for errors
- * @return boolean
+ * @param string $file String Path to a file to check for errors
*/
private function checkForMistakes( $file ) {
foreach ( $this->mNoStyleCheckPaths as $regex ) {
diff --git a/maintenance/checkUsernames.php b/maintenance/checkUsernames.php
index 6df189fc..777c8334 100644
--- a/maintenance/checkUsernames.php
+++ b/maintenance/checkUsernames.php
@@ -55,7 +55,7 @@ class CheckUsernames extends Maintenance {
);
foreach ( $res as $row ) {
- if ( ! User::isValidUserName( $row->user_name ) ) {
+ if ( !User::isValidUserName( $row->user_name ) ) {
$this->error( sprintf( "%s: %6d: '%s'\n", wfWikiID(), $row->user_id, $row->user_name ) );
wfDebugLog( 'checkUsernames', $row->user_name );
}
diff --git a/maintenance/cleanupAncientTables.php b/maintenance/cleanupAncientTables.php
index 694efaa6..2dbf8bc1 100644
--- a/maintenance/cleanupAncientTables.php
+++ b/maintenance/cleanupAncientTables.php
@@ -40,8 +40,9 @@ class CleanupAncientTables extends Maintenance {
public function execute() {
if ( !$this->hasOption( 'force' ) ) {
$this->error( "This maintenance script will remove old columns and indexes.\n"
- . "It is recommended to backup your database first, and ensure all your data has been migrated to newer tables\n"
- . "If you want to continue, run this script again with the --force \n"
+ . "It is recommended to backup your database first, and ensure all your data has\n"
+ . "been migrated to newer tables. If you want to continue, run this script again\n"
+ . "with --force.\n"
);
}
@@ -82,7 +83,7 @@ class CleanupAncientTables extends Maintenance {
if ( $db->indexExists( 'text', $index, __METHOD__ ) ) {
$this->output( "Dropping index $index from the text table..." );
$db->query( "DROP INDEX " . $db->addIdentifierQuotes( $index )
- . " ON " . $db->tableName( 'text' ) );
+ . " ON " . $db->tableName( 'text' ) );
$this->output( "done.\n" );
}
}
@@ -101,7 +102,7 @@ class CleanupAncientTables extends Maintenance {
if ( $db->fieldExists( 'text', $field, __METHOD__ ) ) {
$this->output( "Dropping the $field field from the text table..." );
$db->query( "ALTER TABLE " . $db->tableName( 'text' )
- . " DROP COLUMN " . $db->addIdentifierQuotes( $field ) );
+ . " DROP COLUMN " . $db->addIdentifierQuotes( $field ) );
$this->output( "done.\n" );
}
}
diff --git a/maintenance/cleanupCaps.php b/maintenance/cleanupCaps.php
index 1a47ac4e..9e88c135 100644
--- a/maintenance/cleanupCaps.php
+++ b/maintenance/cleanupCaps.php
@@ -7,7 +7,7 @@
* --dry-run don't actually try moving them
*
* Copyright © 2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -71,6 +71,7 @@ class CapsCleanup extends TableCleanup {
$lower = $wgContLang->lcfirst( $row->page_title );
if ( $upper == $lower ) {
$this->output( "\"$display\" already lowercase.\n" );
+
return $this->progress( 0 );
}
@@ -78,6 +79,7 @@ class CapsCleanup extends TableCleanup {
$targetDisplay = $target->getPrefixedText();
if ( $target->exists() ) {
$this->output( "\"$display\" skipped; \"$targetDisplay\" already exists\n" );
+
return $this->progress( 0 );
}
@@ -98,6 +100,7 @@ class CapsCleanup extends TableCleanup {
}
}
}
+
return $this->progress( 0 );
}
}
diff --git a/maintenance/cleanupImages.php b/maintenance/cleanupImages.php
index 0e0b6194..915a2c08 100644
--- a/maintenance/cleanupImages.php
+++ b/maintenance/cleanupImages.php
@@ -7,7 +7,7 @@
* --fix Actually clean up titles; otherwise just checks for them
*
* Copyright © 2005-2006 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -56,6 +56,7 @@ class ImageCleanup extends TableCleanup {
if ( $source == '' ) {
// Ye olde empty rows. Just kill them.
$this->killRow( $source );
+
return $this->progress( 1 );
}
@@ -82,6 +83,7 @@ class ImageCleanup extends TableCleanup {
return $this->progress( 0 );
}
$this->pokeFile( $source, $safe );
+
return $this->progress( 1 );
}
@@ -89,6 +91,7 @@ class ImageCleanup extends TableCleanup {
$munged = $title->getDBkey();
$this->output( "page $source ($munged) doesn't match self.\n" );
$this->pokeFile( $source, $munged );
+
return $this->progress( 1 );
}
@@ -96,7 +99,7 @@ class ImageCleanup extends TableCleanup {
}
/**
- * @param $name string
+ * @param string $name
*/
private function killRow( $name ) {
if ( $this->dryrun ) {
@@ -114,6 +117,7 @@ class ImageCleanup extends TableCleanup {
if ( !isset( $this->repo ) ) {
$this->repo = RepoGroup::singleton()->getLocalRepo();
}
+
return $this->repo->getRootDirectory() . '/' . $this->repo->getHashPath( $name ) . $name;
}
@@ -122,7 +126,12 @@ class ImageCleanup extends TableCleanup {
}
private function pageExists( $name, $db ) {
- return $db->selectField( 'page', '1', array( 'page_namespace' => NS_FILE, 'page_title' => $name ), __METHOD__ );
+ return $db->selectField(
+ 'page',
+ '1',
+ array( 'page_namespace' => NS_FILE, 'page_title' => $name ),
+ __METHOD__
+ );
}
private function pokeFile( $orig, $new ) {
@@ -130,6 +139,7 @@ class ImageCleanup extends TableCleanup {
if ( !file_exists( $path ) ) {
$this->output( "missing file: $path\n" );
$this->killRow( $orig );
+
return;
}
@@ -145,7 +155,7 @@ class ImageCleanup extends TableCleanup {
$version = 0;
$final = $new;
$conflict = ( $this->imageExists( $final, $db ) ||
- ( $this->pageExists( $orig, $db ) && $this->pageExists( $final, $db ) ) );
+ ( $this->pageExists( $orig, $db ) && $this->pageExists( $final, $db ) ) );
while ( $conflict ) {
$this->output( "Rename conflicts with '$final'...\n" );
@@ -179,6 +189,7 @@ class ImageCleanup extends TableCleanup {
if ( !wfMkdirParents( $dir, null, __METHOD__ ) ) {
$this->output( "RENAME FAILED, COULD NOT CREATE $dir" );
$db->rollback( __METHOD__ );
+
return;
}
}
@@ -205,6 +216,7 @@ class ImageCleanup extends TableCleanup {
$test = Title::makeTitleSafe( NS_FILE, $x );
if ( is_null( $test ) || $test->getDBkey() !== $x ) {
$this->error( "Unable to generate safe title from '$name', got '$x'" );
+
return false;
}
diff --git a/maintenance/cleanupRemovedModules.php b/maintenance/cleanupRemovedModules.php
index 84eec289..e1d0ed6e 100644
--- a/maintenance/cleanupRemovedModules.php
+++ b/maintenance/cleanupRemovedModules.php
@@ -36,12 +36,18 @@ class CleanupRemovedModules extends Maintenance {
parent::__construct();
$this->mDescription = 'Remove cache entries for removed ResourceLoader modules from the database';
$this->addOption( 'batchsize', 'Delete rows in batches of this size. Default: 500', false, true );
- $this->addOption( 'max-slave-lag', 'If the slave lag exceeds this many seconds, wait until it drops below this value. Default: 5', false, true );
+ $this->addOption(
+ 'max-slave-lag',
+ 'If the slave lag exceeds this many seconds, wait until it drops below this value. '
+ . 'Default: 5',
+ false,
+ true
+ );
}
public function execute() {
$dbw = wfGetDB( DB_MASTER );
- $rl = new ResourceLoader();
+ $rl = new ResourceLoader( ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
$moduleNames = $rl->getModuleNames();
$moduleList = implode( ', ', array_map( array( $dbw, 'addQuotes' ), $moduleNames ) );
$limit = max( 1, intval( $this->getOption( 'batchsize', 500 ) ) );
diff --git a/maintenance/cleanupSpam.php b/maintenance/cleanupSpam.php
index 4b8c9feb..f4a5147a 100644
--- a/maintenance/cleanupSpam.php
+++ b/maintenance/cleanupSpam.php
@@ -35,11 +35,14 @@ class CleanupSpam extends Maintenance {
$this->mDescription = "Cleanup all spam from a given hostname";
$this->addOption( 'all', 'Check all wikis in $wgLocalDatabases' );
$this->addOption( 'delete', 'Delete pages containing only spam instead of blanking them' );
- $this->addArg( 'hostname', 'Hostname that was spamming, single * wildcard in the beginning allowed' );
+ $this->addArg(
+ 'hostname',
+ 'Hostname that was spamming, single * wildcard in the beginning allowed'
+ );
}
public function execute() {
- global $wgLocalDatabases, $wgUser;
+ global $IP, $wgLocalDatabases, $wgUser;
$username = wfMessage( 'spambot_username' )->text();
$wgUser = User::newFromName( $username );
@@ -67,7 +70,9 @@ class CleanupSpam extends Maintenance {
array( 'el_index' . $dbr->buildLike( $like ) ), __METHOD__ );
if ( $count ) {
$found = true;
- passthru( "php cleanupSpam.php --wiki='$wikiID' $spec | sed 's/^/$wikiID: /'" );
+ $cmd = wfShellWikiCmd( "$IP/maintenance/cleanupSpam.php",
+ array( '--wiki', $wikiID, $spec ) );
+ passthru( "$cmd | sed 's/^/$wikiID: /'" );
}
}
if ( $found ) {
@@ -96,6 +101,7 @@ class CleanupSpam extends Maintenance {
$title = Title::newFromID( $id );
if ( !$title ) {
$this->error( "Internal error: no page for ID $id" );
+
return;
}
@@ -104,7 +110,8 @@ class CleanupSpam extends Maintenance {
$currentRevId = $rev->getId();
while ( $rev && ( $rev->isDeleted( Revision::DELETED_TEXT )
- || LinkFilter::matchEntry( $rev->getContent( Revision::RAW ), $domain ) ) ) {
+ || LinkFilter::matchEntry( $rev->getContent( Revision::RAW ), $domain ) )
+ ) {
$rev = $rev->getPrevious();
}
@@ -121,19 +128,28 @@ class CleanupSpam extends Maintenance {
$content = $rev->getContent( Revision::RAW );
$this->output( "reverting\n" );
- $page->doEditContent( $content, wfMessage( 'spam_reverting', $domain )->inContentLanguage()->text(),
- EDIT_UPDATE, $rev->getId() );
+ $page->doEditContent(
+ $content,
+ wfMessage( 'spam_reverting', $domain )->inContentLanguage()->text(),
+ EDIT_UPDATE,
+ $rev->getId()
+ );
} elseif ( $this->hasOption( 'delete' ) ) {
// Didn't find a non-spammy revision, blank the page
$this->output( "deleting\n" );
- $page->doDeleteArticle( wfMessage( 'spam_deleting', $domain )->inContentLanguage()->text() );
+ $page->doDeleteArticle(
+ wfMessage( 'spam_deleting', $domain )->inContentLanguage()->text()
+ );
} else {
// Didn't find a non-spammy revision, blank the page
$handler = ContentHandler::getForTitle( $title );
$content = $handler->makeEmptyContent();
$this->output( "blanking\n" );
- $page->doEditContent( $content, wfMessage( 'spam_blanking', $domain )->inContentLanguage()->text() );
+ $page->doEditContent(
+ $content,
+ wfMessage( 'spam_blanking', $domain )->inContentLanguage()->text()
+ );
}
$dbw->commit( __METHOD__ );
}
diff --git a/maintenance/cleanupTitles.php b/maintenance/cleanupTitles.php
index 5b5ef184..0df9e7fe 100644
--- a/maintenance/cleanupTitles.php
+++ b/maintenance/cleanupTitles.php
@@ -7,7 +7,7 @@
* --fix Actually clean up titles; otherwise just checks for them
*
* Copyright © 2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -148,9 +148,15 @@ class TitleCleanup extends TableCleanup {
$ns = 0;
}
+ # Namespace which no longer exists. Put the page in the main namespace
+ # since we don't have any idea of the old namespace name. See bug 68501.
+ if ( !MWNamespace::exists( $ns ) ) {
+ $ns = 0;
+ }
+
$clean = 'Broken/' . $prior;
$verified = Title::makeTitleSafe( $ns, $clean );
- if ( $verified->exists() ) {
+ if ( !$verified || $verified->exists() ) {
$blah = "Broken/id:" . $row->page_id;
$this->output( "Couldn't legalize; form '$clean' exists; using '$blah'\n" );
$verified = Title::makeTitleSafe( $ns, $blah );
diff --git a/maintenance/cleanupUploadStash.php b/maintenance/cleanupUploadStash.php
index c2ba5558..24b63a8b 100644
--- a/maintenance/cleanupUploadStash.php
+++ b/maintenance/cleanupUploadStash.php
@@ -38,6 +38,7 @@ class UploadStashCleanup extends Maintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Clean up abandoned files in temporary uploaded file stash";
+ $this->setBatchSize( 50 );
}
public function execute() {
@@ -81,10 +82,9 @@ class UploadStashCleanup extends Maintenance {
try {
$stash->getFile( $key, true );
$stash->removeFileNoAuth( $key );
- } catch ( UploadStashBadPathException $ex ) {
- $this->output( "Failed removing stashed upload with key: $key\n" );
- } catch ( UploadStashZeroLengthFileException $ex ) {
- $this->output( "Failed removing stashed upload with key: $key\n" );
+ } catch ( UploadStashException $ex ) {
+ $type = get_class( $ex );
+ $this->output( "Failed removing stashed upload with key: $key ($type)\n" );
}
if ( $i % 100 == 0 ) {
$this->output( "$i\n" );
@@ -95,20 +95,25 @@ class UploadStashCleanup extends Maintenance {
// Delete all the corresponding thumbnails...
$dir = $tempRepo->getZonePath( 'thumb' );
- $iterator = $tempRepo->getBackend()->getFileList( array( 'dir' => $dir ) );
+ $iterator = $tempRepo->getBackend()->getFileList( array( 'dir' => $dir, 'adviseStat' => 1 ) );
$this->output( "Deleting old thumbnails...\n" );
$i = 0;
+ $batch = array(); // operation batch
foreach ( $iterator as $file ) {
if ( wfTimestamp( TS_UNIX, $tempRepo->getFileTimestamp( "$dir/$file" ) ) < $cutoff ) {
- $status = $tempRepo->quickPurge( "$dir/$file" );
- if ( !$status->isOK() ) {
- $this->error( print_r( $status->getErrorsArray(), true ) );
- }
- if ( ( ++$i % 100 ) == 0 ) {
+ $batch[] = array( 'op' => 'delete', 'src' => "$dir/$file" );
+ if ( count( $batch ) >= $this->mBatchSize ) {
+ $this->doOperations( $tempRepo, $batch );
+ $i += count( $batch );
+ $batch = array();
$this->output( "$i\n" );
}
}
}
+ if ( count( $batch ) ) {
+ $this->doOperations( $tempRepo, $batch );
+ $i += count( $batch );
+ }
$this->output( "$i done\n" );
// Apparently lots of stash files are not registered in the DB...
@@ -119,24 +124,31 @@ class UploadStashCleanup extends Maintenance {
$this->error( "Temp repo is not using the temp container.", 1 ); // die
}
$i = 0;
+ $batch = array(); // operation batch
foreach ( $iterator as $file ) {
- // Absolute sanity check for stashed files and file segments
- if ( !preg_match( '#(^\d{14}!|\.\d+\.\w+\.\d+$)#', basename( $file ) ) ) {
- $this->output( "Skipped non-stash $file\n" );
- continue;
- }
if ( wfTimestamp( TS_UNIX, $tempRepo->getFileTimestamp( "$dir/$file" ) ) < $cutoff ) {
- $status = $tempRepo->quickPurge( "$dir/$file" );
- if ( !$status->isOK() ) {
- $this->error( print_r( $status->getErrorsArray(), true ) );
- }
- if ( ( ++$i % 100 ) == 0 ) {
+ $batch[] = array( 'op' => 'delete', 'src' => "$dir/$file" );
+ if ( count( $batch ) >= $this->mBatchSize ) {
+ $this->doOperations( $tempRepo, $batch );
+ $i += count( $batch );
+ $batch = array();
$this->output( "$i\n" );
}
}
}
+ if ( count( $batch ) ) {
+ $this->doOperations( $tempRepo, $batch );
+ $i += count( $batch );
+ }
$this->output( "$i done\n" );
}
+
+ protected function doOperations( FileRepo $tempRepo, array $ops ) {
+ $status = $tempRepo->getBackend()->doQuickOperations( $ops );
+ if ( !$status->isOK() ) {
+ $this->error( print_r( $status->getErrorsArray(), true ) );
+ }
+ }
}
$maintClass = "UploadStashCleanup";
diff --git a/maintenance/cleanupWatchlist.php b/maintenance/cleanupWatchlist.php
index f1a7b481..eb7d7b18 100644
--- a/maintenance/cleanupWatchlist.php
+++ b/maintenance/cleanupWatchlist.php
@@ -7,7 +7,7 @@
* --fix Actually remove entries; without will only report.
*
* Copyright © 2005,2006 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -65,9 +65,11 @@ class WatchlistCleanup extends TableCleanup {
$title = Title::newFromText( $verified );
if ( $row->wl_user == 0 || is_null( $title ) || !$title->equals( $current ) ) {
- $this->output( "invalid watch by {$row->wl_user} for ({$row->wl_namespace}, \"{$row->wl_title}\")\n" );
+ $this->output( "invalid watch by {$row->wl_user} for "
+ . "({$row->wl_namespace}, \"{$row->wl_title}\")\n" );
$updated = $this->removeWatch( $row );
$this->progress( $updated );
+
return;
}
$this->progress( 0 );
@@ -76,12 +78,16 @@ class WatchlistCleanup extends TableCleanup {
private function removeWatch( $row ) {
if ( !$this->dryrun && $this->hasOption( 'fix' ) ) {
$dbw = wfGetDB( DB_MASTER );
- $dbw->delete( 'watchlist', array(
+ $dbw->delete(
+ 'watchlist', array(
'wl_user' => $row->wl_user,
'wl_namespace' => $row->wl_namespace,
'wl_title' => $row->wl_title ),
- __METHOD__ );
+ __METHOD__
+ );
+
$this->output( "- removed\n" );
+
return 1;
} else {
return 0;
diff --git a/maintenance/commandLine.inc b/maintenance/commandLine.inc
index be071422..88776f4f 100644
--- a/maintenance/commandLine.inc
+++ b/maintenance/commandLine.inc
@@ -23,14 +23,18 @@
require_once __DIR__ . '/Maintenance.php';
+// @codingStandardsIgnoreStart MediaWiki.NamingConventions.ValidGlobalName.wgPrefix
global $optionsWithArgs;
+// @codingStandardsIgnoreEnd
if ( !isset( $optionsWithArgs ) ) {
$optionsWithArgs = array();
}
class CommandLineInc extends Maintenance {
public function __construct() {
+ // @codingStandardsIgnoreStart MediaWiki.NamingConventions.ValidGlobalName.wgPrefix
global $optionsWithArgs;
+ // @codingStandardsIgnoreEnd
parent::__construct();
foreach ( $optionsWithArgs as $name ) {
$this->addOption( $name, '', false, true );
@@ -39,6 +43,7 @@ class CommandLineInc extends Maintenance {
/**
* No help, it would just be misleading since it misses custom options
+ * @param bool $force
*/
protected function maybeHelp( $force = false ) {
if ( !$force ) {
@@ -48,7 +53,9 @@ class CommandLineInc extends Maintenance {
}
public function execute() {
+ // @codingStandardsIgnoreStart MediaWiki.NamingConventions.ValidGlobalName.wgPrefix
global $args, $options;
+ // @codingStandardsIgnoreEnd
$args = $this->mArgs;
$options = $this->mOptions;
}
diff --git a/maintenance/compareParserCache.php b/maintenance/compareParserCache.php
new file mode 100644
index 00000000..98441b60
--- /dev/null
+++ b/maintenance/compareParserCache.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+/**
+ * @ingroup Maintenance
+ */
+class CompareParserCache extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Parse random pages and compare output to cache.";
+ $this->addOption( 'namespace', 'Page namespace number', true, true );
+ $this->addOption( 'maxpages', 'Number of pages to try', true, true );
+ }
+
+ public function execute() {
+ $pages = $this->getOption( 'maxpages' );
+
+ $dbr = $this->getDB( DB_SLAVE );
+
+ $totalsec = 0.0;
+ $scanned = 0;
+ $withcache = 0;
+ $withdiff = 0;
+ while ( $pages-- > 0 ) {
+ $row = $dbr->selectRow( 'page', '*',
+ array(
+ 'page_namespace' => $this->getOption( 'namespace' ),
+ 'page_is_redirect' => 0,
+ 'page_random >= ' . wfRandom()
+ ),
+ __METHOD__,
+ array(
+ 'ORDER BY' => 'page_random',
+ )
+ );
+
+ if ( !$row ) {
+ continue;
+ }
+ ++$scanned;
+
+ $title = Title::newFromRow( $row );
+ $page = WikiPage::factory( $title );
+ $revision = $page->getRevision();
+ $content = $revision->getContent( Revision::RAW );
+
+ $parserOptions = $page->makeParserOptions( 'canonical' );
+
+ $parserOutputOld = ParserCache::singleton()->get( $page, $parserOptions );
+
+ if ( $parserOutputOld ) {
+ $t1 = microtime( true );
+ $parserOutputNew = $content->getParserOutput(
+ $title, $revision->getId(), $parserOptions, false );
+ $sec = microtime( true ) - $t1;
+ $totalsec += $sec;
+
+ $this->output( "Parsed '{$title->getPrefixedText()}' in $sec seconds.\n" );
+
+ $this->output( "Found cache entry found for '{$title->getPrefixedText()}'..." );
+ $oldHtml = trim( preg_replace( '#<!-- .+-->#Us', '', $parserOutputOld->getText() ) );
+ $newHtml = trim( preg_replace( '#<!-- .+-->#Us', '', $parserOutputNew->getText() ) );
+ $diff = wfDiff( $oldHtml, $newHtml );
+ if ( strlen( $diff ) ) {
+ $this->output( "differences found:\n\n$diff\n\n" );
+ ++$withdiff;
+ } else {
+ $this->output( "No differences found.\n" );
+ }
+ ++$withcache;
+ } else {
+ $this->output( "No parser cache entry found for '{$title->getPrefixedText()}'.\n" );
+ }
+ }
+
+ $ave = $totalsec ? $totalsec / $scanned : 0;
+ $this->output( "Checked $scanned pages; $withcache had prior cache entries.\n" );
+ $this->output( "Pages with differences found: $withdiff\n" );
+ $this->output( "Average parse time: $ave sec\n" );
+ }
+}
+
+$maintClass = "CompareParserCache";
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/compareParsers.php b/maintenance/compareParsers.php
index fabc2571..e67c439b 100644
--- a/maintenance/compareParsers.php
+++ b/maintenance/compareParsers.php
@@ -7,7 +7,7 @@
* Templates etc are pulled from the local wiki database, not from the dump.
*
* Copyright © 2011 Platonides
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,11 +47,31 @@ class CompareParsers extends DumpIterator {
$this->addOption( 'parser1', 'The first parser to compare.', true, true );
$this->addOption( 'parser2', 'The second parser to compare.', true, true );
$this->addOption( 'tidy', 'Run tidy on the articles.', false, false );
- $this->addOption( 'save-failed', 'Folder in which articles which differ will be stored.', false, true );
+ $this->addOption(
+ 'save-failed',
+ 'Folder in which articles which differ will be stored.',
+ false,
+ true
+ );
$this->addOption( 'show-diff', 'Show a diff of the two renderings.', false, false );
- $this->addOption( 'diff-bin', 'Binary to use for diffing (can also be provided by DIFF env var).', false, false );
- $this->addOption( 'strip-parameters', 'Remove parameters of html tags to increase readability.', false, false );
- $this->addOption( 'show-parsed-output', 'Show the parsed html if both Parsers give the same output.', false, false );
+ $this->addOption(
+ 'diff-bin',
+ 'Binary to use for diffing (can also be provided by DIFF env var).',
+ false,
+ false
+ );
+ $this->addOption(
+ 'strip-parameters',
+ 'Remove parameters of html tags to increase readability.',
+ false,
+ false
+ );
+ $this->addOption(
+ 'show-parsed-output',
+ 'Show the parsed html if both Parsers give the same output.',
+ false,
+ false
+ );
}
public function checkOptions() {
@@ -96,12 +116,13 @@ class CompareParsers extends DumpIterator {
if ( !$this->stripParametersEnabled ) {
return $text;
}
+
return preg_replace( '/(<a) [^>]+>/', '$1>', $text );
}
/**
* Callback function for each revision, parse with both parsers and compare
- * @param $rev Revision
+ * @param Revision $rev
*/
public function processRevision( $rev ) {
$title = $rev->getTitle();
@@ -118,7 +139,9 @@ class CompareParsers extends DumpIterator {
$content = $rev->getContent();
if ( $content->getModel() !== CONTENT_MODEL_WIKITEXT ) {
- $this->error( "Page {$title->getPrefixedText()} does not contain wikitext but {$content->getModel()}\n" );
+ $this->error( "Page {$title->getPrefixedText()} does not contain wikitext "
+ . "but {$content->getModel()}\n" );
+
return;
}
@@ -132,13 +155,21 @@ class CompareParsers extends DumpIterator {
$this->error( "Parsing for {$title->getPrefixedText()} differs\n" );
if ( $this->saveFailed ) {
- file_put_contents( $this->saveFailed . '/' . rawurlencode( $title->getPrefixedText() ) . ".txt", $text );
+ file_put_contents(
+ $this->saveFailed . '/' . rawurlencode( $title->getPrefixedText() ) . ".txt",
+ $text
+ );
}
if ( $this->showDiff ) {
- $this->output( wfDiff( $this->stripParameters( $output1->getText() ), $this->stripParameters( $output2->getText() ), '' ) );
+ $this->output( wfDiff(
+ $this->stripParameters( $output1->getText() ),
+ $this->stripParameters( $output2->getText() ),
+ ''
+ ) );
}
} else {
$this->output( $title->getPrefixedText() . "\tOK\n" );
+
if ( $this->showParsedOutput ) {
$this->output( $this->stripParameters( $output1->getText() ) );
}
@@ -149,10 +180,9 @@ class CompareParsers extends DumpIterator {
/* Look for the parser in a file appropiately named in the current folder */
if ( !class_exists( $parserName ) && file_exists( "$parserName.php" ) ) {
global $wgAutoloadClasses;
- $wgAutoloadClasses[ $parserName ] = realpath( '.' ) . "/$parserName.php";
+ $wgAutoloadClasses[$parserName] = realpath( '.' ) . "/$parserName.php";
}
}
-
}
$maintClass = "CompareParsers";
diff --git a/maintenance/convertLinks.php b/maintenance/convertLinks.php
index 17b91110..221ebe37 100644
--- a/maintenance/convertLinks.php
+++ b/maintenance/convertLinks.php
@@ -36,14 +36,29 @@ class ConvertLinks extends Maintenance {
public function __construct() {
parent::__construct();
- $this->mDescription = "Convert from the old links schema (string->ID) to the new schema (ID->ID).
-The wiki should be put into read-only mode while this script executes";
+ $this->mDescription =
+ "Convert from the old links schema (string->ID) to the new schema (ID->ID)."
+ . "The wiki should be put into read-only mode while this script executes";
$this->addArg( 'logperformance', "Log performance to perfLogFilename.", false );
- $this->addArg( 'perfLogFilename', "Filename where performance is logged if --logperformance was set (defaults to 'convLinksPerf.txt').", false );
- $this->addArg( 'keep-links-table', "Don't overwrite the old links table with the new one, leave the new table at links_temp.", false );
- $this->addArg( 'nokeys', "Don't create keys, and so allow duplicates in the new links table.\n
-This gives a huge speed improvement for very large links tables which are MyISAM." /* (What about InnoDB?) */, false );
+ $this->addArg(
+ 'perfLogFilename',
+ "Filename where performance is logged if --logperformance was set "
+ . "(defaults to 'convLinksPerf.txt').",
+ false
+ );
+ $this->addArg(
+ 'keep-links-table',
+ "Don't overwrite the old links table with the new one, leave the new table at links_temp.",
+ false
+ );
+ $this->addArg(
+ 'nokeys',
+ /* (What about InnoDB?) */
+ "Don't create keys, and so allow duplicates in the new links table.\n"
+ . "This gives a huge speed improvement for very large links tables which are MyISAM.",
+ false
+ );
}
public function getDbType() {
@@ -56,22 +71,34 @@ This gives a huge speed improvement for very large links tables which are MyISAM
$type = $dbw->getType();
if ( $type != 'mysql' ) {
$this->output( "Link table conversion not necessary for $type\n" );
+
return;
}
global $wgContLang;
- $numBadLinks = $curRowsRead = 0; # counters etc
- $totalTuplesInserted = 0; # total tuples INSERTed into links_temp
+ # counters etc
+ $numBadLinks = $curRowsRead = 0;
+
+ # total tuples INSERTed into links_temp
+ $totalTuplesInserted = 0;
+
+ # whether or not to give progress reports while reading IDs from cur table
+ $reportCurReadProgress = true;
- $reportCurReadProgress = true; # whether or not to give progress reports while reading IDs from cur table
- $curReadReportInterval = 1000; # number of rows between progress reports
+ # number of rows between progress reports
+ $curReadReportInterval = 1000;
- $reportLinksConvProgress = true; # whether or not to give progress reports during conversion
- $linksConvInsertInterval = 1000; # number of rows per INSERT
+ # whether or not to give progress reports during conversion
+ $reportLinksConvProgress = true;
+
+ # number of rows per INSERT
+ $linksConvInsertInterval = 1000;
$initialRowOffset = 0;
- # $finalRowOffset = 0; # not used yet; highest row number from links table to process
+
+ # not used yet; highest row number from links table to process
+ # $finalRowOffset = 0;
$overwriteLinksTable = !$this->hasOption( 'keep-links-table' );
$noKeys = $this->hasOption( 'noKeys' );
@@ -80,16 +107,19 @@ This gives a huge speed improvement for very large links tables which are MyISAM
# --------------------------------------------------------------------
- list( $cur, $links, $links_temp, $links_backup ) = $dbw->tableNamesN( 'cur', 'links', 'links_temp', 'links_backup' );
+ list( $cur, $links, $links_temp, $links_backup ) =
+ $dbw->tableNamesN( 'cur', 'links', 'links_temp', 'links_backup' );
if ( $dbw->tableExists( 'pagelinks' ) ) {
$this->output( "...have pagelinks; skipping old links table updates\n" );
+
return;
}
$res = $dbw->query( "SELECT l_from FROM $links LIMIT 1" );
if ( $dbw->fieldType( $res, 0 ) == "int" ) {
$this->output( "Schema already converted\n" );
+
return;
}
@@ -104,17 +134,17 @@ This gives a huge speed improvement for very large links tables which are MyISAM
} else {
$fh = false;
if ( $this->logPerformance ) {
- $fh = fopen ( $perfLogFilename, "w" );
+ $fh = fopen( $perfLogFilename, "w" );
if ( !$fh ) {
$this->error( "Couldn't open $perfLogFilename" );
$this->logPerformance = false;
}
}
- $baseTime = $startTime = $this->getMicroTime();
+ $baseTime = $startTime = microtime( true );
# Create a title -> cur_id map
$this->output( "Loading IDs from $cur table...\n" );
- $this->performanceLog ( $fh, "Reading $numRows rows from cur table...\n" );
- $this->performanceLog ( $fh, "rows read vs seconds elapsed:\n" );
+ $this->performanceLog( $fh, "Reading $numRows rows from cur table...\n" );
+ $this->performanceLog( $fh, "rows read vs seconds elapsed:\n" );
$dbw->bufferResults( false );
$res = $dbw->query( "SELECT cur_namespace,cur_title,cur_id FROM $cur" );
@@ -129,7 +159,10 @@ This gives a huge speed improvement for very large links tables which are MyISAM
$curRowsRead++;
if ( $reportCurReadProgress ) {
if ( ( $curRowsRead % $curReadReportInterval ) == 0 ) {
- $this->performanceLog( $fh, $curRowsRead . " " . ( $this->getMicroTime() - $baseTime ) . "\n" );
+ $this->performanceLog(
+ $fh,
+ $curRowsRead . " " . ( microtime( true ) - $baseTime ) . "\n"
+ );
$this->output( "\t$curRowsRead rows of $cur table read.\n" );
}
}
@@ -137,7 +170,10 @@ This gives a huge speed improvement for very large links tables which are MyISAM
$dbw->freeResult( $res );
$dbw->bufferResults( true );
$this->output( "Finished loading IDs.\n\n" );
- $this->performanceLog( $fh, "Took " . ( $this->getMicroTime() - $baseTime ) . " seconds to load IDs.\n\n" );
+ $this->performanceLog(
+ $fh,
+ "Took " . ( microtime( true ) - $baseTime ) . " seconds to load IDs.\n\n"
+ );
# --------------------------------------------------------------------
@@ -145,12 +181,14 @@ This gives a huge speed improvement for very large links tables which are MyISAM
# convert, and write to the new table.
$this->createTempTable();
$this->performanceLog( $fh, "Resetting timer.\n\n" );
- $baseTime = $this->getMicroTime();
+ $baseTime = microtime( true );
$this->output( "Processing $numRows rows from $links table...\n" );
$this->performanceLog( $fh, "Processing $numRows rows from $links table...\n" );
$this->performanceLog( $fh, "rows inserted vs seconds elapsed:\n" );
- for ( $rowOffset = $initialRowOffset; $rowOffset < $numRows; $rowOffset += $linksConvInsertInterval ) {
+ for ( $rowOffset = $initialRowOffset; $rowOffset < $numRows;
+ $rowOffset += $linksConvInsertInterval
+ ) {
$sqlRead = "SELECT * FROM $links ";
$sqlRead = $dbw->limitResult( $sqlRead, $linksConvInsertInterval, $rowOffset );
$res = $dbw->query( $sqlRead );
@@ -176,7 +214,8 @@ This gives a huge speed improvement for very large links tables which are MyISAM
}
}
$dbw->freeResult( $res );
- # $this->output( "rowOffset: $rowOffset\ttuplesAdded: $tuplesAdded\tnumBadLinks: $numBadLinks\n" );
+ # $this->output( "rowOffset: $rowOffset\ttuplesAdded: "
+ # . "$tuplesAdded\tnumBadLinks: $numBadLinks\n" );
if ( $tuplesAdded != 0 ) {
if ( $reportLinksConvProgress ) {
$this->output( "Inserting $tuplesAdded tuples into $links_temp..." );
@@ -185,15 +224,25 @@ This gives a huge speed improvement for very large links tables which are MyISAM
$totalTuplesInserted += $tuplesAdded;
if ( $reportLinksConvProgress ) {
$this->output( " done. Total $totalTuplesInserted tuples inserted.\n" );
- $this->performanceLog( $fh, $totalTuplesInserted . " " . ( $this->getMicroTime() - $baseTime ) . "\n" );
+ $this->performanceLog(
+ $fh,
+ $totalTuplesInserted . " " . ( microtime( true ) - $baseTime ) . "\n"
+ );
}
}
}
- $this->output( "$totalTuplesInserted valid titles and $numBadLinks invalid titles were processed.\n\n" );
- $this->performanceLog( $fh, "$totalTuplesInserted valid titles and $numBadLinks invalid titles were processed.\n" );
- $this->performanceLog( $fh, "Total execution time: " . ( $this->getMicroTime() - $startTime ) . " seconds.\n" );
+ $this->output( "$totalTuplesInserted valid titles and "
+ . "$numBadLinks invalid titles were processed.\n\n" );
+ $this->performanceLog(
+ $fh,
+ "$totalTuplesInserted valid titles and $numBadLinks invalid titles were processed.\n"
+ );
+ $this->performanceLog(
+ $fh,
+ "Total execution time: " . ( microtime( true ) - $startTime ) . " seconds.\n"
+ );
if ( $this->logPerformance ) {
- fclose ( $fh );
+ fclose( $fh );
}
}
# --------------------------------------------------------------------
@@ -209,7 +258,6 @@ This gives a huge speed improvement for very large links tables which are MyISAM
$dbw->query( "RENAME TABLE links TO $links_backup, $links_temp TO $links", __METHOD__ );
$this->output( " done.\n\n" );
- $dbw->close();
$this->output( "Conversion complete. The old table remains at $links_backup;\n" );
$this->output( "delete at your leisure.\n" );
} else {
@@ -223,6 +271,7 @@ This gives a huge speed improvement for very large links tables which are MyISAM
if ( !( $dbConn->isOpen() ) ) {
$this->output( "Opening connection to database failed.\n" );
+
return;
}
$links_temp = $dbConn->tableName( 'links_temp' );
@@ -234,14 +283,14 @@ This gives a huge speed improvement for very large links tables which are MyISAM
$this->output( "Creating temporary links table..." );
if ( $this->hasOption( 'noKeys' ) ) {
$dbConn->query( "CREATE TABLE $links_temp ( " .
- "l_from int(8) unsigned NOT NULL default '0', " .
- "l_to int(8) unsigned NOT NULL default '0')" );
+ "l_from int(8) unsigned NOT NULL default '0', " .
+ "l_to int(8) unsigned NOT NULL default '0')" );
} else {
$dbConn->query( "CREATE TABLE $links_temp ( " .
- "l_from int(8) unsigned NOT NULL default '0', " .
- "l_to int(8) unsigned NOT NULL default '0', " .
- "UNIQUE KEY l_from(l_from,l_to), " .
- "KEY (l_to))" );
+ "l_from int(8) unsigned NOT NULL default '0', " .
+ "l_to int(8) unsigned NOT NULL default '0', " .
+ "UNIQUE KEY l_from(l_from,l_to), " .
+ "KEY (l_to))" );
}
$this->output( " done.\n\n" );
}
@@ -251,11 +300,6 @@ This gives a huge speed improvement for very large links tables which are MyISAM
fwrite( $fh, $text );
}
}
-
- private function getMicroTime() { # return time in seconds, with microsecond accuracy
- list( $usec, $sec ) = explode( " ", microtime() );
- return ( (float)$usec + (float)$sec );
- }
}
$maintClass = "ConvertLinks";
diff --git a/maintenance/convertUserOptions.php b/maintenance/convertUserOptions.php
index 34c643bb..1542a8c3 100644
--- a/maintenance/convertUserOptions.php
+++ b/maintenance/convertUserOptions.php
@@ -26,8 +26,6 @@ require_once __DIR__ . '/Maintenance.php';
/**
* Maintenance script to convert user options to the new `user_properties` table.
*
- * Do each user sequentially, since accounts can't be deleted
- *
* @ingroup Maintenance
*/
class ConvertUserOptions extends Maintenance {
@@ -37,6 +35,7 @@ class ConvertUserOptions extends Maintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Convert user options from old to new system";
+ $this->setBatchSize( 50 );
}
public function execute() {
@@ -46,17 +45,23 @@ class ConvertUserOptions extends Maintenance {
if ( !$dbw->fieldExists( 'user', 'user_options', __METHOD__ ) ) {
$this->output( "nothing to migrate. " );
+
return;
}
while ( $id !== null ) {
- $idCond = 'user_id > ' . $dbw->addQuotes( $id );
- $optCond = "user_options != " . $dbw->addQuotes( '' ); // For compatibility
- $res = $dbw->select( 'user', '*',
- array( $optCond, $idCond ), __METHOD__,
- array( 'LIMIT' => 50, 'FOR UPDATE' )
+ $res = $dbw->select( 'user',
+ array( 'user_id', 'user_options' ),
+ array(
+ 'user_id > ' . $dbw->addQuotes( $id ),
+ "user_options != " . $dbw->addQuotes( '' ),
+ ),
+ __METHOD__,
+ array(
+ 'ORDER BY' => 'user_id',
+ 'LIMIT' => $this->mBatchSize,
+ )
);
$id = $this->convertOptionBatch( $res, $dbw );
- $dbw->commit( __METHOD__ );
wfWaitForSlaves();
@@ -68,20 +73,37 @@ class ConvertUserOptions extends Maintenance {
}
/**
- * @param $res
- * @param $dbw DatabaseBase
+ * @param ResultWrapper $res
+ * @param DatabaseBase $dbw
* @return null|int
*/
function convertOptionBatch( $res, $dbw ) {
$id = null;
foreach ( $res as $row ) {
$this->mConversionCount++;
+ $insertRows = array();
+ foreach ( explode( "\n", $row->user_options ) as $s ) {
+ $m = array();
+ if ( !preg_match( "/^(.[^=]*)=(.*)$/", $s, $m ) ) {
+ continue;
+ }
- $u = User::newFromRow( $row );
+ // MW < 1.16 would save even default values. Filter them out
+ // here (as in User) to avoid adding many unnecessary rows.
+ $defaultOption = User::getDefaultOption( $m[1] );
+ if ( is_null( $defaultOption ) || $m[2] != $defaultOption ) {
+ $insertRows[] = array(
+ 'up_user' => $row->user_id,
+ 'up_property' => $m[1],
+ 'up_value' => $m[2],
+ );
+ }
+ }
- $u->saveSettings();
+ if ( count( $insertRows ) ) {
+ $dbw->insert( 'user_properties', $insertRows, __METHOD__, array( 'IGNORE' ) );
+ }
- // Do this here as saveSettings() doesn't set user_options to '' anymore!
$dbw->update(
'user',
array( 'user_options' => '' ),
diff --git a/maintenance/copyFileBackend.php b/maintenance/copyFileBackend.php
index 21ef4ffa..9ed63c3c 100644
--- a/maintenance/copyFileBackend.php
+++ b/maintenance/copyFileBackend.php
@@ -35,7 +35,8 @@ require_once __DIR__ . '/Maintenance.php';
* @ingroup Maintenance
*/
class CopyFileBackend extends Maintenance {
- protected $statCache = array();
+ /** @var array|null (path sha1 => stat) Pre-computed dst stat entries from listings */
+ protected $statCache = null;
public function __construct() {
parent::__construct();
@@ -98,7 +99,7 @@ class CopyFileBackend extends Maintenance {
if ( $dstPathsRel === null ) {
$this->error( "Could not list files in $container.", 1 ); // die
}
- $this->statCache = array(); // clear
+ $this->statCache = array();
foreach ( $dstPathsRel as $dstPathRel ) {
$path = $dst->getRootStoragePath() . "/$backendRel/$dstPathRel";
$this->statCache[sha1( $path )] = $dst->getFileStat( array( 'src' => $path ) );
@@ -238,8 +239,8 @@ class CopyFileBackend extends Maintenance {
$this->error( "$wikiId: Detected illegal (non-UTF8) path for $srcPath." );
continue;
} elseif ( !$this->hasOption( 'missingonly' )
- && $this->filesAreSame( $src, $dst, $srcPath, $dstPath ) )
- {
+ && $this->filesAreSame( $src, $dst, $srcPath, $dstPath )
+ ) {
$this->output( "\tAlready have $srcPathRel.\n" );
continue; // assume already copied...
}
@@ -338,18 +339,42 @@ class CopyFileBackend extends Maintenance {
$skipHash = $this->hasOption( 'skiphash' );
$srcStat = $src->getFileStat( array( 'src' => $sPath ) );
$dPathSha1 = sha1( $dPath );
- $dstStat = isset( $this->statCache[$dPathSha1] )
- ? $this->statCache[$dPathSha1]
- : $dst->getFileStat( array( 'src' => $dPath ) );
- return (
+ if ( $this->statCache !== null ) {
+ // All dst files are already in stat cache
+ $dstStat = isset( $this->statCache[$dPathSha1] )
+ ? $this->statCache[$dPathSha1]
+ : false;
+ } else {
+ $dstStat = $dst->getFileStat( array( 'src' => $dPath ) );
+ }
+ // Initial fast checks to see if files are obviously different
+ $sameFast = (
is_array( $srcStat ) // sanity check that source exists
&& is_array( $dstStat ) // dest exists
&& $srcStat['size'] === $dstStat['size']
- && ( !$skipHash || $srcStat['mtime'] <= $dstStat['mtime'] )
- && ( $skipHash || $src->getFileSha1Base36( array( 'src' => $sPath, 'latest' => 1 ) )
- === $dst->getFileSha1Base36( array( 'src' => $dPath, 'latest' => 1 ) )
- )
);
+ // More thorough checks against files
+ if ( !$sameFast ) {
+ $same = false; // no need to look farther
+ } elseif ( isset( $srcStat['md5'] ) && isset( $dstStat['md5'] ) ) {
+ // If MD5 was already in the stat info, just use it.
+ // This is useful as many objects stores can return this in object listing,
+ // so we can use it to avoid slow per-file HEADs.
+ $same = ( $srcStat['md5'] === $dstStat['md5'] );
+ } elseif ( $skipHash ) {
+ // This mode is good for copying to a backup location or resyncing clone
+ // backends in FileBackendMultiWrite (since they get writes second, they have
+ // higher timestamps). However, when copying the other way, this hits loads of
+ // false positives (possibly 100%) and wastes a bunch of time on GETs/PUTs.
+ $same = ( $srcStat['mtime'] <= $dstStat['mtime'] );
+ } else {
+ // This is the slowest method which does many per-file HEADs (unless an object
+ // store tracks SHA-1 in listings).
+ $same = ( $src->getFileSha1Base36( array( 'src' => $sPath, 'latest' => 1 ) )
+ === $dst->getFileSha1Base36( array( 'src' => $dPath, 'latest' => 1 ) ) );
+ }
+
+ return $same;
}
}
diff --git a/maintenance/copyJobQueue.php b/maintenance/copyJobQueue.php
index e833115b..a9c9547e 100644
--- a/maintenance/copyJobQueue.php
+++ b/maintenance/copyJobQueue.php
@@ -78,19 +78,18 @@ class CopyJobQueue extends Maintenance {
++$total;
$batch[] = $job;
if ( count( $batch ) >= $this->mBatchSize ) {
- if ( $dst->push( $batch ) ) {
- $totalOK += count( $batch );
- }
+ $dst->push( $batch );
+ $totalOK += count( $batch );
$batch = array();
$dst->waitForBackups();
}
}
if ( count( $batch ) ) {
- if ( $dst->push( $batch ) ) {
- $totalOK += count( $batch );
- }
+ $dst->push( $batch );
+ $totalOK += count( $batch );
$dst->waitForBackups();
}
+
return array( $total, $totalOK );
}
}
diff --git a/maintenance/createAndPromote.php b/maintenance/createAndPromote.php
index aa25ee60..79f72542 100644
--- a/maintenance/createAndPromote.php
+++ b/maintenance/createAndPromote.php
@@ -31,13 +31,15 @@ require_once __DIR__ . '/Maintenance.php';
* @ingroup Maintenance
*/
class CreateAndPromote extends Maintenance {
-
- static $permitRoles = array( 'sysop', 'bureaucrat', 'bot' );
+ private static $permitRoles = array( 'sysop', 'bureaucrat', 'bot' );
public function __construct() {
parent::__construct();
$this->mDescription = "Create a new user account and/or grant it additional rights";
- $this->addOption( "force", "If acccount exists already, just grant it rights or change password." );
+ $this->addOption(
+ 'force',
+ 'If acccount exists already, just grant it rights or change password.'
+ );
foreach ( self::$permitRoles as $role ) {
$this->addOption( $role, "Add the account to the {$role} group" );
}
@@ -67,10 +69,14 @@ class CreateAndPromote extends Maintenance {
$inGroups = $user->getGroups();
}
- $promotions = array_diff( array_filter( self::$permitRoles, array( $this, 'hasOption' ) ), $inGroups );
+ $promotions = array_diff(
+ array_filter( self::$permitRoles, array( $this, 'hasOption' ) ),
+ $inGroups
+ );
if ( $exists && !$password && count( $promotions ) === 0 ) {
$this->output( "Account exists and nothing to do.\n" );
+
return;
} elseif ( count( $promotions ) !== 0 ) {
$promoText = "User:{$username} into " . implode( ', ', $promotions ) . "...\n";
diff --git a/maintenance/cssjanus/COPYING b/maintenance/cssjanus/COPYING
deleted file mode 100644
index 3f2c8953..00000000
--- a/maintenance/cssjanus/COPYING
+++ /dev/null
@@ -1,13 +0,0 @@
- Copyright 2008 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/maintenance/cssjanus/LICENSE b/maintenance/cssjanus/LICENSE
deleted file mode 100644
index d6456956..00000000
--- a/maintenance/cssjanus/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/maintenance/cssjanus/README b/maintenance/cssjanus/README
deleted file mode 100644
index 1b96d1a2..00000000
--- a/maintenance/cssjanus/README
+++ /dev/null
@@ -1,91 +0,0 @@
-=CSSJanus=
-
-_Flips CSS from LTR to an RTL orienation and vice-versa_
-
-Author: `Lindsey Simon <elsigh@google.com>`
-
-==Introduction==
-
-CSSJanus is CSS parser utility designed to aid the conversion of a website's
-layout from left-to-right(LTR) to right-to-left(RTL). The script was born out of
-a need to convert CSS for RTL languages when tables are not being used for layout (since tables will automatically reorder TD's in RTL).
-CSSJanus will change most of the obvious CSS property names and their values as
-well as some not-so-obvious ones (cursor, background-position %, etc...).
-The script is designed to offer flexibility to account for cases when you do
-not want to change certain rules which exist to account for bidirectional text
-display bugs, as well as situations where you may or may not want to flip annotations inside of the background url string.
-Note that you can disable CSSJanus from running on an entire class or any
-rule within a class by prepending a /* @noflip */ comment before the rule(s)
-you want CSSJanus to ignore.
-
-CSSJanus itself is not always enough to make a website that works in a LTR
-language context work in a RTL language all the way, but it is a start.
-
-==Getting the code==
-
-View the trunk at:
-
- http://cssjanus.googlecode.com/svn/trunk/
-
-Check out the latest development version anonymously with:
-
-{{{
- $ svn checkout http://cssjanus.googlecode.com/svn/trunk/ cssjanus
-}}}
-
-==Using==
-
-Usage:
- ./cssjanus.py < file.css > file-rtl.css
-Flags:
- --swap_left_right_in_url: Fixes "left"/"right" string within urls.
- Ex: ./cssjanus.py --swap_left_right_in_url < file.css > file_rtl.css
- --swap_ltr_rtl_in_url: Fixes "ltr"/"rtl" string within urls.
- Ex: ./cssjanus.py --swap_ltr_rtl_in_url < file.css > file_rtl.css
-
-If you'd like to make use of the webapp version of cssjanus, you'll need to
-download the Google App Engine SDK
- http://code.google.com/appengine/downloads.html
-and also drop a "django" directory into this directory, with the latest svn
-from django. You should be good to go with that setup. Please let me know
-otherwise.
-
-==Bugs, Patches==
-
-Patches and bug reports are welcome, just please keep the style
-consistent with the original source. If you find a bug, please include a diff
-of cssjanus_test.py with the bug included as a new unit test which fails. It
-will make understanding and fixing the bug easier.
-
-==Todo==
-
-* Include some helpers for some typical bidi text solutions?
-* Aural CSS (azimuth) swapping?
-
-==Contributors==
-
-Additional thanks to Mike Samuel for his work on csslex.py, Andy Perelson for
-his help coding and reviewing, Stephen Zabel for his help with i18n and my sanity,
-and to Eric Meyer for his thoughtful input.
-Thanks to Junyu Wang for the Chinese translation.
-Thanks to Masashi Kawashima for the Japanese translation.
-Thanks to Taaryk Taar and Tariq Al-Omaireeni for an updated Arabic translation.
-Thanks to Jens Meiert for the German translation.
-
-==License==
-
-{{{
- Copyright 2008 Google Inc. All Rights Reserved.
-
- Licensed under the Apache License, Version 2.0 (the 'License');
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an 'AS IS' BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-}}}
diff --git a/maintenance/cssjanus/cssjanus.py b/maintenance/cssjanus/cssjanus.py
deleted file mode 100644
index dd14bd58..00000000
--- a/maintenance/cssjanus/cssjanus.py
+++ /dev/null
@@ -1,574 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2008 Google Inc. All Rights Reserved.
-
-"""Converts a LeftToRight Cascading Style Sheet into a RightToLeft one.
-
- This is a utility script for replacing "left" oriented things in a CSS file
- like float, padding, margin with "right" oriented values.
- It also does the opposite.
- The goal is to be able to conditionally serve one large, cat'd, compiled CSS
- file appropriate for LeftToRight oriented languages and RightToLeft ones.
- This utility will hopefully help your structural layout done in CSS in
- terms of its RTL compatibility. It will not help with some of the more
- complicated bidirectional text issues.
-"""
-
-__author__ = 'elsigh@google.com (Lindsey Simon)'
-__version__ = '0.1'
-
-import logging
-import re
-import sys
-import getopt
-import os
-
-import csslex
-
-logging.getLogger().setLevel(logging.INFO)
-
-# Global for the command line flags.
-SWAP_LTR_RTL_IN_URL_DEFAULT = False
-SWAP_LEFT_RIGHT_IN_URL_DEFAULT = False
-FLAGS = {'swap_ltr_rtl_in_url': SWAP_LTR_RTL_IN_URL_DEFAULT,
- 'swap_left_right_in_url': SWAP_LEFT_RIGHT_IN_URL_DEFAULT}
-
-# Generic token delimiter character.
-TOKEN_DELIMITER = '~'
-
-# This is a temporary match token we use when swapping strings.
-TMP_TOKEN = '%sTMP%s' % (TOKEN_DELIMITER, TOKEN_DELIMITER)
-
-# Token to be used for joining lines.
-TOKEN_LINES = '%sJ%s' % (TOKEN_DELIMITER, TOKEN_DELIMITER)
-
-# Global constant text strings for CSS value matches.
-LTR = 'ltr'
-RTL = 'rtl'
-LEFT = 'left'
-RIGHT = 'right'
-
-# This is a lookbehind match to ensure that we don't replace instances
-# of our string token (left, rtl, etc...) if there's a letter in front of it.
-# Specifically, this prevents replacements like 'background: url(bright.png)'.
-LOOKBEHIND_NOT_LETTER = r'(?<![a-zA-Z])'
-
-# This is a lookahead match to make sure we don't replace left and right
-# in actual classnames, so that we don't break the HTML/CSS dependencies.
-# Read literally, it says ignore cases where the word left, for instance, is
-# directly followed by valid classname characters and a curly brace.
-# ex: .column-left {float: left} will become .column-left {float: right}
-LOOKAHEAD_NOT_OPEN_BRACE = (r'(?!(?:%s|%s|%s|#|\:|\.|\,|\+|>)*?{)' %
- (csslex.NMCHAR, TOKEN_LINES, csslex.SPACE))
-
-
-# These two lookaheads are to test whether or not we are within a
-# background: url(HERE) situation.
-# Ref: http://www.w3.org/TR/CSS21/syndata.html#uri
-VALID_AFTER_URI_CHARS = r'[\'\"]?%s' % csslex.WHITESPACE
-LOOKAHEAD_NOT_CLOSING_PAREN = r'(?!%s?%s\))' % (csslex.URL_CHARS,
- VALID_AFTER_URI_CHARS)
-LOOKAHEAD_FOR_CLOSING_PAREN = r'(?=%s?%s\))' % (csslex.URL_CHARS,
- VALID_AFTER_URI_CHARS)
-
-# Compile a regex to swap left and right values in 4 part notations.
-# We need to match negatives and decimal numeric values.
-# ex. 'margin: .25em -2px 3px 0' becomes 'margin: .25em 0 3px -2px'.
-POSSIBLY_NEGATIVE_QUANTITY = r'((?:-?%s)|(?:inherit|auto))' % csslex.QUANTITY
-POSSIBLY_NEGATIVE_QUANTITY_SPACE = r'%s%s%s' % (POSSIBLY_NEGATIVE_QUANTITY,
- csslex.SPACE,
- csslex.WHITESPACE)
-FOUR_NOTATION_QUANTITY_RE = re.compile(r'%s%s%s%s' %
- (POSSIBLY_NEGATIVE_QUANTITY_SPACE,
- POSSIBLY_NEGATIVE_QUANTITY_SPACE,
- POSSIBLY_NEGATIVE_QUANTITY_SPACE,
- POSSIBLY_NEGATIVE_QUANTITY),
- re.I)
-COLOR = r'(%s|%s)' % (csslex.NAME, csslex.HASH)
-COLOR_SPACE = r'%s%s' % (COLOR, csslex.SPACE)
-FOUR_NOTATION_COLOR_RE = re.compile(r'(-color%s:%s)%s%s%s(%s)' %
- (csslex.WHITESPACE,
- csslex.WHITESPACE,
- COLOR_SPACE,
- COLOR_SPACE,
- COLOR_SPACE,
- COLOR),
- re.I)
-
-# Compile the cursor resize regexes
-CURSOR_EAST_RE = re.compile(LOOKBEHIND_NOT_LETTER + '([ns]?)e-resize')
-CURSOR_WEST_RE = re.compile(LOOKBEHIND_NOT_LETTER + '([ns]?)w-resize')
-
-# Matches the condition where we need to replace the horizontal component
-# of a background-position value when expressed in horizontal percentage.
-# Had to make two regexes because in the case of position-x there is only
-# one quantity, and otherwise we don't want to match and change cases with only
-# one quantity.
-BG_HORIZONTAL_PERCENTAGE_RE = re.compile(r'background(-position)?(%s:%s)'
- '([^%%]*?)(%s)%%'
- '(%s(?:%s|%s))' % (csslex.WHITESPACE,
- csslex.WHITESPACE,
- csslex.NUM,
- csslex.WHITESPACE,
- csslex.QUANTITY,
- csslex.IDENT))
-
-BG_HORIZONTAL_PERCENTAGE_X_RE = re.compile(r'background-position-x(%s:%s)'
- '(%s)%%' % (csslex.WHITESPACE,
- csslex.WHITESPACE,
- csslex.NUM))
-
-# Matches the opening of a body selector.
-BODY_SELECTOR = r'body%s{%s' % (csslex.WHITESPACE, csslex.WHITESPACE)
-
-# Matches anything up until the closing of a selector.
-CHARS_WITHIN_SELECTOR = r'[^\}]*?'
-
-# Matches the direction property in a selector.
-DIRECTION_RE = r'direction%s:%s' % (csslex.WHITESPACE, csslex.WHITESPACE)
-
-# These allow us to swap "ltr" with "rtl" and vice versa ONLY within the
-# body selector and on the same line.
-BODY_DIRECTION_LTR_RE = re.compile(r'(%s)(%s)(%s)(ltr)' %
- (BODY_SELECTOR, CHARS_WITHIN_SELECTOR,
- DIRECTION_RE),
- re.I)
-BODY_DIRECTION_RTL_RE = re.compile(r'(%s)(%s)(%s)(rtl)' %
- (BODY_SELECTOR, CHARS_WITHIN_SELECTOR,
- DIRECTION_RE),
- re.I)
-
-
-# Allows us to swap "direction:ltr" with "direction:rtl" and
-# vice versa anywhere in a line.
-DIRECTION_LTR_RE = re.compile(r'%s(ltr)' % DIRECTION_RE)
-DIRECTION_RTL_RE = re.compile(r'%s(rtl)' % DIRECTION_RE)
-
-# We want to be able to switch left with right and vice versa anywhere
-# we encounter left/right strings, EXCEPT inside the background:url(). The next
-# two regexes are for that purpose. We have alternate IN_URL versions of the
-# regexes compiled in case the user passes the flag that they do
-# actually want to have left and right swapped inside of background:urls.
-LEFT_RE = re.compile('%s(%s)%s%s' % (LOOKBEHIND_NOT_LETTER,
- LEFT,
- LOOKAHEAD_NOT_CLOSING_PAREN,
- LOOKAHEAD_NOT_OPEN_BRACE),
- re.I)
-RIGHT_RE = re.compile('%s(%s)%s%s' % (LOOKBEHIND_NOT_LETTER,
- RIGHT,
- LOOKAHEAD_NOT_CLOSING_PAREN,
- LOOKAHEAD_NOT_OPEN_BRACE),
- re.I)
-LEFT_IN_URL_RE = re.compile('%s(%s)%s' % (LOOKBEHIND_NOT_LETTER,
- LEFT,
- LOOKAHEAD_FOR_CLOSING_PAREN),
- re.I)
-RIGHT_IN_URL_RE = re.compile('%s(%s)%s' % (LOOKBEHIND_NOT_LETTER,
- RIGHT,
- LOOKAHEAD_FOR_CLOSING_PAREN),
- re.I)
-LTR_IN_URL_RE = re.compile('%s(%s)%s' % (LOOKBEHIND_NOT_LETTER,
- LTR,
- LOOKAHEAD_FOR_CLOSING_PAREN),
- re.I)
-RTL_IN_URL_RE = re.compile('%s(%s)%s' % (LOOKBEHIND_NOT_LETTER,
- RTL,
- LOOKAHEAD_FOR_CLOSING_PAREN),
- re.I)
-
-COMMENT_RE = re.compile('(%s)' % csslex.COMMENT, re.I)
-
-NOFLIP_TOKEN = r'\@noflip'
-# The NOFLIP_TOKEN inside of a comment. For now, this requires that comments
-# be in the input, which means users of a css compiler would have to run
-# this script first if they want this functionality.
-NOFLIP_ANNOTATION = r'/\*%s%s%s\*/' % (csslex.WHITESPACE,
- NOFLIP_TOKEN,
- csslex. WHITESPACE)
-
-# After a NOFLIP_ANNOTATION, and within a class selector, we want to be able
-# to set aside a single rule not to be flipped. We can do this by matching
-# our NOFLIP annotation and then using a lookahead to make sure there is not
-# an opening brace before the match.
-NOFLIP_SINGLE_RE = re.compile(r'(%s%s[^;}]+;?)' % (NOFLIP_ANNOTATION,
- LOOKAHEAD_NOT_OPEN_BRACE),
- re.I)
-
-# After a NOFLIP_ANNOTATION, we want to grab anything up until the next } which
-# means the entire following class block. This will prevent all of its
-# declarations from being flipped.
-NOFLIP_CLASS_RE = re.compile(r'(%s%s})' % (NOFLIP_ANNOTATION,
- CHARS_WITHIN_SELECTOR),
- re.I)
-
-
-class Tokenizer:
- """Replaces any CSS comments with string tokens and vice versa."""
-
- def __init__(self, token_re, token_string):
- """Constructor for the Tokenizer.
-
- Args:
- token_re: A regex for the string to be replace by a token.
- token_string: The string to put between token delimiters when tokenizing.
- """
- logging.debug('Tokenizer::init token_string=%s' % token_string)
- self.token_re = token_re
- self.token_string = token_string
- self.originals = []
-
- def Tokenize(self, line):
- """Replaces any string matching token_re in line with string tokens.
-
- By passing a function as an argument to the re.sub line below, we bypass
- the usual rule where re.sub will only replace the left-most occurrence of
- a match by calling the passed in function for each occurrence.
-
- Args:
- line: A line to replace token_re matches in.
-
- Returns:
- line: A line with token_re matches tokenized.
- """
- line = self.token_re.sub(self.TokenizeMatches, line)
- logging.debug('Tokenizer::Tokenize returns: %s' % line)
- return line
-
- def DeTokenize(self, line):
- """Replaces tokens with the original string.
-
- Args:
- line: A line with tokens.
-
- Returns:
- line with any tokens replaced by the original string.
- """
-
- # Put all of the comments back in by their comment token.
- for i, original in enumerate(self.originals):
- token = '%s%s_%s%s' % (TOKEN_DELIMITER, self.token_string, i + 1,
- TOKEN_DELIMITER)
- line = line.replace(token, original)
- logging.debug('Tokenizer::DeTokenize i:%s w/%s' % (i, token))
- logging.debug('Tokenizer::DeTokenize returns: %s' % line)
- return line
-
- def TokenizeMatches(self, m):
- """Replaces matches with tokens and stores the originals.
-
- Args:
- m: A match object.
-
- Returns:
- A string token which replaces the CSS comment.
- """
- logging.debug('Tokenizer::TokenizeMatches %s' % m.group(1))
- self.originals.append(m.group(1))
- return '%s%s_%s%s' % (TOKEN_DELIMITER,
- self.token_string,
- len(self.originals),
- TOKEN_DELIMITER)
-
-
-def FixBodyDirectionLtrAndRtl(line):
- """Replaces ltr with rtl and vice versa ONLY in the body direction.
-
- Args:
- line: A string to replace instances of ltr with rtl.
- Returns:
- line with direction: ltr and direction: rtl swapped only in body selector.
- line = FixBodyDirectionLtrAndRtl('body { direction:ltr }')
- line will now be 'body { direction:rtl }'.
- """
-
- line = BODY_DIRECTION_LTR_RE.sub('\\1\\2\\3%s' % TMP_TOKEN, line)
- line = BODY_DIRECTION_RTL_RE.sub('\\1\\2\\3%s' % LTR, line)
- line = line.replace(TMP_TOKEN, RTL)
- logging.debug('FixBodyDirectionLtrAndRtl returns: %s' % line)
- return line
-
-
-def FixLeftAndRight(line):
- """Replaces left with right and vice versa in line.
-
- Args:
- line: A string in which to perform the replacement.
-
- Returns:
- line with left and right swapped. For example:
- line = FixLeftAndRight('padding-left: 2px; margin-right: 1px;')
- line will now be 'padding-right: 2px; margin-left: 1px;'.
- """
-
- line = LEFT_RE.sub(TMP_TOKEN, line)
- line = RIGHT_RE.sub(LEFT, line)
- line = line.replace(TMP_TOKEN, RIGHT)
- logging.debug('FixLeftAndRight returns: %s' % line)
- return line
-
-
-def FixLeftAndRightInUrl(line):
- """Replaces left with right and vice versa ONLY within background urls.
-
- Args:
- line: A string in which to replace left with right and vice versa.
-
- Returns:
- line with left and right swapped in the url string. For example:
- line = FixLeftAndRightInUrl('background:url(right.png)')
- line will now be 'background:url(left.png)'.
- """
-
- line = LEFT_IN_URL_RE.sub(TMP_TOKEN, line)
- line = RIGHT_IN_URL_RE.sub(LEFT, line)
- line = line.replace(TMP_TOKEN, RIGHT)
- logging.debug('FixLeftAndRightInUrl returns: %s' % line)
- return line
-
-
-def FixLtrAndRtlInUrl(line):
- """Replaces ltr with rtl and vice versa ONLY within background urls.
-
- Args:
- line: A string in which to replace ltr with rtl and vice versa.
-
- Returns:
- line with left and right swapped. For example:
- line = FixLtrAndRtlInUrl('background:url(rtl.png)')
- line will now be 'background:url(ltr.png)'.
- """
-
- line = LTR_IN_URL_RE.sub(TMP_TOKEN, line)
- line = RTL_IN_URL_RE.sub(LTR, line)
- line = line.replace(TMP_TOKEN, RTL)
- logging.debug('FixLtrAndRtlInUrl returns: %s' % line)
- return line
-
-
-def FixCursorProperties(line):
- """Fixes directional CSS cursor properties.
-
- Args:
- line: A string to fix CSS cursor properties in.
-
- Returns:
- line reformatted with the cursor properties substituted. For example:
- line = FixCursorProperties('cursor: ne-resize')
- line will now be 'cursor: nw-resize'.
- """
-
- line = CURSOR_EAST_RE.sub('\\1' + TMP_TOKEN, line)
- line = CURSOR_WEST_RE.sub('\\1e-resize', line)
- line = line.replace(TMP_TOKEN, 'w-resize')
- logging.debug('FixCursorProperties returns: %s' % line)
- return line
-
-
-def FixFourPartNotation(line):
- """Fixes the second and fourth positions in 4 part CSS notation.
-
- Args:
- line: A string to fix 4 part CSS notation in.
-
- Returns:
- line reformatted with the 4 part notations swapped. For example:
- line = FixFourPartNotation('padding: 1px 2px 3px 4px')
- line will now be 'padding: 1px 4px 3px 2px'.
- """
- line = FOUR_NOTATION_QUANTITY_RE.sub('\\1 \\4 \\3 \\2', line)
- line = FOUR_NOTATION_COLOR_RE.sub('\\1\\2 \\5 \\4 \\3', line)
- logging.debug('FixFourPartNotation returns: %s' % line)
- return line
-
-
-def FixBackgroundPosition(line):
- """Fixes horizontal background percentage values in line.
-
- Args:
- line: A string to fix horizontal background position values in.
-
- Returns:
- line reformatted with the 4 part notations swapped.
- """
- line = BG_HORIZONTAL_PERCENTAGE_RE.sub(CalculateNewBackgroundPosition, line)
- line = BG_HORIZONTAL_PERCENTAGE_X_RE.sub(CalculateNewBackgroundPositionX,
- line)
- logging.debug('FixBackgroundPosition returns: %s' % line)
- return line
-
-
-def CalculateNewBackgroundPosition(m):
- """Fixes horizontal background-position percentages.
-
- This function should be used as an argument to re.sub since it needs to
- perform replacement specific calculations.
-
- Args:
- m: A match object.
-
- Returns:
- A string with the horizontal background position percentage fixed.
- BG_HORIZONTAL_PERCENTAGE_RE.sub(FixBackgroundPosition,
- 'background-position: 75% 50%')
- will return 'background-position: 25% 50%'.
- """
-
- # The flipped value is the offset from 100%
- new_x = str(100-int(m.group(4)))
-
- # Since m.group(1) may very well be None type and we need a string..
- if m.group(1):
- position_string = m.group(1)
- else:
- position_string = ''
-
- return 'background%s%s%s%s%%%s' % (position_string, m.group(2), m.group(3),
- new_x, m.group(5))
-
-
-def CalculateNewBackgroundPositionX(m):
- """Fixes percent based background-position-x.
-
- This function should be used as an argument to re.sub since it needs to
- perform replacement specific calculations.
-
- Args:
- m: A match object.
-
- Returns:
- A string with the background-position-x percentage fixed.
- BG_HORIZONTAL_PERCENTAGE_X_RE.sub(CalculateNewBackgroundPosition,
- 'background-position-x: 75%')
- will return 'background-position-x: 25%'.
- """
-
- # The flipped value is the offset from 100%
- new_x = str(100-int(m.group(2)))
-
- return 'background-position-x%s%s%%' % (m.group(1), new_x)
-
-
-def ChangeLeftToRightToLeft(lines,
- swap_ltr_rtl_in_url=None,
- swap_left_right_in_url=None):
- """Turns lines into a stream and runs the fixing functions against it.
-
- Args:
- lines: An list of CSS lines.
- swap_ltr_rtl_in_url: Overrides this flag if param is set.
- swap_left_right_in_url: Overrides this flag if param is set.
-
- Returns:
- The same lines, but with left and right fixes.
- """
-
- global FLAGS
-
- # Possibly override flags with params.
- logging.debug('ChangeLeftToRightToLeft swap_ltr_rtl_in_url=%s, '
- 'swap_left_right_in_url=%s' % (swap_ltr_rtl_in_url,
- swap_left_right_in_url))
- if swap_ltr_rtl_in_url is None:
- swap_ltr_rtl_in_url = FLAGS['swap_ltr_rtl_in_url']
- if swap_left_right_in_url is None:
- swap_left_right_in_url = FLAGS['swap_left_right_in_url']
-
- # Turns the array of lines into a single line stream.
- logging.debug('LINES COUNT: %s' % len(lines))
- line = TOKEN_LINES.join(lines)
-
- # Tokenize any single line rules with the /* noflip */ annotation.
- noflip_single_tokenizer = Tokenizer(NOFLIP_SINGLE_RE, 'NOFLIP_SINGLE')
- line = noflip_single_tokenizer.Tokenize(line)
-
- # Tokenize any class rules with the /* noflip */ annotation.
- noflip_class_tokenizer = Tokenizer(NOFLIP_CLASS_RE, 'NOFLIP_CLASS')
- line = noflip_class_tokenizer.Tokenize(line)
-
- # Tokenize the comments so we can preserve them through the changes.
- comment_tokenizer = Tokenizer(COMMENT_RE, 'C')
- line = comment_tokenizer.Tokenize(line)
-
- # Here starteth the various left/right orientation fixes.
- line = FixBodyDirectionLtrAndRtl(line)
-
- if swap_left_right_in_url:
- line = FixLeftAndRightInUrl(line)
-
- if swap_ltr_rtl_in_url:
- line = FixLtrAndRtlInUrl(line)
-
- line = FixLeftAndRight(line)
- line = FixCursorProperties(line)
- line = FixFourPartNotation(line)
- line = FixBackgroundPosition(line)
-
- # DeTokenize the single line noflips.
- line = noflip_single_tokenizer.DeTokenize(line)
-
- # DeTokenize the class-level noflips.
- line = noflip_class_tokenizer.DeTokenize(line)
-
- # DeTokenize the comments.
- line = comment_tokenizer.DeTokenize(line)
-
- # Rejoin the lines back together.
- lines = line.split(TOKEN_LINES)
-
- return lines
-
-def usage():
- """Prints out usage information."""
-
- print 'Usage:'
- print ' ./cssjanus.py < file.css > file-rtl.css'
- print 'Flags:'
- print ' --swap_left_right_in_url: Fixes "left"/"right" string within urls.'
- print ' Ex: ./cssjanus.py --swap_left_right_in_url < file.css > file_rtl.css'
- print ' --swap_ltr_rtl_in_url: Fixes "ltr"/"rtl" string within urls.'
- print ' Ex: ./cssjanus --swap_ltr_rtl_in_url < file.css > file_rtl.css'
-
-def setflags(opts):
- """Parse the passed in command line arguments and set the FLAGS global.
-
- Args:
- opts: getopt iterable intercepted from argv.
- """
-
- global FLAGS
-
- # Parse the arguments.
- for opt, arg in opts:
- logging.debug('opt: %s, arg: %s' % (opt, arg))
- if opt in ("-h", "--help"):
- usage()
- sys.exit()
- elif opt in ("-d", "--debug"):
- logging.getLogger().setLevel(logging.DEBUG)
- elif opt == '--swap_ltr_rtl_in_url':
- FLAGS['swap_ltr_rtl_in_url'] = True
- elif opt == '--swap_left_right_in_url':
- FLAGS['swap_left_right_in_url'] = True
-
-
-def main(argv):
- """Sends stdin lines to ChangeLeftToRightToLeft and writes to stdout."""
-
- # Define the flags.
- try:
- opts, args = getopt.getopt(argv, 'hd', ['help', 'debug',
- 'swap_left_right_in_url',
- 'swap_ltr_rtl_in_url'])
- except getopt.GetoptError:
- usage()
- sys.exit(2)
-
- # Parse and set the flags.
- setflags(opts)
-
- # Call the main routine with all our functionality.
- fixed_lines = ChangeLeftToRightToLeft(sys.stdin.readlines())
- sys.stdout.write(''.join(fixed_lines))
-
-if __name__ == '__main__':
- main(sys.argv[1:])
diff --git a/maintenance/cssjanus/csslex.py b/maintenance/cssjanus/csslex.py
deleted file mode 100644
index 1fc7304e..00000000
--- a/maintenance/cssjanus/csslex.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2007 Google Inc. All Rights Reserved.
-
-"""CSS Lexical Grammar rules.
-
-CSS lexical grammar from http://www.w3.org/TR/CSS21/grammar.html
-"""
-
-__author__ = ['elsigh@google.com (Lindsey Simon)',
- 'msamuel@google.com (Mike Samuel)']
-
-# public symbols
-__all__ = [ "NEWLINE", "HEX", "NON_ASCII", "UNICODE", "ESCAPE", "NMSTART", "NMCHAR", "STRING1", "STRING2", "IDENT", "NAME", "HASH", "NUM", "STRING", "URL", "SPACE", "WHITESPACE", "COMMENT", "QUANTITY", "PUNC" ]
-
-# The comments below are mostly copied verbatim from the grammar.
-
-# "@import" {return IMPORT_SYM;}
-# "@page" {return PAGE_SYM;}
-# "@media" {return MEDIA_SYM;}
-# "@charset" {return CHARSET_SYM;}
-KEYWORD = r'(?:\@(?:import|page|media|charset))'
-
-# nl \n|\r\n|\r|\f ; a newline
-NEWLINE = r'\n|\r\n|\r|\f'
-
-# h [0-9a-f] ; a hexadecimal digit
-HEX = r'[0-9a-f]'
-
-# nonascii [\200-\377]
-NON_ASCII = r'[\200-\377]'
-
-# unicode \\{h}{1,6}(\r\n|[ \t\r\n\f])?
-UNICODE = r'(?:(?:\\' + HEX + r'{1,6})(?:\r\n|[ \t\r\n\f])?)'
-
-# escape {unicode}|\\[^\r\n\f0-9a-f]
-ESCAPE = r'(?:' + UNICODE + r'|\\[^\r\n\f0-9a-f])'
-
-# nmstart [_a-z]|{nonascii}|{escape}
-NMSTART = r'(?:[_a-z]|' + NON_ASCII + r'|' + ESCAPE + r')'
-
-# nmchar [_a-z0-9-]|{nonascii}|{escape}
-NMCHAR = r'(?:[_a-z0-9-]|' + NON_ASCII + r'|' + ESCAPE + r')'
-
-# ident -?{nmstart}{nmchar}*
-IDENT = r'-?' + NMSTART + NMCHAR + '*'
-
-# name {nmchar}+
-NAME = NMCHAR + r'+'
-
-# hash
-HASH = r'#' + NAME
-
-# string1 \"([^\n\r\f\\"]|\\{nl}|{escape})*\" ; "string"
-STRING1 = r'"(?:[^\"\\]|\\.)*"'
-
-# string2 \'([^\n\r\f\\']|\\{nl}|{escape})*\' ; 'string'
-STRING2 = r"'(?:[^\'\\]|\\.)*'"
-
-# string {string1}|{string2}
-STRING = '(?:' + STRING1 + r'|' + STRING2 + ')'
-
-# num [0-9]+|[0-9]*"."[0-9]+
-NUM = r'(?:[0-9]*\.[0-9]+|[0-9]+)'
-
-# s [ \t\r\n\f]
-SPACE = r'[ \t\r\n\f]'
-
-# w {s}*
-WHITESPACE = '(?:' + SPACE + r'*)'
-
-# url special chars
-URL_SPECIAL_CHARS = r'[!#$%&*-~]'
-
-# url chars ({url_special_chars}|{nonascii}|{escape})*
-URL_CHARS = r'(?:%s|%s|%s)*' % (URL_SPECIAL_CHARS, NON_ASCII, ESCAPE)
-
-# url
-URL = r'url\(%s(%s|%s)%s\)' % (WHITESPACE, STRING, URL_CHARS, WHITESPACE)
-
-# comments
-# see http://www.w3.org/TR/CSS21/grammar.html
-COMMENT = r'/\*[^*]*\*+([^/*][^*]*\*+)*/'
-
-# {E}{M} {return EMS;}
-# {E}{X} {return EXS;}
-# {P}{X} {return LENGTH;}
-# {C}{M} {return LENGTH;}
-# {M}{M} {return LENGTH;}
-# {I}{N} {return LENGTH;}
-# {P}{T} {return LENGTH;}
-# {P}{C} {return LENGTH;}
-# {D}{E}{G} {return ANGLE;}
-# {R}{A}{D} {return ANGLE;}
-# {G}{R}{A}{D} {return ANGLE;}
-# {M}{S} {return TIME;}
-# {S} {return TIME;}
-# {H}{Z} {return FREQ;}
-# {K}{H}{Z} {return FREQ;}
-# % {return PERCENTAGE;}
-UNIT = r'(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)'
-
-# {num}{UNIT|IDENT} {return NUMBER;}
-QUANTITY = '%s(?:%s%s|%s)?' % (NUM, WHITESPACE, UNIT, IDENT)
-
-# "<!--" {return CDO;}
-# "-->" {return CDC;}
-# "~=" {return INCLUDES;}
-# "|=" {return DASHMATCH;}
-# {w}"{" {return LBRACE;}
-# {w}"+" {return PLUS;}
-# {w}">" {return GREATER;}
-# {w}"," {return COMMA;}
-PUNC = r'<!--|-->|~=|\|=|[\{\+>,:;]'
diff --git a/maintenance/deleteArchivedFiles.inc b/maintenance/deleteArchivedFiles.inc
index d58e9a40..0c0b34a3 100644
--- a/maintenance/deleteArchivedFiles.inc
+++ b/maintenance/deleteArchivedFiles.inc
@@ -39,6 +39,10 @@ class DeleteArchivedFilesImplementation {
$count = 0;
foreach ( $res as $row ) {
$key = $row->fa_storage_key;
+ if ( !strlen( $key ) ) {
+ $output->handleOutput( "Entry with ID {$row->fa_id} has empty key, skipping\n" );
+ continue;
+ }
$group = $row->fa_storage_group;
$id = $row->fa_id;
$path = $repo->getZonePath( 'deleted' ) . '/' . $repo->getDeletedHashPath( $key ) . $key;
@@ -49,9 +53,13 @@ class DeleteArchivedFilesImplementation {
$sha1 = LocalRepo::getHashFromKey( $key );
}
// Check if the file is used anywhere...
- $inuse = $dbw->selectField( 'oldimage', '1',
- array( 'oi_sha1' => $sha1,
- 'oi_deleted & ' . File::DELETED_FILE => File::DELETED_FILE ),
+ $inuse = $dbw->selectField(
+ 'oldimage',
+ '1',
+ array(
+ 'oi_sha1' => $sha1,
+ 'oi_deleted & ' . File::DELETED_FILE => File::DELETED_FILE
+ ),
__METHOD__,
array( 'FOR UPDATE' )
);
diff --git a/maintenance/deleteArchivedFiles.php b/maintenance/deleteArchivedFiles.php
index ad7b54d0..286b1f24 100644
--- a/maintenance/deleteArchivedFiles.php
+++ b/maintenance/deleteArchivedFiles.php
@@ -47,6 +47,7 @@ class DeleteArchivedFiles extends Maintenance {
public function execute() {
if ( !$this->hasOption( 'delete' ) ) {
$this->output( "Use --delete to actually confirm this script\n" );
+
return;
}
$force = $this->hasOption( 'force' );
diff --git a/maintenance/deleteArchivedRevisions.inc b/maintenance/deleteArchivedRevisions.inc
index dd8e3dd4..ed620ee3 100644
--- a/maintenance/deleteArchivedRevisions.inc
+++ b/maintenance/deleteArchivedRevisions.inc
@@ -30,8 +30,7 @@ class DeleteArchivedRevisionsImplementation {
/**
* Perform the delete on archived revisions.
-
- * @param $maint Object An object (typically of class Maintenance)
+ * @param object $maint An object (typically of class Maintenance)
* that implements two methods: handleOutput() and
* purgeRedundantText(). See Maintenance for a description of
* those methods.
diff --git a/maintenance/deleteArchivedRevisions.php b/maintenance/deleteArchivedRevisions.php
index ffd581c1..30883ba4 100644
--- a/maintenance/deleteArchivedRevisions.php
+++ b/maintenance/deleteArchivedRevisions.php
@@ -36,7 +36,8 @@ require_once __DIR__ . '/deleteArchivedRevisions.inc';
class DeleteArchivedRevisions extends Maintenance {
public function __construct() {
parent::__construct();
- $this->mDescription = "Deletes all archived revisions\nThese revisions will no longer be restorable";
+ $this->mDescription =
+ "Deletes all archived revisions\nThese revisions will no longer be restorable";
$this->addOption( 'delete', 'Performs the deletion' );
}
@@ -53,7 +54,8 @@ class DeleteArchivedRevisions extends Maintenance {
$dbw = wfGetDB( DB_MASTER );
$res = $dbw->selectRow( 'archive', 'COUNT(*) as count', array(), __FUNCTION__ );
$this->output( "Found {$res->count} revisions to delete.\n" );
- $this->output( "Please run the script again with the --delete option to really delete the revisions.\n" );
+ $this->output( "Please run the script again with the --delete option "
+ . "to really delete the revisions.\n" );
}
}
}
diff --git a/maintenance/deleteBatch.php b/maintenance/deleteBatch.php
index c1cc03cd..93507b34 100644
--- a/maintenance/deleteBatch.php
+++ b/maintenance/deleteBatch.php
@@ -3,11 +3,11 @@
* Deletes a batch of pages.
* Usage: php deleteBatch.php [-u <user>] [-r <reason>] [-i <interval>] [listfile]
* where
- * [listfile] is a file where each line contains the title of a page to be
- * deleted, standard input is used if listfile is not given.
- * <user> is the username
- * <reason> is the delete reason
- * <interval> is the number of seconds to sleep for after each delete
+ * [listfile] is a file where each line contains the title of a page to be
+ * deleted, standard input is used if listfile is not given.
+ * <user> is the username
+ * <reason> is the delete reason
+ * <interval> is the number of seconds to sleep for after each delete
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -79,7 +79,9 @@ class DeleteBatch extends Maintenance {
$dbw = wfGetDB( DB_MASTER );
# Handle each entry
+ // @codingStandardsIgnoreStart Ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed
for ( $linenum = 1; !feof( $file ); $linenum++ ) {
+ // @codingStandardsIgnoreEnd
$line = trim( fgets( $file ) );
if ( $line == '' ) {
continue;
@@ -97,7 +99,7 @@ class DeleteBatch extends Maintenance {
$this->output( $title->getPrefixedText() );
$dbw->begin( __METHOD__ );
if ( $title->getNamespace() == NS_FILE ) {
- $img = wfFindFile( $title );
+ $img = wfFindFile( $title, array( 'ignoreRedirect' => true ) );
if ( $img && $img->isLocal() && !$img->delete( $reason ) ) {
$this->output( " FAILED to delete associated file... " );
}
diff --git a/maintenance/deleteDefaultMessages.php b/maintenance/deleteDefaultMessages.php
index 7d8c80e4..5aeeb8e1 100644
--- a/maintenance/deleteDefaultMessages.php
+++ b/maintenance/deleteDefaultMessages.php
@@ -34,7 +34,7 @@ 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\"";
+ " which were last edited by \"MediaWiki default\"";
}
public function execute() {
@@ -54,6 +54,7 @@ class DeleteDefaultMessages extends Maintenance {
if ( $dbr->numRows( $res ) == 0 ) {
# No more messages left
$this->output( "done.\n" );
+
return;
}
diff --git a/maintenance/deleteEqualMessages.php b/maintenance/deleteEqualMessages.php
index 81758913..dbe96982 100644
--- a/maintenance/deleteEqualMessages.php
+++ b/maintenance/deleteEqualMessages.php
@@ -30,15 +30,18 @@ require_once __DIR__ . '/Maintenance.php';
class DeleteEqualMessages extends Maintenance {
public function __construct() {
parent::__construct();
- $this->mDescription = "Deletes all pages in the MediaWiki namespace that are equal to the default message";
+ $this->mDescription = 'Deletes all pages in the MediaWiki namespace that are equal to '
+ . 'the default message';
$this->addOption( 'delete', 'Actually delete the pages (default: dry run)' );
$this->addOption( 'delete-talk', 'Don\'t leave orphaned talk pages behind during deletion' );
- $this->addOption( 'lang-code', 'Check for subpages of this language code (default: root page against content language). ' .
- 'Use value "*" to run for all mwfile language code subpages (including the base pages that override content language).', false, true );
+ $this->addOption( 'lang-code', 'Check for subpages of this language code (default: root '
+ . 'page against content language). Use value "*" to run for all mwfile language code '
+ . 'subpages (including the base pages that override content language).', false, true );
}
/**
* @param string|bool $langCode See --lang-code option.
+ * @param array &$messageInfo
*/
protected function fetchMessageInfo( $langCode, array &$messageInfo ) {
global $wgContLang;
@@ -59,7 +62,8 @@ class DeleteEqualMessages extends Maintenance {
// Normalise message names for NS_MEDIAWIKI page_title
$messageNames = array_map( array( $wgContLang, 'ucfirst' ), $messageNames );
- $statuses = AllmessagesTablePager::getCustomisedStatuses( $messageNames, $langCode, $nonContLang );
+ $statuses = AllMessagesTablePager::getCustomisedStatuses(
+ $messageNames, $langCode, $nonContLang );
// getCustomisedStatuses is stripping the sub page from the page titles, add it back
$titleSuffix = $nonContLang ? "/$langCode" : '';
@@ -130,11 +134,14 @@ class DeleteEqualMessages extends Maintenance {
if ( $messageInfo['equalPages'] === 0 ) {
// No more equal messages left
$this->output( "\ndone.\n" );
+
return;
}
- $this->output( "\n{$messageInfo['relevantPages']} pages in the MediaWiki namespace override messages." );
- $this->output( "\n{$messageInfo['equalPages']} pages are equal to the default message (+ {$messageInfo['equalPagesTalks']} talk pages).\n" );
+ $this->output( "\n{$messageInfo['relevantPages']} pages in the MediaWiki namespace "
+ . "override messages." );
+ $this->output( "\n{$messageInfo['equalPages']} pages are equal to the default message "
+ . "(+ {$messageInfo['equalPagesTalks']} talk pages).\n" );
if ( !$doDelete ) {
$list = '';
@@ -151,6 +158,7 @@ class DeleteEqualMessages extends Maintenance {
$this->output( " (include --delete-talk to also delete the talk pages)" );
}
$this->output( "\n" );
+
return;
}
@@ -170,7 +178,6 @@ class DeleteEqualMessages extends Maintenance {
foreach ( $messageInfo['results'] as $result ) {
wfWaitForSlaves();
$dbw->ping();
- $dbw->begin( __METHOD__ );
$title = Title::makeTitle( NS_MEDIAWIKI, $result['title'] );
$this->output( "\n* [[$title]]" );
$page = WikiPage::factory( $title );
@@ -181,9 +188,9 @@ class DeleteEqualMessages extends Maintenance {
$this->output( "\n* [[$title]]" );
$page = WikiPage::factory( $title );
$error = ''; // Passed by ref
- $page->doDeleteArticle( 'Orphaned talk page of no longer required message', false, 0, false, $error, $user );
+ $page->doDeleteArticle( 'Orphaned talk page of no longer required message',
+ false, 0, false, $error, $user );
}
- $dbw->commit( __METHOD__ );
}
$this->output( "\n\ndone!\n" );
}
diff --git a/maintenance/deleteImageMemcached.php b/maintenance/deleteImageMemcached.php
index 835de352..4799e5e0 100644
--- a/maintenance/deleteImageMemcached.php
+++ b/maintenance/deleteImageMemcached.php
@@ -60,7 +60,12 @@ class DeleteImageCache extends Maintenance {
foreach ( $res as $row ) {
if ( $i % $this->report == 0 ) {
- $this->output( sprintf( "%s: %13s done (%s)\n", wfWikiID(), "$i/$total", wfPercent( $i / $total * 100 ) ) );
+ $this->output( sprintf(
+ "%s: %13s done (%s)\n",
+ wfWikiID(),
+ "$i/$total",
+ wfPercent( $i / $total * 100 )
+ ) );
}
$md5 = md5( $row->img_name );
$wgMemc->delete( wfMemcKey( 'Image', $md5 ) );
@@ -75,6 +80,7 @@ class DeleteImageCache extends Maintenance {
private function getImageCount() {
$dbr = wfGetDB( DB_SLAVE );
+
return $dbr->selectField( 'image', 'COUNT(*)', array(), __METHOD__ );
}
}
diff --git a/maintenance/deleteOrphanedRevisions.php b/maintenance/deleteOrphanedRevisions.php
index f0a96928..7f1ffe41 100644
--- a/maintenance/deleteOrphanedRevisions.php
+++ b/maintenance/deleteOrphanedRevisions.php
@@ -49,7 +49,8 @@ class DeleteOrphanedRevisions extends Maintenance {
# Find all the orphaned revisions
$this->output( "Checking for orphaned revisions..." );
- $sql = "SELECT rev_id FROM {$revision} LEFT JOIN {$page} ON rev_page = page_id WHERE page_namespace IS NULL";
+ $sql = "SELECT rev_id FROM {$revision} LEFT JOIN {$page} ON rev_page = page_id "
+ . "WHERE page_namespace IS NULL";
$res = $dbw->query( $sql, 'deleteOrphanedRevisions' );
# Stash 'em all up for deletion (if needed)
@@ -80,8 +81,8 @@ class DeleteOrphanedRevisions extends Maintenance {
* Delete one or more revisions from the database
* Do this inside a transaction
*
- * @param $id Array of revision id values
- * @param $dbw DatabaseBase class (needs to be a master)
+ * @param array $id Array of revision id values
+ * @param DatabaseBase $dbw DatabaseBase class (needs to be a master)
*/
private function deleteRevs( $id, &$dbw ) {
if ( !is_array( $id ) ) {
diff --git a/maintenance/deleteRevision.php b/maintenance/deleteRevision.php
index 6bc0f7cd..818ee360 100644
--- a/maintenance/deleteRevision.php
+++ b/maintenance/deleteRevision.php
@@ -42,41 +42,64 @@ class DeleteRevision extends Maintenance {
}
$this->output( "Deleting revision(s) " . implode( ',', $this->mArgs ) .
- " from " . wfWikiID() . "...\n" );
+ " 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_page_id' => 'page_id',
- 'ar_comment' => 'rev_comment',
- 'ar_user' => 'rev_user',
- 'ar_user_text' => 'rev_user_text',
- 'ar_timestamp' => 'rev_timestamp',
+ 'ar_namespace' => 'page_namespace',
+ 'ar_title' => 'page_title',
+ 'ar_page_id' => 'page_id',
+ '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',
- 'ar_deleted' => 'rev_deleted',
- 'ar_len' => 'rev_len',
- ), array(
+ 'ar_rev_id' => 'rev_id',
+ 'ar_text_id' => 'rev_text_id',
+ 'ar_deleted' => 'rev_deleted',
+ 'ar_len' => 'rev_len',
+ ),
+ array(
'rev_id' => $revID,
'page_id = rev_page'
- ), __METHOD__
+ ),
+ __METHOD__
);
if ( !$dbw->affectedRows() ) {
$this->output( "Revision $revID not found\n" );
} else {
$affected += $dbw->affectedRows();
- $pageID = $dbw->selectField( 'revision', 'rev_page', array( 'rev_id' => $revID ), __METHOD__ );
- $pageLatest = $dbw->selectField( 'page', 'page_latest', array( 'page_id' => $pageID ), __METHOD__ );
+ $pageID = $dbw->selectField(
+ 'revision',
+ 'rev_page',
+ array( 'rev_id' => $revID ),
+ __METHOD__
+ );
+ $pageLatest = $dbw->selectField(
+ 'page',
+ 'page_latest',
+ array( 'page_id' => $pageID ),
+ __METHOD__
+ );
$dbw->delete( 'revision', array( 'rev_id' => $revID ) );
if ( $pageLatest == $revID ) {
// Database integrity
- $newLatest = $dbw->selectField( 'revision', 'rev_id', array( 'rev_page' => $pageID ), __METHOD__, array( 'ORDER BY' => 'rev_timestamp DESC' ) );
- $dbw->update( 'page', array( 'page_latest' => $newLatest ), array( 'page_id' => $pageID ), __METHOD__ );
+ $newLatest = $dbw->selectField(
+ 'revision',
+ 'rev_id',
+ array( 'rev_page' => $pageID ),
+ __METHOD__,
+ array( 'ORDER BY' => 'rev_timestamp DESC' )
+ );
+ $dbw->update(
+ 'page',
+ array( 'page_latest' => $newLatest ),
+ array( 'page_id' => $pageID ),
+ __METHOD__
+ );
}
}
}
diff --git a/maintenance/dev/includes/php.sh b/maintenance/dev/includes/php.sh
index 7ce87944..3c5bef0d 100644
--- a/maintenance/dev/includes/php.sh
+++ b/maintenance/dev/includes/php.sh
@@ -4,7 +4,7 @@
# and previous home directory location
# The binary path is returned in $PHP if any
-for binary in $PHP `which php || true` "$DEV/php/bin/php" "$HOME/.mediawiki/php/bin/php" "$HOME/.mwphp/bin/php" ]; do
+for binary in $PHP $(which php || true) "$DEV/php/bin/php" "$HOME/.mediawiki/php/bin/php" "$HOME/.mwphp/bin/php" ]; do
if [ -x "$binary" ]; then
if "$binary" -r 'exit((int)!version_compare(PHP_VERSION, "5.4", ">="));'; then
PHP="$binary"
diff --git a/maintenance/dev/includes/router.php b/maintenance/dev/includes/router.php
index a3cc0ba3..0a65e31e 100644
--- a/maintenance/dev/includes/router.php
+++ b/maintenance/dev/includes/router.php
@@ -59,6 +59,7 @@ if ( $ext == 'php' || $ext == 'php5' ) {
# the php webserver will discard post data and things like login
# will not function in the dev environment.
require $file;
+
return true;
}
$mime = false;
@@ -79,7 +80,7 @@ if ( !$mime ) {
}
}
if ( $mime ) {
- # Use custom handling to serve files with a known mime type
+ # Use custom handling to serve files with a known MIME type
# This way we can serve things like .svg files that the built-in
# PHP webserver doesn't understand.
# ;) Nicely enough we just happen to bundle a mime.types file
@@ -93,6 +94,7 @@ if ( $mime ) {
header( "Content-Length: " . filesize( $file ) );
// Stream that out to the browser
fpassthru( $f );
+
return true;
}
diff --git a/maintenance/dictionary/mediawiki.dic b/maintenance/dictionary/mediawiki.dic
index 164b5b05..df8a34ca 100644
--- a/maintenance/dictionary/mediawiki.dic
+++ b/maintenance/dictionary/mediawiki.dic
@@ -1,10 +1,10 @@
-ænglisc
-ævar
&add
&amp
&bar
+&img
&sim
&url
+&wap
ABNF
API
Aacute
@@ -90,7 +90,6 @@ Edit
Editor
Education
Egrave
-Ehcache
Elig
Email
Empty
@@ -367,6 +366,7 @@ abusive
ac
acad
accel
+acceptbilling
acceptlang
accessdenied
accesskey
@@ -431,6 +431,8 @@ ai
aifc
aiff
aiprop
+airtel
+aisort
ajaxwatch
al
alefsym
@@ -442,6 +444,7 @@ allcategories
alldata
alle
allexamples
+allfileusages
allhidden
allimages
allimit
@@ -459,6 +462,8 @@ allpagesbadtitle
allpagesprefix
allpagesredirect
allpagessubmit
+allpartners
+allredirects
allrev
alltitles
alltransclusions
@@ -471,15 +476,16 @@ alreadyexists
alreadyrolled
alunique
am
+analyticsconfig
anchor
anchorclose
anchorencode
and
andconvert
+andreescu
andtitle
anon
anoneditwarning
-anonlogin
anonnotice
anononly
anonpreviewwarning
@@ -656,6 +662,7 @@ badversion
balancer
balancers
banjar
+barebone
barstein
base
basefont
@@ -685,6 +692,7 @@ bgcolor
bgzip
bidi
bigdelete
+bingbot
binhex
bitdepth
bitfield
@@ -742,11 +750,13 @@ bmwschema
bmysql
bname
bodycontent
+bogo
boldening
bolding
booksources
bool
boolean
+bordercolor
borderhack
bot
botedit
@@ -831,12 +841,14 @@ capitalizeallnouns
captchaid
captchas
captchaword
+carriersnoips
cascade
cascadeable
cascadeon
cascadeprotected
cascadeprotectedwarning
cascading
+cascadinglevels
cascadingness
categories
categories's
@@ -850,6 +862,7 @@ categorypage
categoryviewer
catids
catlinks
+catmsg
catpage
catrope
cattitles
@@ -863,6 +876,7 @@ cedil
ceebc
cellpadding
cellspacing
+cellulant
central
centralauth
centralnotice
@@ -941,7 +955,6 @@ collapsable
collectionsaveascommunitypage
collectionsaveasuserpage
colname
-cologneblue
colonseparator
colorer
colspan
@@ -1070,6 +1083,7 @@ danga
danielc
darr
datalen
+datapath
dataset
datasets
datasize
@@ -1110,6 +1124,7 @@ defaultcontentmodel
defaultmessagetext
defaultmissing
defaultns
+defaultoptions
defaultsort
defaultval
deferr
@@ -1170,6 +1185,7 @@ devangari
devel
df
dflt
+dflts
dhtml
diams
didn
@@ -1197,7 +1213,6 @@ disabled
disabledtranscode
disablemail
disablepp
-disablesuggest
disclaimerpage
diskussion
displayname
@@ -1237,6 +1252,7 @@ domainpart
domainparts
domas
doms
+dont
dotdotcount
dotm
dotsc
@@ -1254,6 +1270,7 @@ dropdown
dump
dumpfm
dupfunc
+dupl
duplicatefiles
duplicatesoffile
dvips
@@ -1314,7 +1331,6 @@ editusercssjs
edituserjs
edoe
egrave
-ehcache
ei
eich
eiinvalidparammix
@@ -1322,7 +1338,9 @@ eimissingparam
eititle
el
elapsedreal
+elastica
elemname
+elems
elink
eltitle
email
@@ -1385,6 +1403,7 @@ epcampus
epcoordinator
epinstructor
eponline
+eqiad
erevoke
errno
error
@@ -1441,6 +1460,7 @@ externaldberror
externaldiff
externaledit
externaleditor
+externalimages
externallinks
externalstore
extet
@@ -1450,6 +1470,7 @@ extlinks
extracts
extradata
extrafields
+extralanglink
extraq
extratags
exturlusage
@@ -1520,6 +1541,7 @@ filepage
filepath
filerenameerror
filerepo
+filerepoinfo
filerevert
filerevisions
files
@@ -1558,6 +1580,7 @@ flagtype
flatlist
flds
float
+flrevs
fmttime
fname
fnof
@@ -1576,6 +1599,7 @@ forcebot
forceditsummary
forceeditsummary
forcelinkupdate
+forcerecursivelinkupdate
forcetoc
forcontent
formaction
@@ -1593,6 +1617,7 @@ found
founder
fr
frac
+frameborder
frameless
framesets
frasl
@@ -1629,12 +1654,15 @@ gadgetcategories
gadgets
gaid
gaifilterredir
+gaifrom
gallerybox
gallerycaption
gallerytext
gapdir
gapfilterredir
+gapfrom
gaplimit
+gapnamespace
gapprefix
garber
gblblock
@@ -1648,8 +1676,10 @@ general
generatexml
generator
geocoordinate
+geodata
geosearch
gerrit
+geshi
getcookie
getenv
getheader
@@ -1686,6 +1716,7 @@ globe
gmail
gmdate
goodtitle
+googlebot
gopher
graymap
grayscale
@@ -1782,8 +1813,8 @@ hit
hitcount
hitcounter
hits
+hlist
hmac
-hmtl
hobby
homelink
hookaborted
@@ -1847,9 +1878,11 @@ ilfrom
ilto
im
image
+imagecolorallocate
imagegetsize
imageinfo
imageinvalidfilename
+imagelimits
imagelinks
imagemagick
imagemaxsize
@@ -1862,6 +1895,7 @@ imagesize
imagetype
imagetypemismatch
imageusage
+imagewhitelistenabled
imagick
imgmultigo
imgmultigoto
@@ -1933,6 +1967,7 @@ interwiki
interwikimap
interwikipage
interwikis
+interwikisearchinfo
interwikisource
intnull
intoken
@@ -1980,6 +2015,8 @@ ipchain
ipedits
iphash
ipinrange
+ipset
+ipsets
ipusers
iquest
irc
@@ -1991,12 +2028,14 @@ isconnected
iscur
isin
isip
+islocal
ismap
isminor
ismodsince
ismulti
isnew
ispermalink
+isroot
isself
isset
istainted
@@ -2024,6 +2063,7 @@ iwltitle
iwprefix
iwtitle
iwurl
+ized
javascript
javascripttest
jbartsh
@@ -2042,6 +2082,7 @@ jslint
jsmimetype
jsminplus
json
+jsonconfig
jsonfm
jsparse
jstext
@@ -2060,6 +2101,7 @@ keyname
keynames
keytype
khash
+kikongo
kludgy
knownnamespace
konqueror
@@ -2075,11 +2117,13 @@ langcode
langcodes
langconversion
langlinks
+langname
langprop
langs
language
languagelinks
languages
+languageselection
languageshtml
laquo
large
@@ -2090,6 +2134,7 @@ lastdot
lastedit
lasteditor
lastedittime
+lastfile
lastlink
lastmod
lastmodifiedat
@@ -2140,6 +2185,8 @@ link
linkarr
linkcolour
linkprefix
+linkprefixcharset
+linkpurge
links
linkstoimage
linktbl
@@ -2175,6 +2222,7 @@ localdayname
localdow
locale
localhour
+localinterwiki
localmonth
localmonthabbrev
localmonthname
@@ -2205,6 +2253,7 @@ loginerror
loginfo
loginlanguagelinks
loginlink
+loginout
loginprompt
loginreqlink
loginreqpagetext
@@ -2241,7 +2290,6 @@ ltitle
ltrimmed
lurl
lysator
-möller
macr
magicarr
magicfile
@@ -2260,6 +2308,7 @@ mailtext
mailto
mainmodule
mainpage
+maint
maintainership
makesafe
male
@@ -2295,16 +2344,19 @@ maxwidth
mazeland
mbresponse
mbstring
+mccmnc
mckey
mcklmqw
mcrypt
mcvalue
md
mdash
+mdot
medialink
mediaqueries
mediatype
mediawarning
+mediawiki
mediawiki's
mediawikipage
megapixels
@@ -2385,6 +2437,7 @@ mkdir
mms
mobile
mobileformat
+mobilelanding
mobileview
modified
modifiedarticleprotection
@@ -2405,6 +2458,7 @@ moodbar
moredotdotdot
morelinkstoimage
morethan
+mouseup
move
movedarticleprotection
moveddeleted
@@ -2442,6 +2496,7 @@ msgsmall
msgtext
msie
msmetafile
+msnbot
mssql
msvideo
msword
@@ -2449,6 +2504,7 @@ mtime
mtype
mullane
multi
+multiactions
multibyte
multicast
multipage
@@ -2486,10 +2542,13 @@ mysqldump
mytalk
mytext
mywatchlist
+möller
nabla
name
namehidden
nameinlowercase
+namelookup
+namemsg
names
namespace
namespacealiases
@@ -2530,9 +2589,7 @@ newheader
newid
newimages
newlen
-newmessagesdifflink
newmessagesdifflinkplural
-newmessageslink
newmessageslinkplural
newname
newnames
@@ -2548,6 +2605,7 @@ newpos
newquery
newrevid
news
+newsectionheaderdefaultlevel
newsectionlink
newsectionsummary
newset
@@ -2574,6 +2632,7 @@ nextredirect
nextrevision
nextval
nfkc
+nfkd
nginx
nheight
niklas
@@ -2787,6 +2846,7 @@ noto
notoc
notoggle
notoken
+notpatrollable
notransform
notreviewable
notrustworthy
@@ -2888,6 +2948,7 @@ oldtitle
oldtitlemsg
oline
oname
+onerror
onkeyup
online
onload
@@ -2898,6 +2959,7 @@ onlyquery
onsubmit
onthisday
ontop
+onuser
openbasedir
opendoc
opendocument
@@ -2906,6 +2968,7 @@ opensearchdescription
openssl's
openxml
openxmlformats
+operamini
oplus
oppositedm
optgroup
@@ -2920,6 +2983,7 @@ ordertype
ordf
ordm
org
+orghttp
origcategory
ortime
oslash
@@ -2991,6 +3055,7 @@ pagetriagetagging
pagetriagetemplate
pageurl
pageview
+pango
param
parameters
paraminfo
@@ -3091,8 +3156,10 @@ pltitles
plusminus
plusmn
pname
+png'd
pnmtojpeg
pnmtopng
+pointsize
poolcounter
popts
popularpages
@@ -3117,17 +3184,18 @@ pptm
pptx
precaching
precompiled
+preemptively
preferences
preferencestoken
prefill
prefilled
prefix
prefixindex
+prefixsearch
prefixsearchdisabled
prefs
prefsection
-prefsnologin
-prefsnologintext
+prefsnologintext2
prefsubmit
preload
preloads
@@ -3139,6 +3207,7 @@ preprocessing
preprocessors
presentationml
presep
+pretransfer
prevchar
prevdiff
previd
@@ -3202,6 +3271,7 @@ protecttoken
proto
protocol
protocols
+protorel
protos
proxied
proxyblocker
@@ -3224,6 +3294,7 @@ purged
qabardjajəbza
qbar
qbsettings
+qlow
qmoicj
qp
quasit
@@ -3242,6 +3313,7 @@ querytype
question
queuefull
quickbar
+quicksorts
quicktemplate
quicktime
qunit
@@ -3337,6 +3409,7 @@ redirectable
redirectcreated
redirectedfrom
redirections
+redirector
redirectpagesub
redirectparams
redirects
@@ -3351,6 +3424,7 @@ redis
redlink
redlinks
redocument
+redux
reedyboy
reenables
reencode
@@ -3377,7 +3451,6 @@ relname
relnamespace
remarticle
remembermypassword
-rememberpassword
removablegroups
removal
remove
@@ -3389,6 +3462,8 @@ remstudent
renameuser
renaming
renderable
+renderesibanner
+renderwarning
renormalized
repeating
repl
@@ -3574,6 +3649,7 @@ selflink
selfmove
semiglobal
semiprotected
+semiprotectedlevels
semiprotectedpagewarning
sendemail
sendmail
@@ -3692,9 +3768,14 @@ slideshow
sm
smaxage
smil
+smpp
+sms's
+smscontent
+smslogs
smtp
snippet
sodipodi
+softredirect
softtabstop
solaris
somecontent
@@ -3748,6 +3829,7 @@ stabilize
stable
stablesettings
stansvik
+starcode
start
startid
startime
@@ -3755,6 +3837,7 @@ startsortkey
startsortkeyprefix
starttime
starttimestamp
+starttransfer
stash
stashfailed
stashimageinfo
@@ -3771,6 +3854,7 @@ stopwords
storedversion
strcasecmp
strcmp
+strftime
string
stripos
stripslashes
@@ -3887,6 +3971,7 @@ taglist
tags
tagset
tagstack
+tahoma
tailorings
talk
talkable
@@ -3904,8 +3989,8 @@ talkpagetext
talkspace
talkspacee
talkto
-taraškievica
tarask
+taraškievica
target
tb
tbase
@@ -3932,6 +4017,7 @@ test
testclean
testdata
testmailuser
+teston
testpass
testrunner
testswarm
@@ -3972,6 +4058,7 @@ thumbheight
thumbhtml
thumbimage
thumbinner
+thumblimits
thumbmime
thumbnail
thumbnailing
@@ -4045,6 +4132,7 @@ toparse
topbar
toplevel
toplinks
+topojson
toponly
torev
torevid
@@ -4076,7 +4164,9 @@ transwiki
troff
true
truespeed
+truncatedtext
trustworthy
+truteq
truthy
tsearch
tsquery
@@ -4099,6 +4189,7 @@ udpprofile
ufffd
ugrave
ui
+uids
uint
ulimit
ulink
@@ -4124,6 +4215,8 @@ undel
undelete
undeleted
undeletion
+undismissable
+undismissible
undo
undoafter
undofailure
@@ -4138,6 +4231,7 @@ unhelpful
unhidden
unhide
unidata
+unidecode
unindent
unindexed
uniq
@@ -4165,6 +4259,7 @@ unprotect
unprotectedarticle
unprotection
unprotectthispage
+unreadcount
unredacted
unrequest
unrequested
@@ -4177,6 +4272,7 @@ unseed
unserialization
unserialize
unserialized
+unserializes
unserializing
unsetting
unstub
@@ -4220,6 +4316,7 @@ uploadscripted
uploadsource
uploadstash
uploadvirus
+uploadwarning
uppercased
upsih
urandom
@@ -4303,6 +4400,9 @@ usertoollinks
useskin
useto
usort
+usrmonth
+ussd
+ussdcontent
ustar
ustoken
utfnormal
@@ -4347,6 +4447,7 @@ viewdeleted
viewhelppage
viewmyprivateinfo
viewmywatchlist
+viewport
viewprevnext
viewsource
viewsourcelink
@@ -4363,6 +4464,7 @@ vorbis
vpad
vrml
vslow
+vumi
vvcv
vxml
wais
@@ -4400,6 +4502,7 @@ wbxml
wddx
wddxfm
weblog
+weblogs
webm
webp
webrequest
@@ -4442,17 +4545,23 @@ wikilove
wikiloveimagelog
wikimedia
wikimediacommons
+wikimediafoundation
+wikinews
wikipage
wikipedia
wikipedian
wikipedias
+wikiquote
wikis
+wikisource
wikisyntax
wikitable
wikitables
wikitech
wikitext
wikiuser
+wikiversity
+wikivoyage
wiktionary
wincache
wininet
@@ -4477,6 +4586,7 @@ wmls
wmlsc
wmlscript
wmlscriptc
+wmnet
wordcount
wordprocessingml
wordwg
@@ -4491,6 +4601,7 @@ writerequired
writerights
wrongpassword
x
+xanalytics
xbitmap
xcache
xcancel
@@ -4512,8 +4623,8 @@ xml
xmldoublequote
xmlfm
xmlimport
+xmlmeta
xmlns
-xmlsafe
xmlselect
xor
xpinstall
@@ -4526,6 +4637,7 @@ xxxxx
yacute
yaml
yamlfm
+yandex
year
yes
youhavenewmessages
@@ -4547,10 +4659,26 @@ yourvariant
yourwiki
yuml
yyyymmddhhiiss
+zcmd
+zerobanner
+zerobar
+zerobutton
+zeroconfig
+zerodontask
+zerodot
+zeroinfo
+zeronet
+zeroportal
+zfile
zhdaemon
zhengzhu
zhtable
zijdel
+zlang
zlib
zoffset
+zrma
zwnj
+ænglisc
+ævar
+świerkosz
diff --git a/maintenance/doMaintenance.php b/maintenance/doMaintenance.php
index 3bd508cb..46844c9d 100644
--- a/maintenance/doMaintenance.php
+++ b/maintenance/doMaintenance.php
@@ -44,6 +44,7 @@ if ( !$maintClass || !class_exists( $maintClass ) ) {
}
// Get an object to start us off
+/** @var Maintenance $maintenance */
$maintenance = new $maintClass();
// Basic sanity checks and such
@@ -77,37 +78,24 @@ if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
# Use a callback function to configure MediaWiki
call_user_func( MW_CONFIG_CALLBACK );
} else {
- if ( file_exists( "$IP/../wmf-config/wikimedia-mode" ) ) {
- // Load settings, using wikimedia-mode if needed
- // @todo FIXME: Replace this hack with general farm-friendly code
- # @todo FIXME: Wikimedia-specific stuff needs to go away to an ext
- # Maybe a hook?
- global $cluster;
- $cluster = 'pmtpa';
- require "$IP/../wmf-config/wgConf.php";
- }
// Require the configuration (probably LocalSettings.php)
require $maintenance->loadSettings();
}
-if ( $maintenance->getDbType() === Maintenance::DB_ADMIN &&
- is_readable( "$IP/AdminSettings.php" ) )
-{
- require "$IP/AdminSettings.php";
-}
-
if ( $maintenance->getDbType() === Maintenance::DB_NONE ) {
- if ( $wgLocalisationCacheConf['storeClass'] === false && ( $wgLocalisationCacheConf['store'] == 'db' || ( $wgLocalisationCacheConf['store'] == 'detect' && !$wgCacheDirectory ) ) ) {
- $wgLocalisationCacheConf['storeClass'] = 'LCStore_Null';
+ if ( $wgLocalisationCacheConf['storeClass'] === false
+ && ( $wgLocalisationCacheConf['store'] == 'db'
+ || ( $wgLocalisationCacheConf['store'] == 'detect' && !$wgCacheDirectory ) )
+ ) {
+ $wgLocalisationCacheConf['storeClass'] = 'LCStoreNull';
}
}
+
+$maintenance->setConfig( ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
$maintenance->finalSetup();
// Some last includes
require_once "$IP/includes/Setup.php";
-// Much much faster startup than creating a title object
-$wgTitle = null;
-
// Do the work
try {
$maintenance->execute();
diff --git a/maintenance/dumpBackup.php b/maintenance/dumpBackup.php
index 25a777cd..18c78dcd 100644
--- a/maintenance/dumpBackup.php
+++ b/maintenance/dumpBackup.php
@@ -4,7 +4,7 @@
* wrapper format for export or backup
*
* Copyright © 2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -127,5 +127,5 @@ Fancy stuff: (Works? Add examples please.)
--filter=<type>[:<options>] Add a filter on an output branch
ENDS
-);
+ );
}
diff --git a/maintenance/dumpIterator.php b/maintenance/dumpIterator.php
index dd468a9f..4b2ff717 100644
--- a/maintenance/dumpIterator.php
+++ b/maintenance/dumpIterator.php
@@ -5,7 +5,7 @@
* We implement below the simple task of searching inside a dump.
*
* Copyright © 2011 Platonides
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -57,8 +57,11 @@ abstract class DumpIterator extends Maintenance {
$revision = new WikiRevision;
$revision->setText( file_get_contents( $this->getOption( 'file' ) ) );
- $revision->setTitle( Title::newFromText( rawurldecode( basename( $this->getOption( 'file' ), '.txt' ) ) ) );
+ $revision->setTitle( Title::newFromText(
+ rawurldecode( basename( $this->getOption( 'file' ), '.txt' ) )
+ ) );
$this->handleRevision( $revision );
+
return;
}
@@ -67,7 +70,8 @@ abstract class DumpIterator extends Maintenance {
if ( $this->getOption( 'dump' ) == '-' ) {
$source = new ImportStreamSource( $this->getStdin() );
} else {
- $this->error( "Sorry, I don't support dump filenames yet. Use - and provide it on stdin on the meantime.", true );
+ $this->error( "Sorry, I don't support dump filenames yet. "
+ . "Use - and provide it on stdin on the meantime.", true );
}
$importer = new WikiImporter( $source );
@@ -86,8 +90,9 @@ abstract class DumpIterator extends Maintenance {
$this->error( round( $this->count / $delta, 2 ) . " pages/sec" );
}
- # Perform the memory_get_peak_usage() when all the other data has been output so there's no damage if it dies.
- # It is only available since 5.2.0 (since 5.2.1 if you haven't compiled with --enable-memory-limit)
+ # Perform the memory_get_peak_usage() when all the other data has been
+ # output so there's no damage if it dies. It is only available since
+ # 5.2.0 (since 5.2.1 if you haven't compiled with --enable-memory-limit)
$this->error( "Memory peak usage of " . memory_get_peak_usage() . " bytes\n" );
}
@@ -97,7 +102,7 @@ abstract class DumpIterator extends Maintenance {
if ( $this->getDbType() == Maintenance::DB_NONE ) {
global $wgUseDatabaseMessages, $wgLocalisationCacheConf, $wgHooks;
$wgUseDatabaseMessages = false;
- $wgLocalisationCacheConf['storeClass'] = 'LCStore_Null';
+ $wgLocalisationCacheConf['storeClass'] = 'LCStoreNull';
$wgHooks['InterwikiLoadPrefix'][] = 'DumpIterator::disableInterwikis';
}
}
@@ -112,12 +117,13 @@ abstract class DumpIterator extends Maintenance {
/**
* Callback function for each revision, child classes should override
* processRevision instead.
- * @param $rev Revision
+ * @param DatabaseBase $rev
*/
public function handleRevision( $rev ) {
$title = $rev->getTitle();
if ( !$title ) {
$this->error( "Got bogus revision with null title!" );
+
return;
}
@@ -167,7 +173,7 @@ class SearchDump extends DumpIterator {
}
/**
- * @param $rev Revision
+ * @param Revision $rev
*/
public function processRevision( $rev ) {
if ( preg_match( $this->getOption( 'regex' ), $rev->getContent()->getTextForSearchIndex() ) ) {
diff --git a/maintenance/dumpLinks.php b/maintenance/dumpLinks.php
index be0b4633..888c2dc1 100644
--- a/maintenance/dumpLinks.php
+++ b/maintenance/dumpLinks.php
@@ -9,7 +9,7 @@
* Dumps ASCII text to stdout; command-line.
*
* Copyright © 2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -59,7 +59,7 @@ class DumpLinks extends Maintenance {
$lastPage = null;
foreach ( $result as $row ) {
if ( $lastPage != $row->page_id ) {
- if ( isset( $lastPage ) ) {
+ if ( $lastPage !== null ) {
$this->output( "\n" );
}
$page = Title::makeTitle( $row->page_namespace, $row->page_title );
@@ -69,7 +69,7 @@ class DumpLinks extends Maintenance {
$link = Title::makeTitle( $row->pl_namespace, $row->pl_title );
$this->output( " " . $link->getPrefixedURL() );
}
- if ( isset( $lastPage ) ) {
+ if ( $lastPage !== null ) {
$this->output( "\n" );
}
}
diff --git a/maintenance/dumpSisterSites.php b/maintenance/dumpSisterSites.php
index 5f0c5b7c..784dc7a8 100644
--- a/maintenance/dumpSisterSites.php
+++ b/maintenance/dumpSisterSites.php
@@ -4,7 +4,7 @@
* http://www.eekim.com/cgi-bin/wiki.pl?SisterSites
*
* Copyright © 2006 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/maintenance/dumpTextPass.php b/maintenance/dumpTextPass.php
index 5d783cb9..7c176071 100644
--- a/maintenance/dumpTextPass.php
+++ b/maintenance/dumpTextPass.php
@@ -3,7 +3,7 @@
* Script that postprocesses XML dumps from dumpBackup.php to add page text
*
* Copyright (C) 2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,7 +29,6 @@ $originalDir = getcwd();
require_once __DIR__ . '/commandLine.inc';
require_once __DIR__ . '/backupTextPass.inc';
-
$dumper = new TextPassDumper( $argv );
if ( !isset( $options['help'] ) ) {
@@ -62,5 +61,5 @@ Options:
--spawn Spawn a subprocess for loading text records
--help Display this help message
ENDS
-);
+ );
}
diff --git a/maintenance/dumpUploads.php b/maintenance/dumpUploads.php
index 1a9293cb..9d53f07c 100644
--- a/maintenance/dumpUploads.php
+++ b/maintenance/dumpUploads.php
@@ -64,7 +64,7 @@ By default, outputs relative paths against the parent directory of \$wgUploadDir
$this->mSharedSupplement = true;
}
}
- $this-> { $this->mAction } ( $this->mShared );
+ $this->{$this->mAction} ( $this->mShared );
if ( $this->mSharedSupplement ) {
$this->fetchUsed( true );
}
@@ -73,7 +73,7 @@ By default, outputs relative paths against the parent directory of \$wgUploadDir
/**
* Fetch a list of used images from a particular image source.
*
- * @param $shared Boolean: true to pass shared-dir settings to hash func
+ * @param bool $shared True to pass shared-dir settings to hash func
*/
function fetchUsed( $shared ) {
$dbr = wfGetDB( DB_SLAVE );
@@ -94,7 +94,7 @@ By default, outputs relative paths against the parent directory of \$wgUploadDir
/**
* Fetch a list of all images from a particular image source.
*
- * @param $shared Boolean: true to pass shared-dir settings to hash func
+ * @param bool $shared True to pass shared-dir settings to hash func
*/
function fetchLocal( $shared ) {
$dbr = wfGetDB( DB_SLAVE );
diff --git a/maintenance/edit.php b/maintenance/edit.php
index 7c24f0fa..75ec12bf 100644
--- a/maintenance/edit.php
+++ b/maintenance/edit.php
@@ -38,11 +38,13 @@ class EditCLI extends Maintenance {
$this->addOption( 'bot', 'Bot edit', false, false, 'b' );
$this->addOption( 'autosummary', 'Enable autosummary', false, false, 'a' );
$this->addOption( 'no-rc', 'Do not show the change in recent changes', false, false, 'r' );
+ $this->addOption( 'nocreate', 'Don\'t create new pages', false, false );
+ $this->addOption( 'createonly', 'Only create new pages', false, false );
$this->addArg( 'title', 'Title of article to edit' );
}
public function execute() {
- global $wgUser, $wgTitle;
+ global $wgUser;
$userName = $this->getOption( 'user', 'Maintenance script' );
$summary = $this->getOption( 'summary', '' );
@@ -52,8 +54,6 @@ class EditCLI extends Maintenance {
$noRC = $this->hasOption( 'no-rc' );
$wgUser = User::newFromName( $userName );
- $context = RequestContext::getMain();
- $context->setUser( $wgUser );
if ( !$wgUser ) {
$this->error( "Invalid username", true );
}
@@ -61,17 +61,22 @@ class EditCLI extends Maintenance {
$wgUser->addToDatabase();
}
- $wgTitle = Title::newFromText( $this->getArg() );
- if ( !$wgTitle ) {
+ $title = Title::newFromText( $this->getArg() );
+ if ( !$title ) {
$this->error( "Invalid title", true );
}
- $context->setTitle( $wgTitle );
- $page = WikiPage::factory( $wgTitle );
+ if ( $this->hasOption( 'nocreate' ) && !$title->exists() ) {
+ $this->error( "Page does not exist", true );
+ } elseif ( $this->hasOption( 'createonly' ) && $title->exists() ) {
+ $this->error( "Page already exists", true );
+ }
+
+ $page = WikiPage::factory( $title );
# Read the text
$text = $this->getStdin( Maintenance::STDIN_ALL );
- $content = ContentHandler::makeContent( $text, $wgTitle );
+ $content = ContentHandler::makeContent( $text, $title );
# Do the edit
$this->output( "Saving... " );
diff --git a/maintenance/eraseArchivedFile.php b/maintenance/eraseArchivedFile.php
index 1c3f0376..94ca604d 100644
--- a/maintenance/eraseArchivedFile.php
+++ b/maintenance/eraseArchivedFile.php
@@ -27,7 +27,7 @@ require_once __DIR__ . '/Maintenance.php';
/**
* Maintenance script to delete archived (non-current) files from storage.
*
- * @TODO: Maybe add some simple logging
+ * @todo Maybe add some simple logging
*
* @ingroup Maintenance
* @since 1.22
diff --git a/maintenance/eval.php b/maintenance/eval.php
index abedc61a..51f2cace 100644
--- a/maintenance/eval.php
+++ b/maintenance/eval.php
@@ -1,6 +1,5 @@
<?php
/**
- * PHP lacks an interactive mode, but this can be very helpful when debugging.
* This script lets a command-line user start up the wiki engine and then poke
* about by issuing PHP commands directly.
*
@@ -56,7 +55,7 @@ if ( isset( $options['d'] ) ) {
}
$useReadline = function_exists( 'readline_add_history' )
- && Maintenance::posix_isatty( 0 /*STDIN*/ );
+ && Maintenance::posix_isatty( 0 /*STDIN*/ );
if ( $useReadline ) {
$historyFile = isset( $_ENV['HOME'] ) ?
@@ -64,13 +63,28 @@ if ( $useReadline ) {
readline_read_history( $historyFile );
}
+$e = null; // PHP exception
while ( ( $line = Maintenance::readconsole() ) !== false ) {
+ if ( $e && !preg_match( '/^(exit|die);?$/', $line ) ) {
+ // Internal state may be corrupted or fatals may occur later due
+ // to some object not being set. Don't drop out of eval in case
+ // lines were being pasted in (which would then get dumped to the shell).
+ // Instead, just absorb the remaning commands. Let "exit" through per DWIM.
+ echo "Exception was thrown before; please restart eval.php\n";
+ continue;
+ }
if ( $useReadline ) {
readline_add_history( $line );
readline_write_history( $historyFile );
}
- $val = eval( $line . ";" );
- if ( wfIsHipHop() || is_null( $val ) ) {
+ try {
+ $val = eval( $line . ";" );
+ } catch ( Exception $e ) {
+ echo "Caught exception " . get_class( $e ) .
+ ": {$e->getMessage()}\n" . $e->getTraceAsString() . "\n";
+ continue;
+ }
+ if ( wfIsHHVM() || is_null( $val ) ) {
echo "\n";
} elseif ( is_string( $val ) || is_numeric( $val ) ) {
echo "$val\n";
diff --git a/maintenance/fetchText.php b/maintenance/fetchText.php
index 05470d30..fc676b89 100644
--- a/maintenance/fetchText.php
+++ b/maintenance/fetchText.php
@@ -37,11 +37,11 @@ class FetchText extends Maintenance {
/**
* returns a string containing the following in order:
- * textid
- * \n
- * length of text (-1 on error = failure to retrieve/unserialize/gunzip/etc)
- * \n
- * text (may be empty)
+ * textid
+ * \n
+ * length of text (-1 on error = failure to retrieve/unserialize/gunzip/etc)
+ * \n
+ * text (may be empty)
*
* note that that the text string itself is *not* followed by newline
*/
@@ -59,8 +59,7 @@ class FetchText extends Maintenance {
if ( $text === false ) {
# actual error, not zero-length text
$textLen = "-1";
- }
- else {
+ } else {
$textLen = strlen( $text );
}
$this->output( $textId . "\n" . $textLen . "\n" . $text );
@@ -69,9 +68,9 @@ class FetchText extends Maintenance {
/**
* May throw a database error if, say, the server dies during query.
- * @param $db DatabaseBase object
- * @param $id int The old_id
- * @return String
+ * @param DatabaseBase $db
+ * @param int $id The old_id
+ * @return string
*/
private function doGetText( $db, $id ) {
$id = intval( $id );
@@ -83,6 +82,7 @@ class FetchText extends Maintenance {
if ( $text === false ) {
return false;
}
+
return $text;
}
}
diff --git a/maintenance/findHooks.php b/maintenance/findHooks.php
index 373170ff..36760d7e 100644
--- a/maintenance/findHooks.php
+++ b/maintenance/findHooks.php
@@ -42,6 +42,11 @@ require_once __DIR__ . '/Maintenance.php';
* @ingroup Maintenance
*/
class FindHooks extends Maintenance {
+ /*
+ * Hooks that are ignored
+ */
+ protected static $ignore = array( 'testRunLegacyHooks' );
+
public function __construct() {
parent::__construct();
$this->mDescription = 'Find hooks that are undocumented, missing, or just plain wrong';
@@ -58,34 +63,53 @@ class FindHooks extends Maintenance {
$documented = $this->getHooksFromDoc( $IP . '/docs/hooks.txt' );
$potential = array();
$bad = array();
+
+ // TODO: Don't hardcode the list of directories
$pathinc = array(
$IP . '/',
$IP . '/includes/',
$IP . '/includes/actions/',
$IP . '/includes/api/',
$IP . '/includes/cache/',
+ $IP . '/includes/changes/',
+ $IP . '/includes/clientpool/',
$IP . '/includes/content/',
$IP . '/includes/context/',
+ $IP . '/includes/dao/',
$IP . '/includes/db/',
+ $IP . '/includes/debug/',
+ $IP . '/includes/deferred/',
$IP . '/includes/diff/',
+ $IP . '/includes/externalstore/',
+ $IP . '/includes/filebackend/',
$IP . '/includes/filerepo/',
$IP . '/includes/filerepo/file/',
+ $IP . '/includes/gallery/',
+ $IP . '/includes/htmlform/',
$IP . '/includes/installer/',
$IP . '/includes/interwiki/',
+ $IP . '/includes/jobqueue/',
+ $IP . '/includes/json/',
$IP . '/includes/logging/',
$IP . '/includes/media/',
+ $IP . '/includes/page/',
$IP . '/includes/parser/',
+ $IP . '/includes/rcfeed/',
$IP . '/includes/resourceloader/',
$IP . '/includes/revisiondelete/',
$IP . '/includes/search/',
+ $IP . '/includes/site/',
+ $IP . '/includes/skins/',
+ $IP . '/includes/specialpage/',
$IP . '/includes/specials/',
$IP . '/includes/upload/',
+ $IP . '/includes/utils/',
$IP . '/languages/',
$IP . '/maintenance/',
+ $IP . '/maintenance/language/',
$IP . '/tests/',
$IP . '/tests/parser/',
$IP . '/tests/phpunit/suites/',
- $IP . '/skins/',
);
foreach ( $pathinc as $dir ) {
@@ -103,15 +127,15 @@ class FindHooks extends Maintenance {
$this->printArray( 'Documented and not found', $deprecated );
$this->printArray( 'Unclear hook calls', $bad );
- if ( count( $todo ) == 0 && count( $deprecated ) == 0 && count( $bad ) == 0 )
- {
+ if ( count( $todo ) == 0 && count( $deprecated ) == 0 && count( $bad ) == 0 ) {
$this->output( "Looks good!\n" );
}
}
/**
* Get the hook documentation, either locally or from MediaWiki.org
- * @return array of documented hooks
+ * @param string $doc
+ * @return array Array of documented hooks
*/
private function getHooksFromDoc( $doc ) {
if ( $this->hasOption( 'online' ) ) {
@@ -123,62 +147,75 @@ class FindHooks extends Maintenance {
/**
* Get hooks from a local file (for example docs/hooks.txt)
- * @param $doc string: filename to look in
- * @return array of documented hooks
+ * @param string $doc Filename to look in
+ * @return array Array of documented hooks
*/
private function getHooksFromLocalDoc( $doc ) {
- $m = array();
- $content = file_get_contents( $doc );
- preg_match_all( "/\n'(.*?)'/", $content, $m );
- return array_unique( $m[1] );
+ $m = array();
+ $content = file_get_contents( $doc );
+ preg_match_all( "/\n'(.*?)':/", $content, $m );
+
+ return array_unique( $m[1] );
}
/**
* Get hooks from www.mediawiki.org using the API
- * @return array of documented hooks
+ * @return array Array of documented hooks
*/
private function getHooksFromOnlineDoc() {
- // All hooks
- $allhookdata = Http::get( 'http://www.mediawiki.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:MediaWiki_hooks&cmlimit=500&format=php' );
- $allhookdata = unserialize( $allhookdata );
- $allhooks = array();
- foreach ( $allhookdata['query']['categorymembers'] as $page ) {
- $found = preg_match( '/Manual\:Hooks\/([a-zA-Z0-9- :]+)/', $page['title'], $matches );
- if ( $found ) {
- $hook = str_replace( ' ', '_', $matches[1] );
- $allhooks[] = $hook;
- }
+ // All hooks
+ $allhookdata = Http::get(
+ 'http://www.mediawiki.org/w/api.php?action=query&list=categorymembers&'
+ . 'cmtitle=Category:MediaWiki_hooks&cmlimit=500&format=php'
+ );
+ $allhookdata = unserialize( $allhookdata );
+ $allhooks = array();
+ foreach ( $allhookdata['query']['categorymembers'] as $page ) {
+ $found = preg_match( '/Manual\:Hooks\/([a-zA-Z0-9- :]+)/', $page['title'], $matches );
+ if ( $found ) {
+ $hook = str_replace( ' ', '_', $matches[1] );
+ $allhooks[] = $hook;
}
- // Removed hooks
- $oldhookdata = Http::get( 'http://www.mediawiki.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Removed_hooks&cmlimit=500&format=php' );
- $oldhookdata = unserialize( $oldhookdata );
- $removed = array();
- foreach ( $oldhookdata['query']['categorymembers'] as $page ) {
- $found = preg_match( '/Manual\:Hooks\/([a-zA-Z0-9- :]+)/', $page['title'], $matches );
- if ( $found ) {
- $hook = str_replace( ' ', '_', $matches[1] );
- $removed[] = $hook;
- }
+ }
+ // Removed hooks
+ $oldhookdata = Http::get(
+ 'http://www.mediawiki.org/w/api.php?action=query&list=categorymembers&'
+ . 'cmtitle=Category:Removed_hooks&cmlimit=500&format=php'
+ );
+ $oldhookdata = unserialize( $oldhookdata );
+ $removed = array();
+ foreach ( $oldhookdata['query']['categorymembers'] as $page ) {
+ $found = preg_match( '/Manual\:Hooks\/([a-zA-Z0-9- :]+)/', $page['title'], $matches );
+ if ( $found ) {
+ $hook = str_replace( ' ', '_', $matches[1] );
+ $removed[] = $hook;
}
- return array_diff( $allhooks, $removed );
+ }
+
+ return array_diff( $allhooks, $removed );
}
/**
* Get hooks from a PHP file
- * @param $file string Full filename to the PHP file.
- * @return array of hooks found.
+ * @param string $file Full filename to the PHP file.
+ * @return array Array of hooks found
*/
private function getHooksFromFile( $file ) {
$content = file_get_contents( $file );
$m = array();
- preg_match_all( '/(?:wfRunHooks|Hooks\:\:run|ContentHandler\:\:runLegacyHooks)\(\s*([\'"])(.*?)\1/', $content, $m );
+ preg_match_all(
+ '/(?:wfRunHooks|Hooks\:\:run|ContentHandler\:\:runLegacyHooks)\(\s*([\'"])(.*?)\1/',
+ $content,
+ $m
+ );
+
return $m[2];
}
/**
* Get hooks from the source code.
- * @param $path Directory where the include files can be found
- * @return array of hooks found.
+ * @param string $path Directory where the include files can be found
+ * @return array Array of hooks found
*/
private function getHooksFromPath( $path ) {
$hooks = array();
@@ -191,13 +228,14 @@ class FindHooks extends Maintenance {
}
closedir( $dh );
}
+
return $hooks;
}
/**
* Get bad hooks (where the hook name could not be determined) from a PHP file
- * @param $file string Full filename to the PHP file.
- * @return array of bad wfRunHooks() lines
+ * @param string $file Full filename to the PHP file.
+ * @return array Array of bad wfRunHooks() lines
*/
private function getBadHooksFromFile( $file ) {
$content = file_get_contents( $file );
@@ -208,13 +246,14 @@ class FindHooks extends Maintenance {
foreach ( $m[0] as $match ) {
$list[] = $match . "(" . $file . ")";
}
+
return $list;
}
/**
* Get bad hooks from the source code.
- * @param $path Directory where the include files can be found
- * @return array of bad wfRunHooks() lines
+ * @param string $path Directory where the include files can be found
+ * @return array Array of bad wfRunHooks() lines
*/
private function getBadHooksFromPath( $path ) {
$hooks = array();
@@ -228,21 +267,25 @@ class FindHooks extends Maintenance {
}
closedir( $dh );
}
+
return $hooks;
}
/**
* Nicely output the array
- * @param $msg String: a message to show before the value
- * @param $arr Array: an array
- * @param $sort Boolean: whether to sort the array (Default: true)
+ * @param string $msg A message to show before the value
+ * @param array $arr
+ * @param bool $sort Whether to sort the array (Default: true)
*/
private function printArray( $msg, $arr, $sort = true ) {
if ( $sort ) {
asort( $arr );
}
+
foreach ( $arr as $v ) {
- $this->output( "$msg: $v\n" );
+ if ( !in_array( $v, self::$ignore ) ) {
+ $this->output( "$msg: $v\n" );
+ }
}
}
}
diff --git a/maintenance/findMissingFiles.php b/maintenance/findMissingFiles.php
new file mode 100644
index 00000000..5f9f643a
--- /dev/null
+++ b/maintenance/findMissingFiles.php
@@ -0,0 +1,115 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Aaron Schulz
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+class FindMissingFiles extends Maintenance {
+ function __construct() {
+ parent::__construct();
+
+ $this->mDescription = 'Find registered files with no corresponding file.';
+ $this->addOption( 'start', 'Starting file name', false, true );
+ $this->addOption( 'mtimeafter', 'Only include files changed since this time', false, true );
+ $this->addOption( 'mtimebefore', 'Only includes files changed before this time', false, true );
+ $this->setBatchSize( 300 );
+ }
+
+ function execute() {
+ $lastName = $this->getOption( 'start', '' );
+
+ $repo = RepoGroup::singleton()->getLocalRepo();
+ $dbr = $repo->getSlaveDB();
+ $be = $repo->getBackend();
+
+ $mtime1 = $dbr->timestampOrNull( $this->getOption( 'mtimeafter', null ) );
+ $mtime2 = $dbr->timestampOrNull( $this->getOption( 'mtimebefore', null ) );
+
+ $joinTables = array( 'image' );
+ $joinConds = array( 'image' => array( 'INNER JOIN', 'img_name = page_title' ) );
+ if ( $mtime1 || $mtime2 ) {
+ $joinTables[] = 'logging';
+ $on = array( 'log_page = page_id', 'log_type' => array( 'upload', 'move', 'delete' ) );
+ if ( $mtime1 ) {
+ $on[] = "log_timestamp > {$dbr->addQuotes($mtime1)}";
+ }
+ if ( $mtime2 ) {
+ $on[] = "log_timestamp < {$dbr->addQuotes($mtime2)}";
+ }
+ $joinConds['logging'] = array( 'INNER JOIN', $on );
+ }
+
+ do {
+ $res = $dbr->select(
+ array_merge( array( 'page' ), $joinTables ),
+ array( 'img_name' => 'DISTINCT(page_title)' ),
+ array( 'page_namespace' => NS_FILE,
+ "page_title >= " . $dbr->addQuotes( $lastName ) ),
+ __METHOD__,
+ array( 'ORDER BY' => 'page_title', 'LIMIT' => $this->mBatchSize ),
+ $joinConds
+ );
+
+ // Check if any of these files are missing...
+ $pathsByName = array();
+ foreach ( $res as $row ) {
+ $file = $repo->newFile( $row->img_name );
+ $pathsByName[$row->img_name] = $file->getPath();
+ $lastName = $row->img_name;
+ }
+ $be->preloadFileStat( array( 'srcs' => $pathsByName ) );
+ foreach ( $pathsByName as $path ) {
+ if ( $be->fileExists( array( 'src' => $path ) ) === false ) {
+ $this->output( "$path\n" );
+ }
+ }
+
+ // Find all missing old versions of any of the files in this batch...
+ if ( count( $pathsByName ) ) {
+ $ores = $dbr->select( 'oldimage',
+ array( 'oi_name', 'oi_archive_name' ),
+ array( 'oi_name' => array_keys( $pathsByName ) ),
+ __METHOD__
+ );
+
+ $checkPaths = array();
+ foreach ( $ores as $row ) {
+ if ( !strlen( $row->oi_archive_name ) ) {
+ continue; // broken row
+ }
+ $file = $repo->newFromArchiveName( $row->oi_name, $row->oi_archive_name );
+ $checkPaths[] = $file->getPath();
+ }
+
+ foreach ( array_chunk( $checkPaths, $this->mBatchSize ) as $paths ) {
+ $be->preloadFileStat( array( 'srcs' => $paths ) );
+ foreach ( $paths as $path ) {
+ if ( $be->fileExists( array( 'src' => $path ) ) === false ) {
+ $this->output( "$path\n" );
+ }
+ }
+ }
+ }
+ } while ( $res->numRows() >= $this->mBatchSize );
+ }
+}
+
+$maintClass = 'FindMissingFiles';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/fixDoubleRedirects.php b/maintenance/fixDoubleRedirects.php
index 523be7ef..95682847 100644
--- a/maintenance/fixDoubleRedirects.php
+++ b/maintenance/fixDoubleRedirects.php
@@ -3,7 +3,7 @@
* Fix double redirects.
*
* Copyright © 2011 Ilmari Karonen <nospam@vyznev.net>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -44,13 +44,14 @@ class FixDoubleRedirects extends Maintenance {
public function execute() {
$async = $this->getOption( 'async', false );
$dryrun = $this->getOption( 'dry-run', false );
- $title = $this->getOption( 'title' );
- if ( isset( $title ) ) {
- $title = Title::newFromText( $title );
+ if ( $this->hasOption( 'title' ) ) {
+ $title = Title::newFromText( $this->getOption( 'title' ) );
if ( !$title || !$title->isRedirect() ) {
$this->error( $title->getPrefixedText() . " is not a redirect!\n", true );
}
+ } else {
+ $title = null;
}
$dbr = wfGetDB( DB_SLAVE );
@@ -71,11 +72,11 @@ class FixDoubleRedirects extends Maintenance {
'rd_from = pa.page_id',
'rd_namespace = pb.page_namespace',
'rd_title = pb.page_title',
- '(rd_interwiki IS NULL OR rd_interwiki = "")', // bug 40352
+ 'rd_interwiki IS NULL OR rd_interwiki = ' . $dbr->addQuotes( '' ), // bug 40352
'pb.page_is_redirect' => 1,
);
- if ( isset( $title ) ) {
+ if ( $title != null ) {
$conds['pb.page_namespace'] = $title->getNamespace();
$conds['pb.page_title'] = $title->getDBkey();
}
@@ -85,6 +86,7 @@ class FixDoubleRedirects extends Maintenance {
if ( !$res->numRows() ) {
$this->output( "No double redirects found.\n" );
+
return;
}
@@ -105,7 +107,8 @@ class FixDoubleRedirects extends Maintenance {
if ( !$async ) {
$success = ( $dryrun ? true : $job->run() );
if ( !$success ) {
- $this->error( "Error fixing " . $titleA->getPrefixedText() . ": " . $job->getLastError() . "\n" );
+ $this->error( "Error fixing " . $titleA->getPrefixedText()
+ . ": " . $job->getLastError() . "\n" );
}
} else {
$jobs[] = $job;
diff --git a/maintenance/fixExtLinksProtocolRelative.php b/maintenance/fixExtLinksProtocolRelative.php
index 02d65ed1..0c60e62c 100644
--- a/maintenance/fixExtLinksProtocolRelative.php
+++ b/maintenance/fixExtLinksProtocolRelative.php
@@ -34,7 +34,8 @@ require_once __DIR__ . '/Maintenance.php';
class FixExtLinksProtocolRelative extends LoggedUpdateMaintenance {
public function __construct() {
parent::__construct();
- $this->mDescription = "Fixes any entries in the externallinks table containing protocol-relative URLs";
+ $this->mDescription =
+ "Fixes any entries in the externallinks table containing protocol-relative URLs";
}
protected function getUpdateKey() {
@@ -49,6 +50,7 @@ class FixExtLinksProtocolRelative extends LoggedUpdateMaintenance {
$db = wfGetDB( DB_MASTER );
if ( !$db->tableExists( 'externallinks' ) ) {
$this->error( "externallinks table does not exist" );
+
return false;
}
$this->output( "Fixing protocol-relative entries in the externallinks table...\n" );
@@ -79,9 +81,18 @@ class FixExtLinksProtocolRelative extends LoggedUpdateMaintenance {
)
), __METHOD__, array( 'IGNORE' )
);
- $db->delete( 'externallinks', array( 'el_index' => $row->el_index, 'el_from' => $row->el_from, 'el_to' => $row->el_to ), __METHOD__ );
+ $db->delete(
+ 'externallinks',
+ array(
+ 'el_index' => $row->el_index,
+ 'el_from' => $row->el_from,
+ 'el_to' => $row->el_to
+ ),
+ __METHOD__
+ );
}
$this->output( "Done, $count rows updated.\n" );
+
return true;
}
}
diff --git a/maintenance/fixSlaveDesync.php b/maintenance/fixSlaveDesync.php
index e4e557fe..a5418ced 100644
--- a/maintenance/fixSlaveDesync.php
+++ b/maintenance/fixSlaveDesync.php
@@ -30,6 +30,9 @@ require_once __DIR__ . '/Maintenance.php';
* @ingroup Maintenance
*/
class FixSlaveDesync extends Maintenance {
+ /** @var array */
+ private $slaveIndexes;
+
public function __construct() {
parent::__construct();
$this->mDescription = "";
@@ -41,7 +44,8 @@ class FixSlaveDesync extends Maintenance {
public function execute() {
$this->slaveIndexes = array();
- for ( $i = 1; $i < wfGetLB()->getServerCount(); $i++ ) {
+ $serverCount = wfGetLB()->getServerCount();
+ for ( $i = 1; $i < $serverCount; $i++ ) {
if ( wfGetLB()->isNonZeroLoad( $i ) ) {
$this->slaveIndexes[] = $i;
}
@@ -66,7 +70,12 @@ class FixSlaveDesync extends Maintenance {
$n = 0;
$dbw = wfGetDB( DB_MASTER );
$masterIDs = array();
- $res = $dbw->select( 'page', array( 'page_id', 'page_latest' ), array( 'page_id<6054123' ), __METHOD__ );
+ $res = $dbw->select(
+ 'page',
+ array( 'page_id', 'page_latest' ),
+ array( 'page_id<6054123' ),
+ __METHOD__
+ );
$this->output( "Number of pages: " . $res->numRows() . "\n" );
foreach ( $res as $row ) {
$masterIDs[$row->page_id] = $row->page_latest;
@@ -78,7 +87,12 @@ class FixSlaveDesync extends Maintenance {
foreach ( $this->slaveIndexes as $i ) {
$db = wfGetDB( $i );
- $res = $db->select( 'page', array( 'page_id', 'page_latest' ), array( 'page_id<6054123' ), __METHOD__ );
+ $res = $db->select(
+ 'page',
+ array( 'page_id', 'page_latest' ),
+ array( 'page_id<6054123' ),
+ __METHOD__
+ );
foreach ( $res as $row ) {
if ( isset( $masterIDs[$row->page_id] ) && $masterIDs[$row->page_id] != $row->page_latest ) {
$desync[$row->page_id] = true;
@@ -87,12 +101,13 @@ class FixSlaveDesync extends Maintenance {
}
}
$this->output( "\n" );
+
return $desync;
}
/**
* Fix a broken page entry
- * @param $pageID int The page_id to fix
+ * @param int $pageID The page_id to fix
*/
private function desyncFixPage( $pageID ) {
# Check for a corrupted page_latest
@@ -122,6 +137,7 @@ class FixSlaveDesync extends Maintenance {
if ( !$found ) {
$this->output( "page_id $pageID seems fine\n" );
$dbw->commit( __METHOD__ );
+
return;
}
@@ -141,7 +157,8 @@ class FixSlaveDesync extends Maintenance {
if ( count( $masterIDs ) < count( $slaveIDs ) ) {
$missingIDs = array_diff( $slaveIDs, $masterIDs );
if ( count( $missingIDs ) ) {
- $this->output( "Found " . count( $missingIDs ) . " lost in master, copying from slave... " );
+ $this->output( "Found " . count( $missingIDs )
+ . " lost in master, copying from slave... " );
$dbFrom = $dbw;
$found = true;
$toMaster = true;
@@ -151,7 +168,8 @@ class FixSlaveDesync extends Maintenance {
} else {
$missingIDs = array_diff( $masterIDs, $slaveIDs );
if ( count( $missingIDs ) ) {
- $this->output( "Found " . count( $missingIDs ) . " missing revision(s), copying from master... " );
+ $this->output( "Found " . count( $missingIDs )
+ . " missing revision(s), copying from master... " );
$dbFrom = $dbw;
$found = true;
$toMaster = false;
@@ -199,11 +217,23 @@ class FixSlaveDesync extends Maintenance {
if ( $found ) {
$this->output( "Fixing page_latest... " );
if ( $toMaster ) {
- # $dbw->update( 'page', array( 'page_latest' => $realLatest ), array( 'page_id' => $pageID ), __METHOD__ );
+ /*
+ $dbw->update(
+ 'page',
+ array( 'page_latest' => $realLatest ),
+ array( 'page_id' => $pageID ),
+ __METHOD__
+ );
+ */
} else {
foreach ( $this->slaveIndexes as $i ) {
$db = wfGetDB( $i );
- $db->update( 'page', array( 'page_latest' => $realLatest ), array( 'page_id' => $pageID ), __METHOD__ );
+ $db->update(
+ 'page',
+ array( 'page_latest' => $realLatest ),
+ array( 'page_id' => $pageID ),
+ __METHOD__
+ );
}
}
$this->output( "done\n" );
diff --git a/maintenance/fixTimestamps.php b/maintenance/fixTimestamps.php
index b0609d17..5431cf2c 100644
--- a/maintenance/fixTimestamps.php
+++ b/maintenance/fixTimestamps.php
@@ -85,11 +85,11 @@ class FixTimestamps extends Maintenance {
if ( $sign == 0 || $sign == $expectedSign ) {
// Monotonic change
$lastNormal = $timestamp;
- ++ $numGoodRevs;
+ ++$numGoodRevs;
continue;
} elseif ( abs( $delta ) <= $grace ) {
// Non-monotonic change within grace interval
- ++ $numGoodRevs;
+ ++$numGoodRevs;
continue;
} else {
// Non-monotonic change larger than grace interval
@@ -100,7 +100,7 @@ class FixTimestamps extends Maintenance {
$numBadRevs = count( $badRevs );
if ( $numBadRevs > $numGoodRevs ) {
$this->error(
- "The majority of revisions in the search interval are marked as bad.
+ "The majority of revisions in the search interval are marked as bad.
Are you sure the offset ($offset) has the right sign? Positive means the clock
was incorrectly set forward, negative means the clock was incorrectly set back.
@@ -117,7 +117,8 @@ class FixTimestamps extends Maintenance {
$fixup = -$offset;
$sql = "UPDATE $revisionTable " .
- "SET rev_timestamp=DATE_FORMAT(DATE_ADD(rev_timestamp, INTERVAL $fixup SECOND), '%Y%m%d%H%i%s') " .
+ "SET rev_timestamp="
+ . "DATE_FORMAT(DATE_ADD(rev_timestamp, INTERVAL $fixup SECOND), '%Y%m%d%H%i%s') " .
"WHERE rev_id IN (" . $dbw->makeList( $badRevs ) . ')';
$dbw->query( $sql, __METHOD__ );
$this->output( "Done\n" );
diff --git a/maintenance/fixUserRegistration.php b/maintenance/fixUserRegistration.php
index 097936c9..878593c7 100644
--- a/maintenance/fixUserRegistration.php
+++ b/maintenance/fixUserRegistration.php
@@ -44,10 +44,20 @@ class FixUserRegistration extends Maintenance {
foreach ( $res as $row ) {
$id = $row->user_id;
// Get first edit time
- $timestamp = $dbr->selectField( 'revision', 'MIN(rev_timestamp)', array( 'rev_user' => $id ), __METHOD__ );
+ $timestamp = $dbr->selectField(
+ 'revision',
+ 'MIN(rev_timestamp)',
+ array( 'rev_user' => $id ),
+ __METHOD__
+ );
// Update
if ( !empty( $timestamp ) ) {
- $dbw->update( 'user', array( 'user_registration' => $timestamp ), array( 'user_id' => $id ), __METHOD__ );
+ $dbw->update(
+ 'user',
+ array( 'user_registration' => $timestamp ),
+ array( 'user_id' => $id ),
+ __METHOD__
+ );
$this->output( "$id $timestamp\n" );
} else {
$this->output( "$id NULL\n" );
diff --git a/maintenance/fuzz-tester.php b/maintenance/fuzz-tester.php
deleted file mode 100644
index 548bb2f2..00000000
--- a/maintenance/fuzz-tester.php
+++ /dev/null
@@ -1,2692 +0,0 @@
-<?php
-/**
- * Performs fuzz-style testing of MediaWiki's parser and forms.
- *
- * Copyright © 2006 Nick Jenkins
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- * @author Nick Jenkins ( http://nickj.org/ ).
-
-
-Started: 18 May 2006.
-
-Description:
- Performs fuzz-style testing of MediaWiki's parser and forms.
-
-How:
- - Generate lots of nasty wiki text.
- - Ask the Parser to render that wiki text to HTML, or ask MediaWiki's forms
- to deal with that wiki text.
- - Check MediaWiki's output for problems.
- - Repeat.
-
-Why:
- - To help find bugs.
- - To help find security issues, or potential security issues.
-
-What type of problems are being checked for:
- - Unclosed tags.
- - Errors or interesting warnings from Tidy.
- - PHP errors / warnings / notices.
- - MediaWiki internal errors.
- - Very slow responses.
- - No response from apache.
- - Optionally checking for malformed HTML using the W3C validator.
-
-Background:
- Many of the wikiFuzz class methods are a modified PHP port,
- of a "shameless" Python port, of LCAMTUF'S MANGELME:
- - http://www.securiteam.com/tools/6Z00N1PBFK.html
- - http://www.securityfocus.com/archive/1/378632/2004-10-15/2004-10-21/0
-
-Video:
- There's an XviD video discussing this fuzz tester. You can get it from:
- http://files.nickj.org/MediaWiki/Fuzz-Testing-MediaWiki-xvid.avi
-
-Requirements:
- To run this, you will need:
- - Command-line PHP5, with PHP-curl enabled (not all installations have this
- enabled - try "apt-get install php5-curl" if you're on Debian to install).
- - the Tidy standalone executable. ("apt-get install tidy").
-
-Optional:
- - If you want to run the curl scripts, you'll need standalone curl installed
- ("apt-get install curl")
- - For viewing the W3C validator output on a command line, the "html2text"
- program may be useful ("apt-get install html2text")
-
-Saving tests and test results:
- Any of the fuzz tests which find problems are saved for later review.
- In order to help track down problems, tests are saved in a number of
- different formats. The default filename extensions and their meanings are:
- - ".test.php" : PHP script that reproduces just that one problem using PHP-Curl.
- - ".curl.sh" : Shell script that reproduces that problem using standalone curl.
- - ".data.bin" : The serialized PHP data so that this script can re-run the test.
- - ".info.txt" : A human-readable text file with details of the field contents.
-
-Wiki configuration for testing:
- You should make some additions to LocalSettings.php in order to catch the most
- errors. Note this configuration is for **TESTING PURPOSES ONLY**, and is IN NO
- WAY, SHAPE, OR FORM suitable for deployment on a hostile network. That said,
- personally I find these additions to be the most helpful for testing purposes:
-
- // --------- Start ---------
- // Everyone can do everything. Very useful for testing, yet useless for deployment.
- $wgGroupPermissions['*']['autoconfirmed'] = true;
- $wgGroupPermissions['*']['block'] = true;
- $wgGroupPermissions['*']['bot'] = true;
- $wgGroupPermissions['*']['delete'] = true;
- $wgGroupPermissions['*']['deletedhistory'] = true;
- $wgGroupPermissions['*']['deleterevision'] = true;
- $wgGroupPermissions['*']['editinterface'] = true;
- $wgGroupPermissions['*']['hiderevision'] = true;
- $wgGroupPermissions['*']['import'] = true;
- $wgGroupPermissions['*']['importupload'] = true;
- $wgGroupPermissions['*']['minoredit'] = true;
- $wgGroupPermissions['*']['move'] = true;
- $wgGroupPermissions['*']['patrol'] = true;
- $wgGroupPermissions['*']['protect'] = true;
- $wgGroupPermissions['*']['proxyunbannable'] = true;
- $wgGroupPermissions['*']['renameuser'] = true;
- $wgGroupPermissions['*']['reupload'] = true;
- $wgGroupPermissions['*']['reupload-shared'] = true;
- $wgGroupPermissions['*']['rollback'] = true;
- $wgGroupPermissions['*']['siteadmin'] = true;
- $wgGroupPermissions['*']['unwatchedpages'] = true;
- $wgGroupPermissions['*']['upload'] = true;
- $wgGroupPermissions['*']['userrights'] = true;
- $wgGroupPermissions['*']['renameuser'] = true;
- $wgGroupPermissions['*']['makebot'] = true;
- $wgGroupPermissions['*']['makesysop'] = true;
-
- // Enable weird and wonderful options:
- // Increase default error reporting level.
- error_reporting (E_ALL); // At a later date could be increased to E_ALL | E_STRICT
- $wgEnableUploads = true; // enable uploads.
- $wgDBerrorLog = "/root/mediawiki-db-error-log.txt"; // log DB errors, replace with suitable path.
- $wgShowSQLErrors = true; // Show SQL errors (instead of saying the query was hidden).
- $wgShowExceptionDetails = true; // want backtraces.
- $wgEnableAPI = true; // enable API.
- $wgEnableWriteAPI = true; // enable API.
-
- // Install & enable Parser Hook extensions to increase code coverage. E.g.:
- require_once "extensions/ParserFunctions/ParserFunctions.php";
- require_once "extensions/Cite/Cite.php";
- require_once "extensions/inputbox/inputbox.php";
- require_once "extensions/Sort/Sort.php";
- require_once "extensions/wikihiero/wikihiero.php";
- require_once "extensions/CharInsert/CharInsert.php";
- require_once "extensions/FixedImage/FixedImage.php";
-
- // Install & enable Special Page extensions to increase code coverage. E.g.:
- require_once "extensions/Cite/SpecialCite.php";
- require_once "extensions/Renameuser/SpecialRenameuser.php";
- // --------- End ---------
-
- If you want to try E_STRICT error logging, add this to the above:
- // --------- Start ---------
- error_reporting (E_ALL | E_STRICT);
- set_error_handler( 'error_handler' );
- function error_handler ($type, $message, $file=__FILE__, $line=__LINE__) {
- if ($message == "var: Deprecated. Please use the public/private/protected modifiers") return;
- print "<br />\n<b>Strict Standards:</b> Type: <b>$type</b>: $message in <b>$file</b> on line <b>$line</b><br />\n";
- }
- // --------- End ---------
-
- Also add/change this in LocalSettings.php:
- // --------- Start ---------
- $wgEnableProfileInfo = true;
- $wgDBserver = "localhost"; // replace with DB server hostname
- // --------- End ---------
-
-Usage:
- Run with "php fuzz-tester.php".
- To see the various command-line options, run "php fuzz-tester.php --help".
- To stop the script, press Ctrl-C.
-
-Console output:
- - If requested, first any previously failed tests will be rerun.
- - Then new tests will be generated and run. Any tests that fail will be saved,
- and a brief message about why they failed will be printed on the console.
- - The console will show the number of tests run, time run, number of tests
- failed, number of tests being done per minute, and the name of the current test.
-
-TODO:
- Some known things that could improve this script:
- - Logging in with cookie jar storage needed for some tests (as there are some
- pages that cannot be tested without being logged in, and which are currently
- untested - e.g. Special:Emailuser, Special:Preferences, adding to Watchist).
- - Testing of Timeline extension (I cannot test as ploticus has/had issues on
- my architecture).
-
-*/
-
-// ///////////////////////// COMMAND LINE HELP ////////////////////////////////////
-
-// This is a command line script, load MediaWiki env (gives command line options);
-require_once __DIR__ . '/commandLine.inc';
-
-// if the user asked for an explanation of command line options.
-if ( isset( $options["help"] ) ) {
- print <<<ENDS
-MediaWiki $wgVersion fuzz tester
-Usage: php {$_SERVER["SCRIPT_NAME"]} [--quiet] [--base-url=<url-to-test-wiki>]
- [--directory=<failed-test-path>] [--include-binary]
- [--w3c-validate] [--delete-passed-retests] [--help]
- [--user=<username>] [--password=<password>]
- [--rerun-failed-tests] [--max-errors=<int>]
- [--max-runtime=<num-minutes>]
- [--specific-test=<test-name>]
-
-Options:
- --quiet : Hides passed tests, shows only failed tests.
- --base-url : URL to a wiki on which to run the tests.
- The "http://" is optional and can be omitted.
- --directory : Full path to directory for storing failed tests.
- Will be created if it does not exist.
- --include-binary : Includes non-alphanumeric characters in the tests.
- --w3c-validate : Validates pages using the W3C's web validator.
- Slow. Currently many pages fail validation.
- --user : Login name of a valid user on your test wiki.
- --password : Password for the valid user on your test wiki.
- --delete-passed-retests : Will delete retests that now pass.
- Requires --rerun-failed-tests to be meaningful.
- --rerun-failed-tests : Whether to rerun any previously failed tests.
- --max-errors : Maximum number of errors to report before exiting.
- Does not include errors from --rerun-failed-tests
- --max-runtime : Maximum runtime, in minutes, to run before exiting.
- Only applies to new tests, not --rerun-failed-tests
- --specific-test : Runs only the specified fuzz test.
- Only applies to new tests, not --rerun-failed-tests
- --keep-passed-tests : Saves all test files, even those that pass.
- --help : Show this help message.
-
-Example:
- If you wanted to fuzz test a nightly MediaWiki checkout using cron for 1 hour,
- and only wanted to be informed of errors, and did not want to redo previously
- failed tests, and wanted a maximum of 100 errors, then you could do:
- php {$_SERVER["SCRIPT_NAME"]} --quiet --max-errors=100 --max-runtime=60
-
-
-ENDS;
-
- exit( 0 );
-}
-
-
-// if we got command line options, check they look valid.
-$validOptions = array ( "quiet", "base-url", "directory", "include-binary",
- "w3c-validate", "user", "password", "delete-passed-retests",
- "rerun-failed-tests", "max-errors",
- "max-runtime", "specific-test", "keep-passed-tests", "help" );
-if ( !empty( $options ) ) {
- $unknownArgs = array_diff ( array_keys( $options ), $validOptions );
- foreach ( $unknownArgs as $invalidArg ) {
- print "Ignoring invalid command-line option: --$invalidArg\n";
- }
-}
-
-
-// /////////////////////////// CONFIGURATION ////////////////////////////////////
-
-// URL to some wiki on which we can run our tests.
-if ( !empty( $options["base-url"] ) ) {
- define( "WIKI_BASE_URL", $options["base-url"] );
-} else {
- define( "WIKI_BASE_URL", $wgServer . $wgScriptPath . '/' );
-}
-
-// The directory name where we store the output.
-// Example for Windows: "c:\\temp\\wiki-fuzz"
-if ( !empty( $options["directory"] ) ) {
- define( "DIRECTORY", $options["directory"] );
-} else {
- define( "DIRECTORY", "{$wgUploadDirectory}/fuzz-tests" );
-}
-
-// Should our test fuzz data include binary strings?
-define( "INCLUDE_BINARY", isset( $options["include-binary"] ) );
-
-// Whether we want to validate HTML output on the web.
-// At the moment very few generated pages will validate, so not recommended.
-define( "VALIDATE_ON_WEB", isset( $options["w3c-validate"] ) );
-// URL to use to validate our output:
-define( "VALIDATOR_URL", "http://validator.w3.org/check" );
-
-// Location of Tidy standalone executable.
-define( "PATH_TO_TIDY", "/usr/bin/tidy" );
-
-// The name of a user who has edited on your wiki. Used
-// when testing the Special:Contributions and Special:Userlogin page.
-if ( !empty( $options["user"] ) ) {
- define( "USER_ON_WIKI", $options["user"] );
-} else {
- define( "USER_ON_WIKI", "nickj" );
-}
-
-// The password of the above user. Used when testing the login page,
-// and to do this we sometimes need to login successfully.
-if ( !empty( $options["password"] ) ) {
- define( "USER_PASSWORD", $options["password"] );
-} else {
- // And no, this is not a valid password on any public wiki.
- define( "USER_PASSWORD", "nickj" );
-}
-
-// If we have a test that failed, and then we run it again, and it passes,
-// do you want to delete it or keep it?
-define( "DELETE_PASSED_RETESTS", isset( $options["delete-passed-retests"] ) );
-
-// Do we want to rerun old saved tests at script startup?
-// Set to true to help catch regressions, or false if you only want new stuff.
-define( "RERUN_OLD_TESTS", isset( $options["rerun-failed-tests"] ) );
-
-// File where the database errors are logged. Should be defined in LocalSettings.php.
-define( "DB_ERROR_LOG_FILE", $wgDBerrorLog );
-
-// Run in chatty mode (all output, default), or run in quiet mode (only prints out details of failed tests)?
-define( "QUIET", isset( $options["quiet"] ) );
-
-// Keep all test files, even those that pass. Potentially useful to tracking input that causes something
-// unusual to happen, if you don't know what "unusual" is until later.
-define( "KEEP_PASSED_TESTS", isset( $options["keep-passed-tests"] ) );
-
-// The maximum runtime, if specified.
-if ( !empty( $options["max-runtime"] ) && intval( $options["max-runtime"] ) > 0 ) {
- define( "MAX_RUNTIME", intval( $options["max-runtime"] ) );
-}
-
-// The maximum number of problems to find, if specified. Excludes retest errors.
-if ( !empty( $options["max-errors"] ) && intval( $options["max-errors"] ) > 0 ) {
- define( "MAX_ERRORS", intval( $options["max-errors"] ) );
-}
-
-// if the user has requested a specific test (instead of all tests), and the test they asked for looks valid.
-if ( !empty( $options["specific-test"] ) ) {
- if ( class_exists( $options["specific-test"] ) && get_parent_class( $options["specific-test"] ) == "pageTest" ) {
- define( "SPECIFIC_TEST", $options["specific-test"] );
- }
- else {
- print "Ignoring invalid --specific-test\n";
- }
-}
-
-// Define the file extensions we'll use:
-define( "PHP_TEST" , ".test.php" );
-define( "CURL_TEST", ".curl.sh" );
-define( "DATA_FILE", ".data.bin" );
-define( "INFO_FILE", ".info.txt" );
-define( "HTML_FILE", ".wiki_preview.html" );
-
-// If it goes wrong, we want to know about it.
-error_reporting( E_ALL | E_STRICT );
-
-// ////////////// A CLASS THAT GENERATES RANDOM NASTY WIKI & HTML STRINGS //////////////////////
-
-class wikiFuzz {
-
- // Only some HTML tags are understood with params by MediaWiki, the rest are ignored.
- // List the tags that accept params below, as well as what those params are.
- public static $data = array(
- "B" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "CAPTION" => array( "CLASS", "ID", "STYLE", "align", "lang", "dir", "title" ),
- "CENTER" => array( "CLASS", "STYLE", "ID", "lang", "dir", "title" ),
- "DIV" => array( "CLASS", "STYLE", "ID", "align", "lang", "dir", "title" ),
- "FONT" => array( "CLASS", "STYLE", "ID", "lang", "dir", "title", "face", "size", "color" ),
- "H1" => array( "STYLE", "CLASS", "ID", "align", "lang", "dir", "title" ),
- "H2" => array( "STYLE", "CLASS", "ID", "align", "lang", "dir", "title" ),
- "HR" => array( "STYLE", "CLASS", "ID", "WIDTH", "lang", "dir", "title", "size", "noshade" ),
- "LI" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "value" ),
- "TABLE" => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "BORDER", "CELLPADDING",
- "CELLSPACING", "lang", "dir", "title", "summary", "frame", "rules" ),
- "TD" => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN",
- "VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang",
- "dir", "title", "char", "charoff" ),
- "TH" => array( "STYLE", "CLASS", "ID", "BGCOLOR", "WIDTH", "ALIGN", "COLSPAN", "ROWSPAN",
- "VALIGN", "abbr", "axis", "headers", "scope", "nowrap", "height", "lang",
- "dir", "title", "char", "charoff" ),
- "TR" => array( "CLASS", "STYLE", "ID", "BGCOLOR", "ALIGN", "VALIGN", "lang", "dir", "title", "char", "charoff" ),
- "UL" => array( "CLASS", "STYLE", "ID", "lang", "dir", "title", "type" ),
- "P" => array( "style", "class", "id", "align", "lang", "dir", "title" ),
- "blockquote" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "cite" ),
- "span" => array( "CLASS", "ID", "STYLE", "align", "lang", "dir", "title" ),
- "code" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "tt" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "small" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "big" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "s" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "u" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "del" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite" ),
- "ins" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "datetime", "cite" ),
- "sub" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "sup" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "ol" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "type", "start" ),
- "br" => array( "CLASS", "ID", "STYLE", "title", "clear" ),
- "cite" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "var" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "ruby" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "rt" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "rp" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "dt" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "dl" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "em" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "strong" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "i" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title" ),
- "thead" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign' ),
- "tfoot" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign' ),
- "tbody" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign' ),
- "colgroup" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign', 'span', 'width' ),
- "col" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", 'align', 'char', 'charoff', 'valign', 'span', 'width' ),
- "pre" => array( "CLASS", "ID", "STYLE", "lang", "dir", "title", "width" ),
-
- // extension tags that accept parameters:
- "sort" => array( "order", "class" ),
- "ref" => array( "name" ),
- "categorytree" => array( "hideroot", "mode", "style" ),
- "chemform" => array( "link", "wikilink", "query" ),
- "section" => array( "begin", "new" ),
-
- // older MW transclusion.
- "transclude" => array( "page" ),
- );
-
- // The types of the HTML that we will be testing were defined above
- // Note: this needs to be initialized later to be equal to: array_keys(wikiFuzz::$data);
- // as such, it also needs to also be publicly modifiable.
- public static $types;
-
-
- // Some attribute values.
- static private $other = array( "&", "=", ":", "?", "\"", "\n", "%n%n%n%n%n%n%n%n%n%n%n%n", "\\" );
- static private $ints = array(
- // various numbers
- "0", "-1", "127", "-7897", "89000", "808080", "90928345",
- "0xfffffff", "ffff",
-
- // Different ways of saying: '
- "&#0000039;", // Long UTF-8 Unicode encoding
- "&#39;", // dec version.
- "&#x27;", // hex version.
- "&#xA7;", // malformed hex variant, MSB not zero.
-
- // Different ways of saying: "
- "&#0000034;", // Long UTF-8 Unicode encoding
- "&#34;",
- "&#x22;", // hex version.
- "&#xA2;", // malformed hex variant, MSB not zero.
-
- // Different ways of saying: <
- "<",
- "&#0000060", // Long UTF-8 Unicode encoding without semicolon (Mediawiki wants the colon)
- "&#0000060;", // Long UTF-8 Unicode encoding with semicolon
- "&#60;",
- "&#x3C;", // hex version.
- "&#xBC;", // malformed hex variant, MSB not zero.
- "&#x0003C;", // mid-length hex version
- "&#X00003C;", // slightly longer hex version, with capital "X"
-
- // Different ways of saying: >
- ">",
- "&#0000062;", // Long UTF-8 Unicode encoding
- "&#62;",
- "&#x3E;", // hex version.
- "&#xBE;", // malformed variant, MSB not zero.
-
- // Different ways of saying: [
- "&#0000091;", // Long UTF-8 Unicode encoding
- "&#91;",
- "&#x5B;", // hex version.
-
- // Different ways of saying: {{
- "&#0000123;&#0000123;", // Long UTF-8 Unicode encoding
- "&#123;&#123;",
- "&#x7B;&#x7B;", // hex version.
-
- // Different ways of saying: |
- "&#0000124;", // Long UTF-8 Unicode encoding
- "&#124;",
- "&#x7C;", // hex version.
- "&#xFC;", // malformed hex variant, MSB not zero.
-
- // a "lignature" - http://www.robinlionheart.com/stds/html4/spchars#ligature
- // &#8204; == &zwnj;
- "&#8204;"
- );
-
- // Defines various wiki-related bits of syntax, that can potentially cause
- // MediaWiki to do something other than just print that literal text.
- static private $ext = array(
- // links, templates, parameters.
- "[[", "]]", "{{", "}}", "|", "[", "]", "{{{", "}}}", "|]]",
-
- // wiki tables.
- "\n{|", "\n|}",
- "!",
- "\n!",
- "!!",
- "||",
- "\n|-", "| ", "\n|",
-
- // section headings.
- "=", "==", "===", "====", "=====", "======",
-
- // lists (ordered and unordered) and indentation.
- "\n*", "*", "\n:", ":",
- "\n#", "#",
-
- // definition lists (dl, dt, dd), newline, and newline with pre, and a tab.
- "\n;", ";", "\n ",
-
- // Whitespace: newline, tab, space.
- "\n", "\t", " ",
-
- // Some XSS attack vectors from http://ha.ckers.org/xss.html
- "&#x09;", // tab
- "&#x0A;", // newline
- "&#x0D;", // carriage return
- "\0", // null character
- " &#14; ", // spaces and meta characters
- "'';!--\"<XSS>=&{()}", // compact injection of XSS & SQL tester
-
- // various NULL fields
- "%00",
- "&#00;",
- "\0",
-
- // horizontal rule.
- "-----", "\n-----",
-
- // signature, redirect, bold, italics.
- "~~~~", "#REDIRECT [[", "'''", "''",
-
- // comments.
- "<!--", "-->",
-
- // quotes.
- "\"", "'",
-
- // tag start and tag end.
- "<", ">",
-
- // implicit link creation on URIs.
- "http://",
- "https://",
- "ftp://",
- "irc://",
- "news:",
- 'gopher://',
- 'telnet://',
- 'nntp://',
- 'worldwind://',
- 'mailto:',
-
- // images.
- "[[image:",
- ".gif",
- ".png",
- ".jpg",
- ".jpeg",
- 'thumbnail=',
- 'thumbnail',
- 'thumb=',
- 'thumb',
- 'right',
- 'none',
- 'left',
- 'framed',
- 'frame',
- 'enframed',
- 'centre',
- 'center',
- "Image:",
- "[[:Image",
- 'px',
- 'upright=',
- 'border',
-
- // misc stuff to throw at the Parser.
- '%08X',
- '/',
- ":x{|",
- "\n|+",
- "<noinclude>",
- "</noinclude>",
- " \302\273",
- " :",
- " !",
- " ;",
- "\302\253",
- "[[category:",
- "?=",
- "(",
- ")",
- "]]]",
- "../",
- "{{{{",
- "}}}}",
- "[[Special:",
- "<includeonly>",
- "</includeonly>",
- "<!--MWTEMPLATESECTION=",
- '<!--MWTOC-->',
-
- // implicit link creation on booknum, RFC, and PubMed ID usage (both with and without IDs)
- "ISBN 2",
- "RFC 000",
- "PMID 000",
- "ISBN ",
- "RFC ",
- "PMID ",
-
- // magic words:
- '__NOTOC__',
- '__FORCETOC__',
- '__NOEDITSECTION__',
- '__START__',
- '__NOTITLECONVERT__',
- '__NOCONTENTCONVERT__',
- '__END__',
- '__TOC__',
- '__NOTC__',
- '__NOCC__',
- "__FORCETOC__",
- "__NEWSECTIONLINK__",
- "__NOGALLERY__",
-
- // more magic words / internal templates.
- '{{PAGENAME}}',
- '{{PAGENAMEE}}',
- '{{NAMESPACE}}',
- "{{MSG:",
- "}}",
- "{{MSGNW:",
- "}}",
- "{{INT:",
- "}}",
- '{{SITENAME}}',
- "{{NS:",
- "}}",
- "{{LOCALURL:",
- "}}",
- "{{LOCALURLE:",
- "}}",
- "{{SCRIPTPATH}}",
- "{{GRAMMAR:gentiv|",
- "}}",
- "{{REVISIONID}}",
- "{{SUBPAGENAME}}",
- "{{SUBPAGENAMEE}}",
- "{{ns:0}}",
- "{{fullurle:",
- "}}",
- "{{subst::",
- "}}",
- "{{UCFIRST:",
- "}}",
- "{{UC:",
- '{{SERVERNAME}}',
- '{{SERVER}}',
- "{{RAW:",
- "}}",
- "{{PLURAL:",
- "}}",
- "{{LCFIRST:",
- "}}",
- "{{LC:",
- "}}",
- '{{CURRENTWEEK}}',
- '{{CURRENTDOW}}',
- "{{INT:{{LC:contribs-showhideminor}}|",
- "}}",
- "{{INT:googlesearch|",
- "}}",
- "{{ROOTPAGENAME}}",
- "{{BASEPAGENAME}}",
- "{{CONTENTLANGUAGE}}",
- "{{PAGESINNAMESPACE:}}",
- "{{#language:",
- "}}",
- "{{#special:",
- "}}",
- "{{#special:emailuser",
- "}}",
-
- // Some raw link for magic words.
- "{{NUMBEROFPAGES:R",
- "}}",
- "{{NUMBEROFUSERS:R",
- "}}",
- "{{NUMBEROFARTICLES:R",
- "}}",
- "{{NUMBEROFFILES:R",
- "}}",
- "{{NUMBEROFADMINS:R",
- "}}",
- "{{padleft:",
- "}}",
- "{{padright:",
- "}}",
- "{{DEFAULTSORT:",
- "}}",
-
- // internal Math "extension":
- "<math>",
- "</math>",
-
- // Parser extension functions:
- "{{#expr:",
- "{{#if:",
- "{{#ifeq:",
- "{{#ifexist:",
- "{{#ifexpr:",
- "{{#switch:",
- "{{#time:",
- "}}",
-
- // references table for the Cite extension.
- "<references/>",
-
- // Internal Parser tokens - try inserting some of these.
- "UNIQ25f46b0524f13e67NOPARSE",
- "UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002",
- "\x07UNIQ17197916557e7cd6-HTMLCommentStrip46238afc3bb0cf5f00000002-QINU",
-
- // Inputbox extension:
- "<inputbox>\ntype=search\nsearchbuttonlabel=\n",
- "</inputbox>",
-
- // charInsert extension:
- "<charInsert>",
- "</charInsert>",
-
- // wikiHiero extension:
- "<hiero>",
- "</hiero>",
-
- // Image gallery:
- "<gallery>",
- "</gallery>",
-
- // FixedImage extension.
- "<fundraising/>",
-
- // Timeline extension: currently untested.
-
- // Nowiki:
- "<nOwIkI>",
- "</nowiki>",
-
- // an external image to test the external image displaying code
- "http://debian.org/Pics/debian.png",
-
- // LabeledSectionTransclusion extension.
- "{{#lstx:",
- "}}",
- "{{#lst:",
- "}}",
- "{{#lst:Main Page|",
- "}}"
- );
-
- /**
- ** Randomly returns one element of the input array.
- */
- public static function chooseInput( array $input ) {
- $randindex = wikiFuzz::randnum( count( $input ) - 1 );
- return $input[$randindex];
- }
-
- // Max number of parameters for HTML attributes.
- static private $maxparams = 10;
-
- /**
- * Returns random number between finish and start.
- * @param $finish
- * @param $start int
- * @return int
- */
- public static function randnum( $finish, $start = 0 ) {
- return mt_rand( $start, $finish );
- }
-
- /**
- * Returns a mix of random text and random wiki syntax.
- * @return string
- */
- private static function randstring() {
- $thestring = "";
-
- for ( $i = 0; $i < 40; $i++ ) {
- $what = wikiFuzz::randnum( 1 );
-
- if ( $what == 0 ) { // include some random wiki syntax
- $which = wikiFuzz::randnum( count( wikiFuzz::$ext ) - 1 );
- $thestring .= wikiFuzz::$ext[$which];
- }
- else { // include some random text
- $char = INCLUDE_BINARY
- // Decimal version:
- // "&#" . wikiFuzz::randnum(255) . ";"
- // Hex version:
- ? "&#x" . str_pad( dechex( wikiFuzz::randnum( 255 ) ), wikiFuzz::randnum( 2, 7 ), "0", STR_PAD_LEFT ) . ";"
- // A truly binary version:
- // ? chr(wikiFuzz::randnum(0,255))
- : chr( wikiFuzz::randnum( 126, 32 ) );
-
- $length = wikiFuzz::randnum( 8 );
- $thestring .= str_repeat ( $char, $length );
- }
- }
- return $thestring;
- }
-
- /**
- * Returns either random text, or random wiki syntax, or random data from "ints",
- * or random data from "other".
- * @return string
- */
- private static function makestring() {
- $what = wikiFuzz::randnum( 2 );
- if ( $what == 0 ) {
- return wikiFuzz::randstring();
- } elseif ( $what == 1 ) {
- return wikiFuzz::$ints[wikiFuzz::randnum( count( wikiFuzz::$ints ) - 1 )];
- } else {
- return wikiFuzz::$other[wikiFuzz::randnum( count( wikiFuzz::$other ) - 1 )];
- }
- }
-
- /**
- * Returns the matched character slash-escaped as in a C string
- * Helper for makeTitleSafe callback
- * @param $matches
- * @return string
- */
- private static function stringEscape( $matches ) {
- return sprintf( "\\x%02x", ord( $matches[1] ) );
- }
-
- /**
- ** Strips out the stuff that Mediawiki balks at in a page's title.
- ** Implementation copied/pasted from cleanupTable.inc & cleanupImages.php
- * @param $str string
- * @return string
- */
- public static function makeTitleSafe( $str ) {
- $legalTitleChars = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF";
- return preg_replace_callback(
- "/([^$legalTitleChars])/", 'wikiFuzz::stringEscape',
- $str );
- }
-
- /**
- ** Returns a string of fuzz text.
- * @return string
- */
- private static function loop() {
- switch ( wikiFuzz::randnum( 3 ) ) {
- case 1: // an opening tag, with parameters.
- $string = "";
- $i = wikiFuzz::randnum( count( wikiFuzz::$types ) - 1 );
- $t = wikiFuzz::$types[$i];
- $arr = wikiFuzz::$data[$t];
- $string .= "<" . $t . " ";
- $num_params = min( wikiFuzz::$maxparams, count( $arr ) );
- for ( $z = 0; $z < $num_params; $z++ ) {
- $badparam = $arr[wikiFuzz::randnum( count( $arr ) - 1 )];
- $badstring = wikiFuzz::makestring();
- $string .= $badparam . "=" . wikiFuzz::getRandQuote() . $badstring . wikiFuzz::getRandQuote() . " ";
- }
- $string .= ">\n";
- return $string;
- case 2: // a closing tag.
- $i = wikiFuzz::randnum( count( wikiFuzz::$types ) - 1 );
- return "</" . wikiFuzz::$types[$i] . ">";
- case 3: // a random string, between tags.
- return wikiFuzz::makeString();
- }
- return ""; // catch-all, should never be called.
- }
-
- /**
- * Returns one of the three styles of random quote: ', ", and nothing.
- * @return string
- */
- private static function getRandQuote() {
- switch ( wikiFuzz::randnum( 3 ) ) {
- case 1 : return "'";
- case 2 : return "\"";
- default: return "";
- }
- }
-
- /**
- ** Returns fuzz text, with the parameter indicating approximately how many lines of text you want.
- * @param $maxtypes int
- * @return string
- */
- public static function makeFuzz( $maxtypes = 2 ) {
- $page = "";
- for ( $k = 0; $k < $maxtypes; $k++ ) {
- $page .= wikiFuzz::loop();
- }
- return $page;
- }
-}
-
-
-// ////// MEDIAWIKI PAGES TO TEST, AND HOW TO TEST THEM ///////
-
-/**
- ** A page test has just these things:
- ** 1) Form parameters.
- ** 2) the URL we are going to test those parameters on.
- ** 3) Any cookies required for the test.
- ** 4) Whether Tidy should validate the page. Defaults to true, but can be turned off.
- ** Declared abstract because it should be extended by a class
- ** that supplies these parameters.
- */
-abstract class pageTest {
- protected $params;
- protected $pagePath;
- protected $cookie = "";
- protected $tidyValidate = true;
-
- public function getParams() {
- return $this->params;
- }
-
- public function getPagePath() {
- return $this->pagePath;
- }
-
- public function getCookie() {
- return $this->cookie;
- }
-
- public function tidyValidate() {
- return $this->tidyValidate;
- }
-}
-
-
-/**
- ** a page test for the "Edit" page. Tests Parser.php and Sanitizer.php.
- */
-class editPageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=WIKIFUZZ";
-
- $this->params = array (
- "action" => "submit",
- "wpMinoredit" => wikiFuzz::makeFuzz( 2 ),
- "wpPreview" => wikiFuzz::makeFuzz( 2 ),
- "wpSection" => wikiFuzz::makeFuzz( 2 ),
- "wpEdittime" => wikiFuzz::makeFuzz( 2 ),
- "wpSummary" => wikiFuzz::makeFuzz( 2 ),
- "wpScrolltop" => wikiFuzz::makeFuzz( 2 ),
- "wpStarttime" => wikiFuzz::makeFuzz( 2 ),
- "wpAutoSummary" => wikiFuzz::makeFuzz( 2 ),
- "wpTextbox1" => wikiFuzz::makeFuzz( 40 ) // the main wiki text, need lots of this.
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpSection"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpEdittime"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpSummary"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpScrolltop"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpStarttime"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpAutoSummary"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpTextbox1"] );
- }
-}
-
-
-/**
- ** a page test for "Special:Listusers".
- */
-class listusersTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Listusers";
-
- $this->params = array (
- "title" => wikiFuzz::makeFuzz( 2 ),
- "group" => wikiFuzz::makeFuzz( 2 ),
- "username" => wikiFuzz::makeFuzz( 2 ),
- "Go" => wikiFuzz::makeFuzz( 2 ),
- "limit" => wikiFuzz::chooseInput( array( "0", "-1", "---'----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- "offset" => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz::makeFuzz( 2 ) ) )
- );
- }
-}
-
-
-/**
- ** a page test for "Special:Search".
- */
-class searchTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Search";
-
- $this->params = array (
- "action" => "index.php?title=Special:Search",
- "ns0" => wikiFuzz::makeFuzz( 2 ),
- "ns1" => wikiFuzz::makeFuzz( 2 ),
- "ns2" => wikiFuzz::makeFuzz( 2 ),
- "ns3" => wikiFuzz::makeFuzz( 2 ),
- "ns4" => wikiFuzz::makeFuzz( 2 ),
- "ns5" => wikiFuzz::makeFuzz( 2 ),
- "ns6" => wikiFuzz::makeFuzz( 2 ),
- "ns7" => wikiFuzz::makeFuzz( 2 ),
- "ns8" => wikiFuzz::makeFuzz( 2 ),
- "ns9" => wikiFuzz::makeFuzz( 2 ),
- "ns10" => wikiFuzz::makeFuzz( 2 ),
- "ns11" => wikiFuzz::makeFuzz( 2 ),
- "ns12" => wikiFuzz::makeFuzz( 2 ),
- "ns13" => wikiFuzz::makeFuzz( 2 ),
- "ns14" => wikiFuzz::makeFuzz( 2 ),
- "ns15" => wikiFuzz::makeFuzz( 2 ),
- "redirs" => wikiFuzz::makeFuzz( 2 ),
- "search" => wikiFuzz::makeFuzz( 2 ),
- "offset" => wikiFuzz::chooseInput( array( "", "0", "-1", "--------'-----0", "+1", "81343242346234234", wikiFuzz::makeFuzz( 2 ) ) ),
- "fulltext" => wikiFuzz::chooseInput( array( "", "0", "1", "--------'-----0", "+1", wikiFuzz::makeFuzz( 2 ) ) ),
- "searchx" => wikiFuzz::chooseInput( array( "", "0", "1", "--------'-----0", "+1", wikiFuzz::makeFuzz( 2 ) ) )
- );
- }
-}
-
-
-/**
- ** a page test for "Special:Recentchanges".
- */
-class recentchangesTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Recentchanges";
-
- $this->params = array (
- "action" => wikiFuzz::makeFuzz( 2 ),
- "title" => wikiFuzz::makeFuzz( 2 ),
- "namespace" => wikiFuzz::chooseInput( range( -1, 15 ) ),
- "Go" => wikiFuzz::makeFuzz( 2 ),
- "invert" => wikiFuzz::chooseInput( array( "-1", "---'----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- "hideanons" => wikiFuzz::chooseInput( array( "-1", "------'-------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- 'limit' => wikiFuzz::chooseInput( array( "0", "-1", "---------'----0", "+1", "81340909772349234", wikiFuzz::makeFuzz( 2 ) ) ),
- "days" => wikiFuzz::chooseInput( array( "-1", "----------'---0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- "hideminor" => wikiFuzz::chooseInput( array( "-1", "-----------'--0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- "hidebots" => wikiFuzz::chooseInput( array( "-1", "---------'----0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- "hideliu" => wikiFuzz::chooseInput( array( "-1", "-------'------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- "hidepatrolled" => wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- "hidemyself" => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- 'categories_any' => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- 'categories' => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- 'feed' => wikiFuzz::chooseInput( array( "-1", "--'-----------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) )
- );
- }
-}
-
-
-/**
- ** a page test for "Special:Prefixindex".
- */
-class prefixindexTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Prefixindex";
-
- $this->params = array (
- "title" => "Special:Prefixindex",
- "namespace" => wikiFuzz::randnum( 101, -10 ),
- "Go" => wikiFuzz::makeFuzz( 2 )
- );
-
- // sometimes we want 'prefix', sometimes we want 'from', and sometimes we want nothing.
- if ( wikiFuzz::randnum( 3 ) == 0 ) {
- $this->params["prefix"] = wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+++--+1",
- wikiFuzz::randnum( 8134, -10 ), wikiFuzz::makeFuzz( 2 ) ) );
- }
- if ( wikiFuzz::randnum( 3 ) == 0 ) {
- $this->params["from"] = wikiFuzz::chooseInput( array( "-1", "-----'--------0", "+++--+1",
- wikiFuzz::randnum( 8134, -10 ), wikiFuzz::makeFuzz( 2 ) ) );
- }
- }
-}
-
-
-/**
- ** a page test for "Special:MIMEsearch".
- */
-class mimeSearchTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:MIMEsearch";
-
- $this->params = array (
- "action" => "index.php?title=Special:MIMEsearch",
- "mime" => wikiFuzz::makeFuzz( 3 ),
- 'limit' => wikiFuzz::chooseInput( array( "0", "-1", "-------'------0", "+1", "81342321351235325", wikiFuzz::makeFuzz( 2 ) ) ),
- 'offset' => wikiFuzz::chooseInput( array( "0", "-1", "-----'--------0", "+1", "81341231235365252234324", wikiFuzz::makeFuzz( 2 ) ) )
- );
- }
-}
-
-
-/**
- ** a page test for "Special:Log".
- */
-class specialLogTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Log";
-
- $this->params = array (
- "type" => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
- "par" => wikiFuzz::makeFuzz( 2 ),
- "user" => wikiFuzz::makeFuzz( 2 ),
- "page" => wikiFuzz::makeFuzz( 2 ),
- "from" => wikiFuzz::makeFuzz( 2 ),
- "until" => wikiFuzz::makeFuzz( 2 ),
- "title" => wikiFuzz::makeFuzz( 2 )
- );
- }
-}
-
-
-/**
- ** a page test for "Special:Userlogin", with a successful login.
- */
-class successfulUserLoginTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Userlogin&action=submitlogin&type=login&returnto=" . wikiFuzz::makeFuzz( 2 );
-
- $this->params = array (
- "wpName" => USER_ON_WIKI,
- // sometimes real password, sometimes not:
- 'wpPassword' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), USER_PASSWORD ) ),
- 'wpRemember' => wikiFuzz::makeFuzz( 2 )
- );
-
- $this->cookie = "wikidb_session=" . wikiFuzz::chooseInput( array( "1" , wikiFuzz::makeFuzz( 2 ) ) );
- }
-}
-
-
-/**
- ** a page test for "Special:Userlogin".
- */
-class userLoginTest extends pageTest {
- function __construct() {
-
- $this->pagePath = "index.php?title=Special:Userlogin";
-
- $this->params = array (
- 'wpRetype' => wikiFuzz::makeFuzz( 2 ),
- 'wpRemember' => wikiFuzz::makeFuzz( 2 ),
- 'wpRealName' => wikiFuzz::makeFuzz( 2 ),
- 'wpPassword' => wikiFuzz::makeFuzz( 2 ),
- 'wpName' => wikiFuzz::makeFuzz( 2 ),
- 'wpMailmypassword' => wikiFuzz::makeFuzz( 2 ),
- 'wpLoginattempt' => wikiFuzz::makeFuzz( 2 ),
- 'wpEmail' => wikiFuzz::makeFuzz( 2 ),
- 'wpDomain' => wikiFuzz::chooseInput( array( "", "local", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpCreateaccountMail' => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpCreateaccount' => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpCookieCheck' => wikiFuzz::chooseInput( array( "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'type' => wikiFuzz::chooseInput( array( "signup", "login", "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'returnto' => wikiFuzz::makeFuzz( 2 ),
- 'action' => wikiFuzz::chooseInput( array( "", "submitlogin", wikiFuzz::makeFuzz( 2 ) ) )
- );
-
- $this->cookie = "wikidb_session=" . wikiFuzz::chooseInput( array( "1" , wikiFuzz::makeFuzz( 2 ) ) );
- }
-}
-
-
-/**
- ** a page test for "Special:Ipblocklist" (also includes unblocking)
- */
-class ipblocklistTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Ipblocklist";
-
- $this->params = array (
- 'wpUnblockAddress' => wikiFuzz::makeFuzz( 2 ),
- 'ip' => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ),
- // something like an IP address, sometimes invalid:
- ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "."
- . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ),
- 'id' => wikiFuzz::makeFuzz( 2 ),
- 'wpUnblockReason' => wikiFuzz::makeFuzz( 2 ),
- 'action' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "success", "submit", "unblock" ) ),
- 'wpEditToken' => wikiFuzz::makeFuzz( 2 ),
- 'wpBlock' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "" ) ),
- 'limit' => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1",
- "09700982312351132098234", wikiFuzz::makeFuzz( 2 ) ) ),
- 'offset' => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1",
- "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) )
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] );
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["ip"] );
- if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["id"] );
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["wpUnblockAddress"] );
- }
-}
-
-
-/**
- ** a page test for "Special:Newimages".
- */
-class newImagesTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Newimages";
-
- $this->params = array (
- 'hidebots' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "1", "", "-1" ) ),
- 'wpIlMatch' => wikiFuzz::makeFuzz( 2 ),
- 'until' => wikiFuzz::makeFuzz( 2 ),
- 'from' => wikiFuzz::makeFuzz( 2 )
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["until"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["from"] );
- }
-}
-
-
-/**
- ** a page test for the "Special:Imagelist" page.
- */
-class imagelistTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Imagelist";
-
- $this->params = array (
- 'sort' => wikiFuzz::chooseInput( array( "bysize", "byname" , "bydate", wikiFuzz::makeFuzz( 2 ) ) ),
- 'limit' => wikiFuzz::chooseInput( array( "0", "-1", "--------'-----0", "+1", "09700982312351132098234", wikiFuzz::makeFuzz( 2 ) ) ),
- 'offset' => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpIlMatch' => wikiFuzz::makeFuzz( 2 )
- );
- }
-}
-
-
-/**
- ** a page test for "Special:Export".
- */
-class specialExportTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Export";
-
- $this->params = array (
- 'action' => wikiFuzz::chooseInput( array( "submit", "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'pages' => wikiFuzz::makeFuzz( 2 ),
- 'curonly' => wikiFuzz::chooseInput( array( "", "0", "-1", wikiFuzz::makeFuzz( 2 ) ) ),
- 'listauthors' => wikiFuzz::chooseInput( array( "", "0", "-1", wikiFuzz::makeFuzz( 2 ) ) ),
- 'history' => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "09700980982341535324234234", wikiFuzz::makeFuzz( 2 ) ) ),
-
- );
-
- // For the time being, need to disable "submit" action as Tidy barfs on MediaWiki's XML export.
- if ( $this->params['action'] == 'submit' ) $this->params['action'] = '';
-
- // Sometimes remove the history field.
- if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["history"] );
-
- // page does not produce HTML.
- $this->tidyValidate = false;
- }
-}
-
-
-/**
- ** a page test for "Special:Booksources".
- */
-class specialBooksourcesTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Booksources";
-
- $this->params = array (
- 'go' => wikiFuzz::makeFuzz( 2 ),
- // ISBN codes have to contain some semi-numeric stuff or will be ignored:
- 'isbn' => "0X0" . wikiFuzz::makeFuzz( 2 )
- );
- }
-}
-
-
-/**
- ** a page test for "Special:Allpages".
- */
-class specialAllpagesTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special%3AAllpages";
-
- $this->params = array (
- 'from' => wikiFuzz::makeFuzz( 2 ),
- 'namespace' => wikiFuzz::chooseInput( range( -1, 15 ) ),
- 'go' => wikiFuzz::makeFuzz( 2 )
- );
- }
-}
-
-
-/**
- ** a page test for the page History.
- */
-class pageHistoryTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Main_Page&action=history";
-
- $this->params = array (
- 'limit' => wikiFuzz::chooseInput( array( "-1", "0", "-------'------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- 'offset' => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) ),
- "go" => wikiFuzz::chooseInput( array( "first", "last", wikiFuzz::makeFuzz( 2 ) ) ),
- "dir" => wikiFuzz::chooseInput( array( "prev", "next", wikiFuzz::makeFuzz( 2 ) ) ),
- "diff" => wikiFuzz::chooseInput( array( "-1", "--------'-----0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- "oldid" => wikiFuzz::chooseInput( array( "prev", "-1", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- "feed" => wikiFuzz::makeFuzz( 2 )
- );
- }
-}
-
-
-/**
- ** a page test for the Special:Contributions".
- */
-class contributionsTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Contributions/" . USER_ON_WIKI;
-
- $this->params = array (
- 'target' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ), "newbies", USER_ON_WIKI ) ),
- 'namespace' => wikiFuzz::chooseInput( array( -1, 15, 1, wikiFuzz::makeFuzz( 2 ) ) ),
- 'offset' => wikiFuzz::chooseInput( array( "0", "-1", "------'-------0", "+1", "982342131232131231241", wikiFuzz::makeFuzz( 2 ) ) ),
- 'bot' => wikiFuzz::chooseInput( array( "", "-1", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
- 'go' => wikiFuzz::chooseInput( array( "-1", 'prev', 'next', wikiFuzz::makeFuzz( 2 ) ) )
- );
- }
-}
-
-
-/**
- ** a page test for viewing a normal page, whilst posting various params.
- */
-class viewPageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Main_Page";
-
- $this->params = array (
- "useskin" => wikiFuzz::chooseInput( array( "chick", "cologneblue", "myskin",
- "nostalgia", "simple", "standard", wikiFuzz::makeFuzz( 2 ) ) ),
- "uselang" => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ),
- "ab", "af", "an", "ar", "arc", "as", "ast", "av", "ay", "az", "ba",
- "bat-smg", "be", "bg", "bm", "bn", "bo", "bpy", "br", "bs", "ca",
- "ce", "cs", "csb", "cv", "cy", "da", "de", "dv", "dz", "el", "en",
- "eo", "es", "et", "eu", "fa", "fi", "fo", "fr", "fur", "fy", "ga",
- "gn", "gsw", "gu", "he", "hi", "hr", "hu", "ia", "id", "ii", "is",
- "it", "ja", "jv", "ka", "km", "kn", "ko", "ks", "ku", "kv", "la",
- "li", "lo", "lt", "lv", "mk", "ml", "ms", "nah", "nap", "nds",
- "nds-nl", "nl", "nn", "no", "non", "nv", "oc", "or", "os", "pa",
- "pl", "pms", "ps", "pt", "pt-br", "qu", "rmy", "ro", "ru", "sc",
- "sd", "sk", "sl", "sq", "sr", "sr-ec", "sr-el",
- "su", "sv", "ta", "te", "th", "tr", "tt", "ty", "tyv", "udm",
- "ug", "uk", "ur", "utf8", "vec", "vi", "wa", "xal", "yi", "za",
- "zh", "zh-cn", "zh-hk", "zh-sg", "zh-tw", "zh-tw" ) ),
- "returnto" => wikiFuzz::makeFuzz( 2 ),
- "feed" => wikiFuzz::chooseInput( array( "atom", "rss", wikiFuzz::makeFuzz( 2 ) ) ),
- "rcid" => wikiFuzz::makeFuzz( 2 ),
- "action" => wikiFuzz::chooseInput( array( "view", "raw", "render", wikiFuzz::makeFuzz( 2 ), "markpatrolled" ) ),
- "printable" => wikiFuzz::makeFuzz( 2 ),
- "oldid" => wikiFuzz::makeFuzz( 2 ),
- "redirect" => wikiFuzz::makeFuzz( 2 ),
- "diff" => wikiFuzz::makeFuzz( 2 ),
- "search" => wikiFuzz::makeFuzz( 2 ),
- "rdfrom" => wikiFuzz::makeFuzz( 2 ), // things from Article.php from here on:
- "token" => wikiFuzz::makeFuzz( 2 ),
- "tbid" => wikiFuzz::makeFuzz( 2 ),
- // @todo FIXME: Duplicate array key.
- "action" => wikiFuzz::chooseInput( array( "purge", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpReason" => wikiFuzz::makeFuzz( 2 ),
- "wpEditToken" => wikiFuzz::makeFuzz( 2 ),
- "from" => wikiFuzz::makeFuzz( 2 ),
- "bot" => wikiFuzz::makeFuzz( 2 ),
- "summary" => wikiFuzz::makeFuzz( 2 ),
- "direction" => wikiFuzz::chooseInput( array( "next", "prev", wikiFuzz::makeFuzz( 2 ) ) ),
- "section" => wikiFuzz::makeFuzz( 2 ),
- "preload" => wikiFuzz::makeFuzz( 2 ),
-
- );
-
- // Tidy does not know how to valid atom or rss, so exclude from testing for the time being.
- if ( $this->params["feed"] == "atom" ) { unset( $this->params["feed"] ); }
- elseif ( $this->params["feed"] == "rss" ) { unset( $this->params["feed"] ); }
-
- // Raw pages cannot really be validated
- if ( $this->params["action"] == "raw" ) unset( $this->params["action"] );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["rcid"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["diff"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["rdfrom"] );
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["oldid"] );
-
- // usually don't want action == purge.
- if ( wikiFuzz::randnum( 6 ) > 1 ) unset( $this->params["action"] );
- }
-}
-
-
-/**
- ** a page test for "Special:Allmessages".
- */
-class specialAllmessagesTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Allmessages";
-
- // only really has one parameter
- $this->params = array (
- "ot" => wikiFuzz::chooseInput( array( "php", "html", wikiFuzz::makeFuzz( 2 ) ) )
- );
- }
-}
-
-/**
- ** a page test for "Special:Newpages".
- */
-class specialNewpagesPageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Newpages";
-
- $this->params = array (
- "namespace" => wikiFuzz::chooseInput( range( -1, 15 ) ),
- "feed" => wikiFuzz::chooseInput( array( "atom", "rss", wikiFuzz::makeFuzz( 2 ) ) ),
- 'limit' => wikiFuzz::chooseInput( array( "-1", "0", "-------'------0", "+1", "8134", wikiFuzz::makeFuzz( 2 ) ) ),
- 'offset' => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) )
- );
-
- // Tidy does not know how to valid atom or rss, so exclude from testing for the time being.
- if ( $this->params["feed"] == "atom" ) { unset( $this->params["feed"] ); }
- elseif ( $this->params["feed"] == "rss" ) { unset( $this->params["feed"] ); }
- }
-}
-
-/**
- ** a page test for "redirect.php"
- */
-class redirectTest extends pageTest {
- function __construct() {
- $this->pagePath = "redirect.php";
-
- $this->params = array (
- "wpDropdown" => wikiFuzz::makeFuzz( 2 )
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpDropdown"] );
- }
-}
-
-
-/**
- ** a page test for "Special:Confirmemail"
- */
-class confirmEmail extends pageTest {
- function __construct() {
- // sometimes we send a bogus confirmation code, and sometimes we don't.
- $this->pagePath = "index.php?title=Special:Confirmemail" . wikiFuzz::chooseInput( array( "", "/" . wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 1 ) ) ) );
-
- $this->params = array (
- "token" => wikiFuzz::makeFuzz( 2 )
- );
- }
-}
-
-
-/**
- ** a page test for "Special:Watchlist"
- ** Note: this test would be better if we were logged in.
- */
-class watchlistTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Watchlist";
-
- $this->params = array (
- "remove" => wikiFuzz::chooseInput( array( "Remove checked items from watchlist", wikiFuzz::makeFuzz( 2 ) ) ),
- 'days' => wikiFuzz::chooseInput( array( 0, -1, -230, "--", 3, 9, wikiFuzz::makeFuzz( 2 ) ) ),
- 'hideOwn' => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
- 'hideBots' => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
- 'namespace' => wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
- 'action' => wikiFuzz::chooseInput( array( "submit", "clear", wikiFuzz::makeFuzz( 2 ) ) ),
- 'id[]' => wikiFuzz::makeFuzz( 2 ),
- 'edit' => wikiFuzz::makeFuzz( 2 ),
- 'token' => wikiFuzz::chooseInput( array( "", "1243213", wikiFuzz::makeFuzz( 2 ) ) )
- );
-
- // sometimes we specifiy "reset", and sometimes we don't.
- if ( wikiFuzz::randnum( 3 ) == 0 ) $this->params["reset"] = wikiFuzz::chooseInput( array( "", "0", "1", wikiFuzz::makeFuzz( 2 ) ) );
- }
-}
-
-/**
- ** a page test for "Special:Movepage"
- */
-class specialMovePage extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Movepage";
-
- $this->params = array (
- "action" => wikiFuzz::chooseInput( array( "success", "submit", "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpEditToken' => wikiFuzz::chooseInput( array( '', 0, 34987987, wikiFuzz::makeFuzz( 2 ) ) ),
- 'target' => wikiFuzz::chooseInput( array( "x", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ) ) ),
- 'wpOldTitle' => wikiFuzz::chooseInput( array( "z", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ), wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpNewTitle' => wikiFuzz::chooseInput( array( "y", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ), wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpReason' => wikiFuzz::chooseInput( array( wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpMovetalk' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpDeleteAndMove' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpConfirm' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- 'talkmoved' => wikiFuzz::chooseInput( array( "1", wikiFuzz::makeFuzz( 2 ), "articleexists", 'notalkpage' ) ),
- 'oldtitle' => wikiFuzz::makeFuzz( 2 ),
- 'newtitle' => wikiFuzz::makeFuzz( 2 ),
- 'wpMovetalk' => wikiFuzz::chooseInput( array( "1", "0", wikiFuzz::makeFuzz( 2 ) ) )
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["wpEditToken"] );
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["target"] );
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["wpNewTitle"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpReason"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpOldTitle"] );
- }
-}
-
-
-/**
- ** a page test for "Special:Undelete"
- */
-class specialUndeletePageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Undelete";
-
- $this->params = array (
- "action" => wikiFuzz::chooseInput( array( "submit", "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpEditToken' => wikiFuzz::chooseInput( array( '', 0, 34987987, wikiFuzz::makeFuzz( 2 ) ) ),
- 'target' => wikiFuzz::chooseInput( array( "x", wikiFuzz::makeTitleSafe( wikiFuzz::makeFuzz( 2 ) ) ) ),
- 'timestamp' => wikiFuzz::chooseInput( array( "125223", wikiFuzz::makeFuzz( 2 ) ) ),
- 'file' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- 'restore' => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
- 'preview' => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpComment' => wikiFuzz::makeFuzz( 2 )
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["wpEditToken"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["target"] );
- if ( wikiFuzz::randnum( 1 ) == 0 ) unset( $this->params["restore"] );
- if ( wikiFuzz::randnum( 1 ) == 0 ) unset( $this->params["preview"] );
- }
-}
-
-
-/**
- ** a page test for "Special:Unlockdb"
- */
-class specialUnlockdbPageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Unlockdb";
-
- $this->params = array (
- "action" => wikiFuzz::chooseInput( array( "submit", "success", "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpEditToken' => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpLockConfirm' => wikiFuzz::chooseInput( array( "0", "1", wikiFuzz::makeFuzz( 2 ) ) )
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpEditToken"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpLockConfirm"] );
- }
-}
-
-
-/**
- ** a page test for "Special:Lockdb"
- */
-class specialLockdbPageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Lockdb";
-
- $this->params = array (
- "action" => wikiFuzz::chooseInput( array( "submit", "success", "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpEditToken' => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpLockReason' => wikiFuzz::makeFuzz( 2 ),
- 'wpLockConfirm' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) )
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpEditToken"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["action"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpLockConfirm"] );
- }
-}
-
-
-/**
- ** a page test for "Special:Userrights"
- */
-class specialUserrights extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Userrights";
-
- $this->params = array (
- 'wpEditToken' => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'user-editname' => wikiFuzz::chooseInput( array( "Nickj2", "Nickj2\n<xyz>", wikiFuzz::makeFuzz( 2 ) ) ),
- 'ssearchuser' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- 'saveusergroups' => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ), "Save User Groups" ),
- 'member[]' => wikiFuzz::chooseInput( array( "0", "bot", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "available[]" => wikiFuzz::chooseInput( array( "0", "sysop", "bureaucrat", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) )
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['ssearchuser'] );
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['saveusergroups'] );
- }
-}
-
-
-/**
- ** a test for page protection and unprotection.
- */
-class pageProtectionForm extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Main_Page";
-
- $this->params = array (
- "action" => "protect",
- 'wpEditToken' => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- "mwProtect-level-edit" => wikiFuzz::chooseInput( array( '', 'autoconfirmed', 'sysop', wikiFuzz::makeFuzz( 2 ) ) ),
- "mwProtect-level-move" => wikiFuzz::chooseInput( array( '', 'autoconfirmed', 'sysop', wikiFuzz::makeFuzz( 2 ) ) ),
- "mwProtectUnchained" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- 'mwProtect-reason' => wikiFuzz::chooseInput( array( "because it was there", wikiFuzz::makeFuzz( 2 ) ) )
- );
-
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["mwProtectUnchained"] );
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params['mwProtect-reason'] );
- }
-}
-
-
-/**
- ** a page test for "Special:Blockip".
- */
-class specialBlockip extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Blockip";
-
- $this->params = array (
- "action" => wikiFuzz::chooseInput( array( "submit", "", wikiFuzz::makeFuzz( 2 ) ) ),
- 'wpEditToken' => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpBlockAddress" => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ),
- // something like an IP address, sometimes invalid:
- ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "."
- . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ),
- "ip" => wikiFuzz::chooseInput( array( "20398702394", "", "Nickj2", wikiFuzz::makeFuzz( 2 ),
- // something like an IP address, sometimes invalid:
- ( wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) . "."
- . wikiFuzz::randnum( 300, -20 ) . "." . wikiFuzz::randnum( 300, -20 ) ) ) ),
- "wpBlockOther" => wikiFuzz::chooseInput( array( '', 'Nickj2', wikiFuzz::makeFuzz( 2 ) ) ),
- "wpBlockExpiry" => wikiFuzz::chooseInput( array( "other", "2 hours", "1 day", "3 days", "1 week", "2 weeks",
- "1 month", "3 months", "6 months", "1 year", "infinite", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpBlockReason" => wikiFuzz::chooseInput( array( "because it was there", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpAnonOnly" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpCreateAccount" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpBlock" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) )
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockOther"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockExpiry"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockReason"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpAnonOnly"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpCreateAccount"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["wpBlockAddress"] );
- if ( wikiFuzz::randnum( 4 ) == 0 ) unset( $this->params["ip"] );
- }
-}
-
-
-/**
- ** a test for the imagepage.
- */
-class imagepageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Image:Small-email.png";
-
- $this->params = array (
- "image" => wikiFuzz::chooseInput( array( "Small-email.png", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpReason" => wikiFuzz::makeFuzz( 2 ),
- "oldimage" => wikiFuzz::chooseInput( array( "Small-email.png", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpEditToken" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["image"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpReason"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldimage"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpEditToken"] );
- }
-}
-
-
-/**
- ** a test for page deletion form.
- */
-class pageDeletion extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Main_Page&action=delete";
-
- $this->params = array (
- "wpEditToken" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpReason" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpConfirm" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpReason"] );
- if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpEditToken"] );
- if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["wpConfirm"] );
- }
-}
-
-
-
-/**
- ** a test for Revision Deletion.
- */
-class specialRevisionDeletePageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Revisiondelete";
-
- $this->params = array (
- "target" => wikiFuzz::chooseInput( array( "Main Page", wikiFuzz::makeFuzz( 2 ) ) ),
- "oldid" => wikiFuzz::makeFuzz( 2 ),
- "oldid[]" => wikiFuzz::makeFuzz( 2 ),
- "wpReason" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "revdelete-hide-text" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "revdelete-hide-comment" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "revdelete-hide-user" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "revdelete-hide-restricted" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["target"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldid"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["oldid[]"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["wpReason"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-text"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-comment"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-user"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["revdelete-hide-restricted"] );
- }
-}
-
-
-/**
- ** a test for Special:Import.
- */
-class specialImportPageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Import";
-
- $this->params = array (
- "action" => "submit",
- "source" => wikiFuzz::chooseInput( array( "upload", "interwiki", wikiFuzz::makeFuzz( 2 ) ) ),
- "MAX_FILE_SIZE" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "xmlimport" => wikiFuzz::chooseInput( array( "/var/www/hosts/mediawiki/wiki/AdminSettings.php", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "namespace" => wikiFuzz::chooseInput( array( wikiFuzz::randnum( 30, -6 ), wikiFuzz::makeFuzz( 2 ) ) ),
- "interwiki" => wikiFuzz::makeFuzz( 2 ),
- "interwikiHistory" => wikiFuzz::makeFuzz( 2 ),
- "frompage" => wikiFuzz::makeFuzz( 2 ),
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["action"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["source"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["MAX_FILE_SIZE"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["xmlimport"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["interwiki"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["interwikiHistory"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["frompage"] );
-
- // Note: Need to do a file upload to fully test this Special page.
- }
-}
-
-
-/**
- ** a test for thumb.php
- */
-class thumbTest extends pageTest {
- function __construct() {
- $this->pagePath = "thumb.php";
-
- $this->params = array (
- "f" => wikiFuzz::chooseInput( array( "..", "\\", "small-email.png", wikiFuzz::makeFuzz( 2 ) ) ),
- "w" => wikiFuzz::chooseInput( array( "80", wikiFuzz::randnum( 6000, -200 ), wikiFuzz::makeFuzz( 2 ) ) ),
- "r" => wikiFuzz::chooseInput( array( "0", wikiFuzz::makeFuzz( 2 ) ) ),
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["f"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["w"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["r"] );
- }
-}
-
-/**
- ** a test for profileinfo.php
- */
-class profileInfo extends pageTest {
- function __construct() {
- $this->pagePath = "profileinfo.php";
-
- $this->params = array (
- "expand" => wikiFuzz::makeFuzz( 2 ),
- "sort" => wikiFuzz::chooseInput( array( "time", "count", "name", wikiFuzz::makeFuzz( 2 ) ) ),
- "filter" => wikiFuzz::chooseInput( array( "Main Page", wikiFuzz::makeFuzz( 2 ) ) ),
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["sort"] );
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["filter"] );
- }
-}
-
-
-/**
- ** a test for Special:Cite (extension Special page).
- */
-class specialCitePageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Cite";
-
- $this->params = array (
- "page" => wikiFuzz::chooseInput( array( "\" onmouseover=\"alert(1);\"", "Main Page", wikiFuzz::makeFuzz( 2 ) ) ),
- "id" => wikiFuzz::chooseInput( array( "-1", "0", "------'-------0", "+1", "-9823412312312412435", wikiFuzz::makeFuzz( 2 ) ) ),
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["page"] );
- if ( wikiFuzz::randnum( 6 ) == 0 ) unset( $this->params["id"] );
- }
-}
-
-
-/**
- ** a test for Special:Filepath (extension Special page).
- */
-class specialFilepathPageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Filepath";
-
- $this->params = array (
- "file" => wikiFuzz::chooseInput( array( "Small-email.png", "Small-email.png" . wikiFuzz::makeFuzz( 1 ), wikiFuzz::makeFuzz( 2 ) ) ),
- );
- }
-}
-
-
-/**
- ** a test for Special:Renameuser (extension Special page).
- */
-class specialRenameuserPageTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Renameuser";
-
- $this->params = array (
- "oldusername" => wikiFuzz::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz::makeFuzz( 1 ) ) ),
- "newusername" => wikiFuzz::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz::makeFuzz( 1 ) ) ),
- "token" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- );
- }
-}
-
-
-/**
- ** a test for Special:Linksearch (extension Special page).
- */
-class specialLinksearch extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special%3ALinksearch";
-
- $this->params = array (
- "target" => wikiFuzz::makeFuzz( 2 ),
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 10 ) == 0 ) unset( $this->params["target"] );
- }
-}
-
-
-/**
- ** a test for Special:CategoryTree (extension Special page).
- */
-class specialCategoryTree extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:CategoryTree";
-
- $this->params = array (
- "target" => wikiFuzz::makeFuzz( 2 ),
- "from" => wikiFuzz::makeFuzz( 2 ),
- "until" => wikiFuzz::makeFuzz( 2 ),
- "showas" => wikiFuzz::makeFuzz( 2 ),
- "mode" => wikiFuzz::chooseInput( array( "pages", "categories", "all", wikiFuzz::makeFuzz( 2 ) ) ),
- );
-
- // sometimes we do want to specify certain parameters.
- if ( wikiFuzz::randnum( 5 ) == 0 ) $this->params["notree"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
- }
-}
-
-
-/**
- ** a test for "Special:Chemicalsources" (extension Special page).
- */
-class specialChemicalsourcesTest extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Chemicalsources";
-
- // choose an input format to use.
- $format = wikiFuzz::chooseInput(
- array( 'go',
- 'CAS',
- 'EINECS',
- 'CHEBI',
- 'PubChem',
- 'SMILES',
- 'InChI',
- 'ATCCode',
- 'KEGG',
- 'RTECS',
- 'ECNumber',
- 'DrugBank',
- 'Formula',
- 'Name'
- )
- );
-
- // values for different formats usually start with either letters or numbers.
- switch ( $format ) {
- case 'Name' : $value = "A"; break;
- case 'InChI' :
- case 'SMILES' :
- case 'Formula': $value = "C"; break;
- default : $value = "0"; break;
- }
-
- // and then we append the fuzz input.
- $this->params = array ( $format => $value . wikiFuzz::makeFuzz( 2 ) );
- }
-}
-
-
-/**
- ** A test for api.php (programmatic interface to MediaWiki in XML/JSON/RSS/etc formats).
- ** Quite involved to test because there are lots of options/parameters, and because
- ** for a lot of the functionality if all the parameters don't make sense then it just
- ** returns the help screen - so currently a lot of the tests aren't actually doing much
- ** because something wasn't right in the query.
- **
- ** @todo Incomplete / unfinished; Runs too fast (suggests not much testing going on).
- */
-class api extends pageTest {
-
- // API login mode.
- private static function loginMode() {
- $arr = array ( "lgname" => wikiFuzz::makeFuzz( 2 ),
- "lgpassword" => wikiFuzz::makeFuzz( 2 ),
- );
- // sometimes we want to specify the extra "lgdomain" parameter.
- if ( wikiFuzz::randnum( 3 ) == 0 ) {
- $arr["lgdomain"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
- }
-
- return $arr;
- }
-
- // API OpenSearch mode.
- private static function opensearchMode() {
- return array ( "search" => wikiFuzz::makeFuzz( 2 ) );
- }
-
- // API watchlist feed mode.
- private static function feedwatchlistMode() {
- // @todo FIXME: Add "wikiFuzz::makeFuzz(2)" as possible value below?
- return array ( "feedformat" => wikiFuzz::chooseInput( array( "rss", "atom" ) ) );
- }
-
- // API query mode.
- private static function queryMode() {
- // @todo FIXME: Add "wikiFuzz::makeFuzz(2)" as possible params for the elements below?
- // Suspect this will stuff up the tests more, but need to check.
- $params = array (
- // @todo FIXME: More titles.
- "titles" => wikiFuzz::chooseInput( array( "Main Page" ) ),
- // @todo FIXME: More pageids.
- "pageids" => 1,
- "prop" => wikiFuzz::chooseInput( array( "info", "revisions", "watchlist" ) ),
- "list" => wikiFuzz::chooseInput( array( "allpages", "logevents", "watchlist", "usercontribs", "recentchanges", "backlinks", "embeddedin", "imagelinks" ) ),
- "meta" => wikiFuzz::chooseInput( array( "siteinfo" ) ),
- "generator" => wikiFuzz::chooseInput( array( "allpages", "logevents", "watchlist", "info", "revisions" ) ),
- "siprop" => wikiFuzz::chooseInput( array( "general", "namespaces", "general|namespaces" ) ),
- );
-
- // Add extra parameters based on what list choice we got.
- switch ( $params["list"] ) {
- case "usercontribs" : self::addListParams ( $params, "uc", array( "limit", "start", "end", "user", "dir" ) ); break;
- case "allpages" : self::addListParams ( $params, "ap", array( "from", "prefix", "namespace", "filterredir", "limit" ) ); break;
- case "watchlist" : self::addListParams ( $params, "wl", array( "allrev", "start", "end", "namespace", "dir", "limit", "prop" ) ); break;
- case "logevents" : self::addListParams ( $params, "le", array( "limit", "type", "start", "end", "user", "dir" ) ); break;
- case "recentchanges": self::addListParams ( $params, "rc", array( "limit", "prop", "show", "namespace", "start", "end", "dir" ) ); break;
- case "backlinks" : self::addListParams ( $params, "bl", array( "continue", "namespace", "redirect", "limit" ) ); break;
- case "embeddedin" : self::addListParams ( $params, "ei", array( "continue", "namespace", "redirect", "limit" ) ); break;
- case "imagelinks" : self::addListParams ( $params, "il", array( "continue", "namespace", "redirect", "limit" ) ); break;
- }
-
- if ( $params["prop"] == "revisions" ) {
- self::addListParams ( $params, "rv", array( "prop", "limit", "startid", "endid", "end", "dir" ) );
- }
-
- // Sometimes we want redirects, sometimes we don't.
- if ( wikiFuzz::randnum( 3 ) == 0 ) {
- $params["redirects"] = wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
- }
-
- return $params;
- }
-
- // Adds all the elements to the array, using the specified prefix.
- private static function addListParams( &$array, $prefix, $elements ) {
- foreach ( $elements as $element ) {
- $array[$prefix . $element] = self::getParamDetails( $element );
- }
- }
-
- // For a given element name, returns the data for that element.
- private static function getParamDetails( $element ) {
- switch ( $element ) {
- case 'startid' :
- case 'endid' :
- case 'start' :
- case 'end' :
- case 'limit' : return wikiFuzz::chooseInput( array( "0", "-1", "---'----------0", "+1", "8134", "320742734234235", "20060230121212", wikiFuzz::randnum( 9000, -100 ), wikiFuzz::makeFuzz( 2 ) ) );
- case 'dir' : return wikiFuzz::chooseInput( array( "newer", "older", wikiFuzz::makeFuzz( 2 ) ) );
- case 'user' : return wikiFuzz::chooseInput( array( USER_ON_WIKI, wikiFuzz::makeFuzz( 2 ) ) );
- case 'namespace' : return wikiFuzz::chooseInput( array( -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 200000, wikiFuzz::makeFuzz( 2 ) ) );
- case 'filterredir': return wikiFuzz::chooseInput( array( "all", "redirects", "nonredirectsallpages", wikiFuzz::makeFuzz( 2 ) ) );
- case 'allrev' : return wikiFuzz::chooseInput( array( "1", 0, "", wikiFuzz::makeFuzz( 2 ) ) );
- case 'prop' : return wikiFuzz::chooseInput( array( "user", "comment", "timestamp", "patrol", "flags", "user|user|comment|flags", wikiFuzz::makeFuzz( 2 ) ) );
- case 'type' : return wikiFuzz::chooseInput( array( "block", "protect", "rights", "delete", "upload", "move", "import", "renameuser", "newusers", "makebot", wikiFuzz::makeFuzz( 2 ) ) );
- case 'hide' : return wikiFuzz::chooseInput( array( "minor", "bots", "anons", "liu", "liu|bots|", wikiFuzz::makeFuzz( 2 ) ) );
- case 'show' : return wikiFuzz::chooseInput( array( 'minor', '!minor', 'bot', '!bot', 'anon', '!anon', wikiFuzz::makeFuzz( 2 ) ) );
- default : return wikiFuzz::makeFuzz( 2 );
- }
- }
-
- // Entry point.
- function __construct() {
- $this->pagePath = "api.php";
-
- $modes = array ( "help",
- "login",
- "opensearch",
- "feedwatchlist",
- "query" );
- $action = wikiFuzz::chooseInput( array_merge ( $modes, array( wikiFuzz::makeFuzz( 2 ) ) ) );
-
- switch ( $action ) {
- case "login" : $this->params = self::loginMode();
- break;
- case "opensearch" : $this->params = self::opensearchMode();
- break;
- case "feedwatchlist" : $this->params = self::feedwatchlistMode();
- break;
- case "query" : $this->params = self::queryMode();
- break;
- case "help" :
- default : // Do something random - "Crazy Ivan" mode.
- $random_mode = wikiFuzz::chooseInput( $modes ) . "Mode";
- // There is no "helpMode".
- if ( $random_mode == "helpMode" ) $random_mode = "queryMode";
- $this->params = self::$random_mode();
- break;
- }
-
- // Save the selected action.
- $this->params["action"] = $action;
-
- // Set the cookie:
- // @todo FIXME: Need to get this cookie dynamically set, rather than hard-coded.
- $this->cookie = "wikidbUserID=10001; wikidbUserName=Test; wikidb_session=178df0fe68c75834643af65dec9ec98a; wikidbToken=1adc6753d62c44aec950c024d7ae0540";
-
- // Output format
- $this->params["format"] = wikiFuzz::chooseInput( array( "json", "jsonfm", "php", "phpfm",
- "wddx", "wddxfm", "xml", "xmlfm",
- "yaml", "yamlfm", "raw", "rawfm",
- wikiFuzz::makeFuzz( 2 ) ) );
-
- // Page does not produce HTML (sometimes).
- $this->tidyValidate = false;
- }
-}
-
-
-/**
- ** a page test for the GeSHi extension.
- */
-class GeSHi_Test extends pageTest {
-
- private function getGeSHiContent() {
- return "<source lang=\"" . $this->getLang() . "\" "
- . ( wikiFuzz::randnum( 2 ) == 0 ? "line " : "" )
- . ( wikiFuzz::randnum( 2 ) == 0 ? "strict " : "" )
- . "start=" . wikiFuzz::chooseInput( array( wikiFuzz::randnum( 6000, -6000 ), wikiFuzz::makeFuzz( 2 ) ) )
- . ">"
- . wikiFuzz::makeFuzz( 2 )
- . "</source>";
- }
-
- private function getLang() {
- return wikiFuzz::chooseInput( array( "actionscript", "ada", "apache", "applescript", "asm", "asp", "autoit", "bash", "blitzbasic", "bnf", "c", "c_mac", "caddcl", "cadlisp",
- "cfdg", "cfm", "cpp", "cpp-qt", "csharp", "css", "d", "delphi", "diff", "div", "dos", "eiffel", "fortran", "freebasic", "gml", "groovy", "html4strict", "idl",
- "ini", "inno", "io", "java", "java5", "javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc", "ocaml", "ocaml-brief", "oobas",
- "oracle8", "pascal", "perl", "php", "php-brief", "plsql", "python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic", "smalltalk", "smarty",
- "sql", "tcl", "text", "thinbasic", "tsql", "vb", "vbnet", "vhdl", "visualfoxpro", "winbatch", "xml", "xpp", "z80", wikiFuzz::makeFuzz( 1 ) ) );
- }
-
- function __construct() {
- $this->pagePath = "index.php?title=WIKIFUZZ";
-
- $this->params = array (
- "action" => "submit",
- "wpMinoredit" => "test",
- "wpPreview" => "test",
- "wpSection" => "test",
- "wpEdittime" => "test",
- "wpSummary" => "test",
- "wpScrolltop" => "test",
- "wpStarttime" => "test",
- "wpAutoSummary" => "test",
- "wpTextbox1" => $this->getGeSHiContent() // the main wiki text, contains fake GeSHi content.
- );
- }
-}
-
-/**
- ** selects a page test to run.
- * @param $count
- * @return \api|\confirmEmail|\contributionsTest|\editPageTest|\imagelistTest|\imagepageTest|\ipblocklistTest|\listusersTest|\mimeSearchTest|\newImagesTest|\pageDeletion|\pageHistoryTest|\pageProtectionForm|\prefixindexTest|\profileInfo|\recentchangesTest|\redirectTest|\searchTest|\specialAllmessagesTest|\specialAllpagesTest|\specialBlockip|\specialBooksourcesTest|\specialCategoryTree|\specialChemicalsourcesTest|\specialCitePageTest|\specialExportTest|\specialFilepathPageTest|\specialImportPageTest|\specialLinksearch|\specialLockdbPageTest|\specialLogTest|\specialMovePage|\specialNewpagesPageTest|\specialRenameuserPageTest|\specialRevisionDeletePageTest|\specialUndeletePageTest|\specialUnlockdbPageTest|\specialUserrights|\successfulUserLoginTest|\thumbTest|\userLoginTest|\viewPageTest|\watchlistTest
- */
-function selectPageTest( $count ) {
-
- // if the user only wants a specific test, then only ever give them that.
- if ( defined( "SPECIFIC_TEST" ) ) {
- $testType = SPECIFIC_TEST;
- return new $testType ();
- }
-
- // Some of the time we test Special pages, the remaining
- // time we test using the standard edit page.
- switch ( $count % 100 ) {
- case 0 : return new successfulUserLoginTest();
- case 1 : return new listusersTest();
- case 2 : return new searchTest();
- case 3 : return new recentchangesTest();
- case 4 : return new prefixindexTest();
- case 5 : return new mimeSearchTest();
- case 6 : return new specialLogTest();
- case 7 : return new userLoginTest();
- case 8 : return new ipblocklistTest();
- case 9 : return new newImagesTest();
- case 10: return new imagelistTest();
- case 11: return new specialExportTest();
- case 12: return new specialBooksourcesTest();
- case 13: return new specialAllpagesTest();
- case 14: return new pageHistoryTest();
- case 15: return new contributionsTest();
- case 16: return new viewPageTest();
- case 17: return new specialAllmessagesTest();
- case 18: return new specialNewpagesPageTest();
- case 19: return new searchTest();
- case 20: return new redirectTest();
- case 21: return new confirmEmail();
- case 22: return new watchlistTest();
- case 24: return new specialUndeletePageTest();
- case 25: return new specialMovePage();
- case 26: return new specialUnlockdbPageTest();
- case 27: return new specialLockdbPageTest();
- case 28: return new specialUserrights();
- case 29: return new pageProtectionForm();
- case 30: return new specialBlockip();
- case 31: return new imagepageTest();
- case 32: return new pageDeletion();
- case 33: return new specialRevisionDeletePageTest();
- case 34: return new specialImportPageTest();
- case 35: return new thumbTest();
- case 37: return new profileInfo();
- case 38: return new specialCitePageTest();
- case 39: return new specialFilepathPageTest();
- case 40: return new specialRenameuserPageTest();
- case 41: return new specialLinksearch();
- case 42: return new specialCategoryTree();
- case 43: return new api();
- case 44: return new specialChemicalsourcesTest();
- default: return new editPageTest();
- }
-}
-
-
-// ///////////////////// SAVING OUTPUT /////////////////////////
-
-/**
- ** Utility function for saving a file. Currently has no error checking.
- */
-function saveFile( $data, $name ) {
- file_put_contents( $name, $data );
-}
-
-/**
- ** Returns a test as an experimental GET-to-POST URL.
- ** This doesn't seem to always work though, and sometimes the output is too long
- ** to be a valid GET URL, so we also save in other formats.
- * @param $test pageTest
- * @return string
- */
-function getAsURL( pageTest $test ) {
- $used_question_mark = ( strpos( $test->getPagePath(), "?" ) !== false );
- $retval = "http://get-to-post.nickj.org/?" . WIKI_BASE_URL . $test->getPagePath();
- foreach ( $test->getParams() as $param => $value ) {
- if ( !$used_question_mark ) {
- $retval .= "?";
- $used_question_mark = true;
- }
- else {
- $retval .= "&";
- }
- $retval .= $param . "=" . urlencode( $value );
- }
- return $retval;
-}
-
-
-/**
- ** Saves a plain-text human-readable version of a test.
- */
-function saveTestAsText( pageTest $test, $filename ) {
- $str = "Test: " . $test->getPagePath();
- foreach ( $test->getParams() as $param => $value ) {
- $str .= "\n$param: $value";
- }
- $str .= "\nGet-to-post URL: " . getAsURL( $test ) . "\n";
- saveFile( $str, $filename );
-}
-
-
-/**
- ** Saves a test as a standalone basic PHP script that shows this one problem.
- ** Resulting script requires PHP-Curl be installed in order to work.
- */
-function saveTestAsPHP( pageTest $test, $filename ) {
- $str = "<?php\n"
- . "\$params = " . var_export( escapeForCurl( $test->getParams() ), true ) . ";\n"
- . "\$ch = curl_init();\n"
- . "curl_setopt(\$ch, CURLOPT_POST, 1);\n"
- . "curl_setopt(\$ch, CURLOPT_POSTFIELDS, \$params );\n"
- . "curl_setopt(\$ch, CURLOPT_URL, " . var_export( WIKI_BASE_URL . $test->getPagePath(), true ) . ");\n"
- . "curl_setopt(\$ch, CURLOPT_RETURNTRANSFER,1);\n"
- . ( $test->getCookie() ? "curl_setopt(\$ch, CURLOPT_COOKIE, " . var_export( $test->getCookie(), true ) . ");\n" : "" )
- . "\$result=curl_exec(\$ch);\n"
- . "curl_close (\$ch);\n"
- . "print \$result;\n"
- . "\n";
- saveFile( $str, $filename );
-}
-
-/**
- * Escapes a value so that it can be used on the command line by Curl.
- * Specifically, "<" and "@" need to be escaped if they are the first character,
- * otherwise curl interprets these as meaning that we want to insert a file.
- * @param $input_params array
- * @return array
- */
-function escapeForCurl( array $input_params ) {
- $output_params = array();
- foreach ( $input_params as $param => $value ) {
- if ( strlen( $value ) > 0 && ( $value[0] == "@" || $value[0] == "<" ) ) {
- $value = "\\" . $value;
- }
- $output_params[$param] = $value;
- }
- return $output_params;
-}
-
-
-/**
- ** Saves a test as a standalone CURL shell script that shows this one problem.
- ** Resulting script requires standalone Curl be installed in order to work.
- */
-function saveTestAsCurl( pageTest $test, $filename ) {
- $str = "#!/bin/bash\n"
- . "curl --silent --include --globoff \\\n"
- . ( $test->getCookie() ? " --cookie " . escapeshellarg( $test->getCookie() ) . " \\\n" : "" );
- foreach ( escapeForCurl( $test->getParams() ) as $param => $value ) {
- $str .= " -F " . escapeshellarg( $param ) . "=" . escapeshellarg( $value ) . " \\\n";
- }
- $str .= " " . escapeshellarg( WIKI_BASE_URL . $test->getPagePath() ); // beginning space matters.
- $str .= "\n";
- saveFile( $str, $filename );
- chmod( $filename, 0755 ); // make executable
-}
-
-
-/**
- ** Saves the internal data structure to file.
- */
-function saveTestData ( pageTest $test, $filename ) {
- saveFile( serialize( $test ), $filename );
-}
-
-
-/**
- ** saves a test in the various formats.
- */
-function saveTest( pageTest $test, $testname ) {
- $base_name = DIRECTORY . "/" . $testname;
- saveTestAsText( $test, $base_name . INFO_FILE );
- saveTestAsPHP ( $test, $base_name . PHP_TEST );
- saveTestAsCurl( $test, $base_name . CURL_TEST );
- saveTestData ( $test, $base_name . DATA_FILE );
-}
-
-// ////////////////// MEDIAWIKI OUTPUT /////////////////////////
-
-/**
- * Asks MediaWiki for the HTML output of a test.
- * @param $test pageTest
- * @return string
- */
-function wikiTestOutput( pageTest $test ) {
-
- $ch = curl_init();
-
- // specify the cookie, if required.
- if ( $test->getCookie() ) {
- curl_setopt( $ch, CURLOPT_COOKIE, $test->getCookie() );
- }
- curl_setopt( $ch, CURLOPT_POST, 1 ); // save form using a POST
-
- $params = escapeForCurl( $test->getParams() );
- curl_setopt( $ch, CURLOPT_POSTFIELDS, $params ); // load the POST variables
-
- curl_setopt( $ch, CURLOPT_URL, WIKI_BASE_URL . $test->getPagePath() ); // set url to post to
- curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); // return into a variable
-
- $result = curl_exec ( $ch );
-
- // if we encountered an error, then say so, and return an empty string.
- if ( curl_error( $ch ) ) {
- print "\nCurl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch );
- $result = "";
- }
-
- curl_close ( $ch );
-
- return $result;
-}
-
-
-// ////////////////// HTML VALIDATION /////////////////////////
-
-/**
- * Asks the validator whether this is valid HTML, or not.
- * @param $text string
- * @return array
- */
-function validateHTML( $text ) {
-
- $params = array ( "fragment" => $text );
-
- $ch = curl_init();
-
- curl_setopt( $ch, CURLOPT_POST, 1 ); // save form using a POST
- curl_setopt( $ch, CURLOPT_POSTFIELDS, $params ); // load the POST variables
- curl_setopt( $ch, CURLOPT_URL, VALIDATOR_URL ); // set url to post to
- curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); // return into a variable
-
- $result = curl_exec ( $ch );
-
- // if we encountered an error, then log it, and exit.
- if ( curl_error( $ch ) ) {
- trigger_error( "Curl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch ) );
- print "Curl error #: " . curl_errno( $ch ) . " - " . curl_error ( $ch ) . " - exiting.\n";
- exit( 1 );
- }
-
- curl_close ( $ch );
-
- $valid = ( strpos( $result, "Failed validation" ) === false );
-
- return array( $valid, $result );
-}
-
-/**
- * Get tidy to check for no HTML errors in the output file (e.g. unescaped strings).
- * @param $name
- * @return bool
- */
-function tidyCheckFile( $name ) {
- $file = DIRECTORY . "/" . $name;
- $command = PATH_TO_TIDY . " -output /tmp/out.html -quiet $file 2>&1";
- $x = `$command`;
-
- // Look for the most interesting Tidy errors and warnings.
- if ( strpos( $x, "end of file while parsing attributes" ) !== false
- || strpos( $x, "attribute with missing trailing quote mark" ) !== false
- || strpos( $x, "missing '>' for end of tag" ) !== false
- || strpos( $x, "Error:" ) !== false ) {
- print "\nTidy found something - view details with: $command";
- return false;
- } else {
- return true;
- }
-}
-
-/**
- ** Returns whether or not an database error log file has changed in size since
- ** the last time this was run. This is used to tell if a test caused a DB error.
- * @return bool
- */
-function dbErrorLogged() {
- static $filesize;
-
- // first time running this function
- if ( !isset( $filesize ) ) {
- // create log if it does not exist
- if ( DB_ERROR_LOG_FILE && !file_exists( DB_ERROR_LOG_FILE ) ) {
- saveFile( '', DB_ERROR_LOG_FILE );
- }
- $filesize = filesize( DB_ERROR_LOG_FILE );
- return false;
- }
-
- $newsize = filesize( DB_ERROR_LOG_FILE );
- // if the log has grown, then assume the current test caused it.
- if ( $newsize != $filesize ) {
- $filesize = $newsize;
- return true;
- }
-
- return false;
-}
-
-// //////////////// TOP-LEVEL PROBLEM-FINDING FUNCTION ////////////////////////
-
-/**
- * takes a page test, and runs it and tests it for problems in the output.
- * Returns: False on finding a problem, or True on no problems being found.
- * @param $test pageTest
- * @param $testname
- * @param $can_overwrite bool
- * @return bool
- */
-function runWikiTest( pageTest $test, &$testname, $can_overwrite = false ) {
-
- // by default don't overwrite a previous test of the same name.
- while ( ! $can_overwrite && file_exists( DIRECTORY . "/" . $testname . DATA_FILE ) ) {
- $testname .= "-" . mt_rand( 0, 9 );
- }
-
- $filename = DIRECTORY . "/" . $testname . DATA_FILE;
-
- // Store the time before and after, to find slow pages.
- $before = microtime( true );
-
- // Get MediaWiki to give us the output of this test.
- $wiki_preview = wikiTestOutput( $test );
-
- $after = microtime( true );
-
- // if we received no response, then that's interesting.
- if ( $wiki_preview == "" ) {
- print "\nNo response received for: $filename";
- return false;
- }
-
- // save output HTML to file.
- $html_file = DIRECTORY . "/" . $testname . HTML_FILE;
- saveFile( $wiki_preview, $html_file );
-
- // if there were PHP errors in the output, then that's interesting too.
- if ( strpos( $wiki_preview, "<b>Warning</b>: " ) !== false
- || strpos( $wiki_preview, "<b>Fatal error</b>: " ) !== false
- || strpos( $wiki_preview, "<b>Notice</b>: " ) !== false
- || strpos( $wiki_preview, "<b>Error</b>: " ) !== false
- || strpos( $wiki_preview, "<b>Strict Standards:</b>" ) !== false
- ) {
- $error = substr( $wiki_preview, strpos( $wiki_preview, "</b>:" ) + 7, 50 );
- // Avoid probable PHP bug with bad session ids; http://bugs.php.net/bug.php?id=38224
- if ( $error != "Unknown: The session id contains illegal character" ) {
- print "\nPHP error/warning/notice in HTML output: $html_file ; $error";
- return false;
- }
- }
-
- // if there was a MediaWiki Backtrace message in the output, then that's also interesting.
- if ( strpos( $wiki_preview, "Backtrace:" ) !== false ) {
- print "\nInternal MediaWiki error in HTML output: $html_file";
- return false;
- }
-
- // if there was a Parser error comment in the output, then that's potentially interesting.
- if ( strpos( $wiki_preview, "!-- ERR" ) !== false ) {
- print "\nParser Error comment in HTML output: $html_file";
- return false;
- }
-
- // if a database error was logged, then that's definitely interesting.
- if ( dbErrorLogged() ) {
- print "\nDatabase Error logged for: $filename";
- return false;
- }
-
- // validate result
- $valid = true;
- if ( VALIDATE_ON_WEB ) {
- list ( $valid, $validator_output ) = validateHTML( $wiki_preview );
- if ( !$valid ) print "\nW3C web validation failed - view details with: html2text " . DIRECTORY . "/" . $testname . ".validator_output.html";
- }
-
- // Get tidy to check the page, unless we already know it produces non-(X)HTML output.
- if ( $test->tidyValidate() ) {
- $valid = tidyCheckFile( $testname . HTML_FILE ) && $valid;
- }
-
- // if it took more than 2 seconds to render, then it may be interesting too. (Possible DoS attack?)
- if ( ( $after - $before ) >= 2 ) {
- print "\nParticularly slow to render (" . round( $after - $before, 2 ) . " seconds): $filename";
- return false;
- }
-
- if ( $valid ) {
- // Remove temp HTML file if test was valid:
- unlink( $html_file );
- } elseif ( VALIDATE_ON_WEB ) {
- saveFile( $validator_output, DIRECTORY . "/" . $testname . ".validator_output.html" );
- }
-
- return $valid;
-}
-
-
-// ///////////////// RERUNNING OLD TESTS ///////////////////
-
-/**
- ** We keep our failed tests so that they can be rerun.
- ** This function does that retesting.
- */
-function rerunPreviousTests() {
- print "Retesting previously found problems.\n";
-
- $dir_contents = scandir ( DIRECTORY );
-
- // sort file into the order a normal person would use.
- natsort ( $dir_contents );
-
- foreach ( $dir_contents as $file ) {
-
- // if file is not a test, then skip it.
- // Note we need to escape any periods or will be treated as "any character".
- $matches = array();
- if ( !preg_match( "/(.*)" . str_replace( ".", "\.", DATA_FILE ) . "$/", $file, $matches ) ) continue;
-
- // reload the test.
- $full_path = DIRECTORY . "/" . $file;
- $test = unserialize( file_get_contents( $full_path ) );
-
- // if this is not a valid test, then skip it.
- if ( ! $test instanceof pageTest ) {
- print "\nSkipping invalid test - $full_path";
- continue;
- }
-
- // The date format is in Apache log format, which makes it easier to locate
- // which retest caused which error in the Apache logs (only happens usually if
- // apache segfaults).
- if ( !QUIET ) print "[" . date ( "D M d H:i:s Y" ) . "] Retesting $file (" . get_class( $test ) . ")";
-
- // run test
- $testname = $matches[1];
- $valid = runWikiTest( $test, $testname, true );
-
- if ( !$valid ) {
- saveTest( $test, $testname );
- if ( QUIET ) {
- print "\nTest: " . get_class( $test ) . " ; Testname: $testname\n------";
- } else {
- print "\n";
- }
- }
- else {
- if ( !QUIET ) print "\r";
- if ( DELETE_PASSED_RETESTS ) {
- $prefix = DIRECTORY . "/" . $testname;
- if ( is_file( $prefix . DATA_FILE ) ) unlink( $prefix . DATA_FILE );
- if ( is_file( $prefix . PHP_TEST ) ) unlink( $prefix . PHP_TEST );
- if ( is_file( $prefix . CURL_TEST ) ) unlink( $prefix . CURL_TEST );
- if ( is_file( $prefix . INFO_FILE ) ) unlink( $prefix . INFO_FILE );
- }
- }
- }
-
- print "\nDone retesting.\n";
-}
-
-
-// //////////////////// MAIN LOOP ////////////////////////
-
-
-// first check whether CURL is installed, because sometimes it's not.
-if ( ! function_exists( 'curl_init' ) ) {
- die( "Could not find 'curl_init' function. Is the curl extension compiled into PHP?\n" );
-}
-
-// Initialization of types. wikiFuzz doesn't have a constructor because we want to
-// access it staticly and not have any globals.
-wikiFuzz::$types = array_keys( wikiFuzz::$data );
-
-// Make directory if doesn't exist
-if ( !is_dir( DIRECTORY ) ) {
- mkdir ( DIRECTORY, 0700 );
-}
-// otherwise, we first retest the things that we have found in previous runs
-elseif ( RERUN_OLD_TESTS ) {
- rerunPreviousTests();
-}
-
-// main loop.
-$start_time = date( "U" );
-$num_errors = 0;
-if ( !QUIET ) {
- print "Beginning main loop. Results are stored in the " . DIRECTORY . " directory.\n";
- print "Press CTRL+C to stop testing.\n";
-}
-
-for ( $count = 0; true; $count++ ) {
- if ( !QUIET ) {
- // spinning progress indicator.
- switch( $count % 4 ) {
- case '0': print "\r/"; break;
- case '1': print "\r-"; break;
- case '2': print "\r\\"; break;
- case '3': print "\r|"; break;
- }
- print " $count";
- }
-
- // generate a page test to run.
- $test = selectPageTest( $count );
-
- $mins = ( date( "U" ) - $start_time ) / 60;
- if ( !QUIET && $mins > 0 ) {
- print ". $num_errors poss errors. "
- . floor( $mins ) . " mins. "
- . round ( $count / $mins, 0 ) . " tests/min. "
- . get_class( $test ); // includes the current test name.
- }
-
- // run this test against MediaWiki, and see if the output was valid.
- $testname = $count;
- $valid = runWikiTest( $test, $testname, false );
-
- // save the failed test
- if ( ! $valid ) {
- if ( QUIET ) {
- print "\nTest: " . get_class( $test ) . " ; Testname: $testname\n------";
- } else {
- print "\n";
- }
- saveTest( $test, $testname );
- $num_errors += 1;
- } elseif ( KEEP_PASSED_TESTS ) {
- // print current time, with microseconds (matches "strace" format), and the test name.
- print " " . date( "H:i:s." ) . substr( current( explode( " ", microtime() ) ), 2 ) . " " . $testname;
- saveTest( $test, $testname );
- }
-
- // stop if we have reached max number of errors.
- if ( defined( "MAX_ERRORS" ) && $num_errors >= MAX_ERRORS ) {
- break;
- }
-
- // stop if we have reached max number of mins runtime.
- if ( defined( "MAX_RUNTIME" ) && $mins >= MAX_RUNTIME ) {
- break;
- }
-}
diff --git a/maintenance/generateJsonI18n.php b/maintenance/generateJsonI18n.php
new file mode 100644
index 00000000..22d99405
--- /dev/null
+++ b/maintenance/generateJsonI18n.php
@@ -0,0 +1,287 @@
+<?php
+
+/**
+ * Convert a PHP messages file to a set of JSON messages files.
+ *
+ * Usage:
+ * php generateJsonI18n.php ExtensionName.i18n.php i18n/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+/**
+ * Maintenance script to generate JSON i18n files from a PHP i18n file.
+ *
+ * @ingroup Maintenance
+ */
+class GenerateJsonI18n extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Build JSON messages files from a PHP messages file";
+
+ $this->addArg( 'phpfile', 'PHP file defining a $messages array', false );
+ $this->addArg( 'jsondir', 'Directory to write JSON files to', false );
+ $this->addOption( 'langcode', 'Language code; only needed for converting core i18n files',
+ false, true );
+ $this->addOption( 'extension', 'Perform default conversion on an extension',
+ false, true );
+ $this->addOption( 'shim-only', 'Only create or update the backward-compatibility shim' );
+ $this->addOption( 'supplementary', 'Find supplementary i18n files in subdirs and convert those',
+ false, false );
+ }
+
+ public function execute() {
+ global $IP;
+
+ $phpfile = $this->getArg( 0 );
+ $jsondir = $this->getArg( 1 );
+ $extension = $this->getOption( 'extension' );
+ $convertSupplementaryI18nFiles = $this->hasOption( 'supplementary' );
+
+ if ( $extension ) {
+ if ( $phpfile ) {
+ $this->error( "The phpfile is already specified, conflicts with --extension.\n", 1 );
+ }
+ $phpfile = "$IP/extensions/$extension/$extension.i18n.php";
+ }
+
+ if ( !$phpfile ) {
+ $this->error( "I'm here for an argument!\n" );
+ $this->maybeHelp( true );
+ // dies.
+ }
+
+ if ( $convertSupplementaryI18nFiles ) {
+ if ( is_readable( $phpfile ) ) {
+ $this->transformI18nFile( $phpfile, $jsondir );
+ } else {
+ // This is non-fatal because we might want to continue searching for
+ // i18n files in subdirs even if the extension does not include a
+ // primary i18n.php.
+ $this->error( "Warning: no primary i18n file was found." );
+ }
+ $this->output( "Searching for supplementary i18n files...\n" );
+ $dir_iterator = new RecursiveDirectoryIterator( dirname( $phpfile ) );
+ $iterator = new RecursiveIteratorIterator(
+ $dir_iterator, RecursiveIteratorIterator::LEAVES_ONLY );
+ foreach ( $iterator as $path => $fileObject ) {
+ if ( fnmatch( "*.i18n.php", $fileObject->getFilename() ) ) {
+ $this->output( "Converting $path.\n" );
+ $this->transformI18nFile( $path );
+ }
+ }
+ } else {
+ // Just convert the primary i18n file.
+ $this->transformI18nFile( $phpfile, $jsondir );
+ }
+ }
+
+ public function transformI18nFile( $phpfile, $jsondir = null ) {
+ if ( !$jsondir ) {
+ // Assume the json directory should be in the same directory as the
+ // .i18n.php file.
+ $jsondir = dirname( $phpfile ) . "/i18n";
+ }
+ if ( !is_dir( $jsondir ) ) {
+ $this->output( "Creating directory $jsondir.\n" );
+ $success = mkdir( $jsondir );
+ if ( !$success ) {
+ $this->error( "Could not create directory $jsondir\n", 1 );
+ }
+ }
+
+ if ( $this->hasOption( 'shim-only' ) ) {
+ $this->shimOnly( $phpfile, $jsondir );
+
+ return;
+ }
+
+ if ( $jsondir === null ) {
+ $this->error( 'Argument [jsondir] is required unless --shim-only is specified.' );
+ $this->maybeHelp( true );
+ }
+
+ if ( !is_readable( $phpfile ) ) {
+ $this->error( "Error reading $phpfile\n", 1 );
+ }
+ include $phpfile;
+ $phpfileContents = file_get_contents( $phpfile );
+
+ if ( !isset( $messages ) ) {
+ $this->error( "PHP file $phpfile does not define \$messages array\n", 1 );
+ }
+
+ $extensionStyle = true;
+ if ( !isset( $messages['en'] ) || !is_array( $messages['en'] ) ) {
+ if ( !$this->hasOption( 'langcode' ) ) {
+ $this->error( "PHP file $phpfile does not set language codes, --langcode " .
+ "is required.\n", 1 );
+ }
+ $extensionStyle = false;
+ $langcode = $this->getOption( 'langcode' );
+ $messages = array( $langcode => $messages );
+ } elseif ( $this->hasOption( 'langcode' ) ) {
+ $this->output( "Warning: --langcode option set but will not be used.\n" );
+ }
+
+ foreach ( $messages as $langcode => $langmsgs ) {
+ $authors = $this->getAuthorsFromComment( $this->findCommentBefore(
+ $extensionStyle ? "\$messages['$langcode'] =" : '$messages =',
+ $phpfileContents
+ ) );
+ // Make sure the @metadata key is the first key in the output
+ $langmsgs = array_merge(
+ array( '@metadata' => array( 'authors' => $authors ) ),
+ $langmsgs
+ );
+
+ $jsonfile = "$jsondir/$langcode.json";
+ $success = file_put_contents(
+ $jsonfile,
+ FormatJson::encode( $langmsgs, "\t", FormatJson::ALL_OK ) . "\n"
+ );
+ if ( $success === false ) {
+ $this->error( "FAILED to write $jsonfile", 1 );
+ }
+ $this->output( "$jsonfile\n" );
+ }
+
+ if ( !$this->hasOption( 'langcode' ) ) {
+ $shim = $this->doShim( $jsondir );
+ file_put_contents( $phpfile, $shim );
+ }
+
+ $this->output( "All done.\n" );
+ $this->output( "Also add \$wgMessagesDirs['YourExtension'] = __DIR__ . '/i18n';\n" );
+ }
+
+ protected function shimOnly( $phpfile, $jsondir ) {
+ if ( file_exists( $phpfile ) ) {
+ if ( !is_readable( $phpfile ) ) {
+ $this->error( "Error reading $phpfile\n", 1 );
+ }
+
+ $phpfileContents = file_get_contents( $phpfile );
+ $m = array();
+ if ( !preg_match( '!"/([^"$]+)/\$csCode.json";!', $phpfileContents, $m ) ) {
+ $this->error( "Cannot recognize $phpfile as a shim.\n", 1 );
+ }
+
+ if ( $jsondir === null ) {
+ $jsondir = $m[1];
+ }
+
+ $this->output( "Updating existing shim $phpfile\n" );
+ } elseif ( $jsondir === null ) {
+ $this->error( "$phpfile does not exist.\n" .
+ "Argument [jsondir] is required in order to create a new shim.\n", 1 );
+ } else {
+ $this->output( "Creating new shim $phpfile\n" );
+ }
+
+ $shim = $this->doShim( $jsondir );
+ file_put_contents( $phpfile, $shim );
+ $this->output( "All done.\n" );
+ }
+
+ protected function doShim( $jsondir ) {
+ $shim = <<<'PHP'
+<?php
+/**
+ * This is a backwards-compatibility shim, generated by:
+ * https://git.wikimedia.org/blob/mediawiki%2Fcore.git/HEAD/maintenance%2FgenerateJsonI18n.php
+ *
+ * Beginning with MediaWiki 1.23, translation strings are stored in json files,
+ * and the EXTENSION.i18n.php file only exists to provide compatibility with
+ * older releases of MediaWiki. For more information about this migration, see:
+ * https://www.mediawiki.org/wiki/Requests_for_comment/Localisation_format
+ *
+ * This shim maintains compatibility back to MediaWiki 1.17.
+ */
+$messages = array();
+if ( !function_exists( '{{FUNC}}' ) ) {
+ function {{FUNC}}( $cache, $code, &$cachedData ) {
+ $codeSequence = array_merge( array( $code ), $cachedData['fallbackSequence'] );
+ foreach ( $codeSequence as $csCode ) {
+ $fileName = dirname( __FILE__ ) . "/{{OUT}}/$csCode.json";
+ if ( is_readable( $fileName ) ) {
+ $data = FormatJson::decode( file_get_contents( $fileName ), true );
+ foreach ( array_keys( $data ) as $key ) {
+ if ( $key === '' || $key[0] === '@' ) {
+ unset( $data[$key] );
+ }
+ }
+ $cachedData['messages'] = array_merge( $data, $cachedData['messages'] );
+ }
+
+ $cachedData['deps'][] = new FileDependency( $fileName );
+ }
+ return true;
+ }
+
+ $GLOBALS['wgHooks']['LocalisationCacheRecache'][] = '{{FUNC}}';
+}
+
+PHP;
+
+ $jsondir = str_replace( '\\', '/', $jsondir );
+ $shim = str_replace( '{{OUT}}', $jsondir, $shim );
+ $shim = str_replace( '{{FUNC}}', 'wfJsonI18nShim' . wfRandomString( 16 ), $shim );
+
+ return $shim;
+ }
+
+ /**
+ * Find the documentation comment immediately before a given search string
+ * @param string $needle String to search for
+ * @param string $haystack String to search in
+ * @return string Substring of $haystack starting at '/**' ending right before $needle, or empty
+ */
+ protected function findCommentBefore( $needle, $haystack ) {
+ $needlePos = strpos( $haystack, $needle );
+ if ( $needlePos === false ) {
+ return '';
+ }
+ // Need to pass a negative offset to strrpos() so it'll search backwards from the
+ // offset
+ $startPos = strrpos( $haystack, '/**', $needlePos - strlen( $haystack ) );
+ if ( $startPos === false ) {
+ return '';
+ }
+
+ return substr( $haystack, $startPos, $needlePos - $startPos );
+ }
+
+ /**
+ * Get an array of author names from a documentation comment containing @author declarations.
+ * @param string $comment Documentation comment
+ * @return array Array of author names (strings)
+ */
+ protected function getAuthorsFromComment( $comment ) {
+ $matches = null;
+ preg_match_all( '/@author (.*?)$/m', $comment, $matches );
+
+ return $matches && $matches[1] ? $matches[1] : array();
+ }
+}
+
+$maintClass = "GenerateJsonI18n";
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/generateSitemap.php b/maintenance/generateSitemap.php
index 0b21a1fe..1930a22a 100644
--- a/maintenance/generateSitemap.php
+++ b/maintenance/generateSitemap.php
@@ -63,7 +63,8 @@ class GenerateSitemap extends Maintenance {
public $fspath;
/**
- * The URL path to prepend to filenames in the index; should resolve to the same directory as $fspath
+ * The URL path to prepend to filenames in the index;
+ * should resolve to the same directory as $fspath.
*
* @var string
*/
@@ -125,7 +126,6 @@ class GenerateSitemap extends Maintenance {
*/
public $findex;
-
/**
* A resource pointing to a sitemap file
*
@@ -146,11 +146,32 @@ class GenerateSitemap extends Maintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Creates a sitemap for the site";
- $this->addOption( 'fspath', 'The file system path to save to, e.g. /tmp/sitemap; defaults to current directory', false, true );
- $this->addOption( 'urlpath', 'The URL path corresponding to --fspath, prepended to filenames in the index; defaults to an empty string', false, true );
- $this->addOption( 'compress', 'Compress the sitemap files, can take value yes|no, default yes', false, true );
+ $this->addOption(
+ 'fspath',
+ 'The file system path to save to, e.g. /tmp/sitemap; defaults to current directory',
+ false,
+ true
+ );
+ $this->addOption(
+ 'urlpath',
+ 'The URL path corresponding to --fspath, prepended to filenames in the index; '
+ . 'defaults to an empty string',
+ false,
+ true
+ );
+ $this->addOption(
+ 'compress',
+ 'Compress the sitemap files, can take value yes|no, default yes',
+ false,
+ true
+ );
$this->addOption( 'skip-redirects', 'Do not include redirecting articles in the sitemap' );
- $this->addOption( 'identifier', 'What site identifier to use for the wiki, defaults to $wgDBname', false, true );
+ $this->addOption(
+ 'identifier',
+ 'What site identifier to use for the wiki, defaults to $wgDBname',
+ false,
+ true
+ );
}
/**
@@ -219,13 +240,10 @@ class GenerateSitemap extends Maintenance {
/**
* Create directory if it does not exist and return pathname with a trailing slash
- * @param $fspath string
+ * @param string $fspath
* @return null|string
*/
private static function init_path( $fspath ) {
- if ( !isset( $fspath ) ) {
- return null;
- }
# Create directory if needed
if ( $fspath && !is_dir( $fspath ) ) {
wfMkdirParents( $fspath, null, __METHOD__ ) or die( "Can not create directory $fspath.\n" );
@@ -242,6 +260,7 @@ class GenerateSitemap extends Maintenance {
global $wgSitemapNamespaces;
if ( is_array( $wgSitemapNamespaces ) ) {
$this->namespaces = $wgSitemapNamespaces;
+
return;
}
@@ -263,11 +282,13 @@ class GenerateSitemap extends Maintenance {
/**
* Get the priority of a given namespace
*
- * @param $namespace Integer: the namespace to get the priority for
- * @return String
+ * @param int $namespace The namespace to get the priority for
+ * @return string
*/
function priority( $namespace ) {
- return isset( $this->priorities[$namespace] ) ? $this->priorities[$namespace] : $this->guessPriority( $namespace );
+ return isset( $this->priorities[$namespace] )
+ ? $this->priorities[$namespace]
+ : $this->guessPriority( $namespace );
}
/**
@@ -275,17 +296,19 @@ class GenerateSitemap extends Maintenance {
* default priority for the namespace, varies depending on whether it's
* a talkpage or not.
*
- * @param $namespace Integer: the namespace to get the priority for
- * @return String
+ * @param int $namespace The namespace to get the priority for
+ * @return string
*/
function guessPriority( $namespace ) {
- return MWNamespace::isSubject( $namespace ) ? $this->priorities[self::GS_MAIN] : $this->priorities[self::GS_TALK];
+ return MWNamespace::isSubject( $namespace )
+ ? $this->priorities[self::GS_MAIN]
+ : $this->priorities[self::GS_TALK];
}
/**
* Return a database resolution of all the pages in a given namespace
*
- * @param $namespace Integer: limit the query to this namespace
+ * @param int $namespace Limit the query to this namespace
* @return Resource
*/
function getPageRes( $namespace ) {
@@ -318,14 +341,17 @@ class GenerateSitemap extends Maintenance {
$fns = $wgContLang->getFormattedNsText( $namespace );
$this->output( "$namespace ($fns)\n" );
- $skippedRedirects = 0; // Number of redirects skipped for that namespace
+ $skippedRedirects = 0; // Number of redirects skipped for that namespace
foreach ( $res as $row ) {
if ( $this->skipRedirects && $row->page_is_redirect ) {
$skippedRedirects++;
continue;
}
- if ( $i++ === 0 || $i === $this->url_limit + 1 || $length + $this->limit[1] + $this->limit[2] > $this->size_limit ) {
+ if ( $i++ === 0
+ || $i === $this->url_limit + 1
+ || $length + $this->limit[1] + $this->limit[2] > $this->size_limit
+ ) {
if ( $this->file !== false ) {
$this->write( $this->file, $this->closeFile() );
$this->close( $this->file );
@@ -350,7 +376,11 @@ class GenerateSitemap extends Maintenance {
if ( $vCode == $wgContLang->getCode() ) {
continue; // we don't want default variant
}
- $entry = $this->fileEntry( $title->getCanonicalURL( '', $vCode ), $date, $this->priority( $namespace ) );
+ $entry = $this->fileEntry(
+ $title->getCanonicalURL( '', $vCode ),
+ $date,
+ $this->priority( $namespace )
+ );
$length += strlen( $entry );
$this->write( $this->file, $entry );
}
@@ -373,18 +403,25 @@ class GenerateSitemap extends Maintenance {
/**
* gzopen() / fopen() wrapper
*
- * @return Resource
+ * @param string $file
+ * @param string $flags
+ * @return resource
*/
function open( $file, $flags ) {
$resource = $this->compress ? gzopen( $file, $flags ) : fopen( $file, $flags );
if ( $resource === false ) {
- throw new MWException( __METHOD__ . " error opening file $file with flags $flags. Check permissions?" );
+ throw new MWException( __METHOD__
+ . " error opening file $file with flags $flags. Check permissions?" );
}
+
return $resource;
}
/**
* gzwrite() / fwrite() wrapper
+ *
+ * @param resource $handle
+ * @param string $str
*/
function write( &$handle, $str ) {
if ( $handle === true || $handle === false ) {
@@ -399,6 +436,8 @@ class GenerateSitemap extends Maintenance {
/**
* gzclose() / fclose() wrapper
+ *
+ * @param resource $handle
*/
function close( &$handle ) {
if ( $this->compress ) {
@@ -411,12 +450,13 @@ class GenerateSitemap extends Maintenance {
/**
* Get a sitemap filename
*
- * @param $namespace Integer: the namespace
- * @param $count Integer: the count
- * @return String
+ * @param int $namespace The namespace
+ * @param int $count The count
+ * @return string
*/
function sitemapFilename( $namespace, $count ) {
$ext = $this->compress ? '.gz' : '';
+
return "sitemap-{$this->identifier}-NS_$namespace-$count.xml$ext";
}
@@ -432,7 +472,7 @@ class GenerateSitemap extends Maintenance {
/**
* Return the XML schema being used
*
- * @return String
+ * @return string
*/
function xmlSchema() {
return 'http://www.sitemaps.org/schemas/sitemap/0.9';
@@ -441,7 +481,7 @@ class GenerateSitemap extends Maintenance {
/**
* Return the XML required to open a sitemap index file
*
- * @return String
+ * @return string
*/
function openIndex() {
return $this->xmlHead() . '<sitemapindex xmlns="' . $this->xmlSchema() . '">' . "\n";
@@ -450,8 +490,8 @@ class GenerateSitemap extends Maintenance {
/**
* Return the XML for a single sitemap indexfile entry
*
- * @param $filename String: the filename of the sitemap file
- * @return String
+ * @param string $filename The filename of the sitemap file
+ * @return string
*/
function indexEntry( $filename ) {
return
@@ -464,7 +504,7 @@ class GenerateSitemap extends Maintenance {
/**
* Return the XML required to close a sitemap index file
*
- * @return String
+ * @return string
*/
function closeIndex() {
return "</sitemapindex>\n";
@@ -473,7 +513,7 @@ class GenerateSitemap extends Maintenance {
/**
* Return the XML required to open a sitemap file
*
- * @return String
+ * @return string
*/
function openFile() {
return $this->xmlHead() . '<urlset xmlns="' . $this->xmlSchema() . '">' . "\n";
@@ -482,10 +522,10 @@ class GenerateSitemap extends Maintenance {
/**
* Return the XML for a single sitemap entry
*
- * @param $url String: an RFC 2396 compliant URL
- * @param $date String: a ISO 8601 date
- * @param $priority String: a priority indicator, 0.0 - 1.0 inclusive with a 0.1 stepsize
- * @return String
+ * @param string $url An RFC 2396 compliant URL
+ * @param string $date A ISO 8601 date
+ * @param string $priority A priority indicator, 0.0 - 1.0 inclusive with a 0.1 stepsize
+ * @return string
*/
function fileEntry( $url, $date, $priority ) {
return
@@ -500,7 +540,7 @@ class GenerateSitemap extends Maintenance {
/**
* Return the XML required to close sitemap file
*
- * @return String
+ * @return string
*/
function closeFile() {
return "</urlset>\n";
@@ -508,6 +548,8 @@ class GenerateSitemap extends Maintenance {
/**
* Populate $this->limit
+ *
+ * @param int $namespace
*/
function generateLimit( $namespace ) {
// bug 17961: make a title with the longest possible URL in this namespace
@@ -515,7 +557,11 @@ class GenerateSitemap extends Maintenance {
$this->limit = array(
strlen( $this->openFile() ),
- strlen( $this->fileEntry( $title->getCanonicalURL(), wfTimestamp( TS_ISO_8601, wfTimestamp() ), $this->priority( $namespace ) ) ),
+ strlen( $this->fileEntry(
+ $title->getCanonicalURL(),
+ wfTimestamp( TS_ISO_8601, wfTimestamp() ),
+ $this->priority( $namespace )
+ ) ),
strlen( $this->closeFile() )
);
}
diff --git a/maintenance/getConfiguration.php b/maintenance/getConfiguration.php
index 5a5eb587..d5f68346 100644
--- a/maintenance/getConfiguration.php
+++ b/maintenance/getConfiguration.php
@@ -63,7 +63,7 @@ class GetConfiguration extends Maintenance {
$format = strtolower( $this->getOption( 'format', 'PHP' ) );
$validFormat = in_array( $format, self::$outFormats );
- if ( ! $validFormat ) {
+ if ( !$validFormat ) {
$this->error( "--format set to an unrecognized format", 0 );
$error_out = true;
}
@@ -87,11 +87,11 @@ class GetConfiguration extends Maintenance {
public function finalSetup() {
parent::finalSetup();
- $this->regex = $this->getOption( 'regex' ) ? : $this->getOption( 'iregex' );
+ $this->regex = $this->getOption( 'regex' ) ?: $this->getOption( 'iregex' );
if ( $this->regex ) {
$this->regex = '/' . $this->regex . '/';
if ( $this->hasOption( 'iregex' ) ) {
- $this->regex .= 'i'; # case insensitive regex
+ $this->regex .= 'i'; # case insensitive regex
}
}
@@ -115,7 +115,7 @@ class GetConfiguration extends Maintenance {
$res = array();
# Sane default: dump any wg / wmg variable
- if ( ! $this->regex && ! $this->getOption( 'settings' ) ) {
+ if ( !$this->regex && !$this->getOption( 'settings' ) ) {
$this->regex = '/^wm?g/';
}
@@ -165,7 +165,7 @@ class GetConfiguration extends Maintenance {
protected function formatVarDump( $res ) {
$ret = '';
foreach ( $res as $key => $value ) {
- ob_start(); # intercept var_dump() output
+ ob_start(); # intercept var_dump() output
print "\${$key} = ";
var_dump( $value );
# grab var_dump() output and discard it from the output buffer
@@ -182,10 +182,12 @@ class GetConfiguration extends Maintenance {
return false;
}
}
+
return true;
} elseif ( is_scalar( $value ) ) {
return true;
}
+
return false;
}
}
diff --git a/maintenance/getSlaveServer.php b/maintenance/getSlaveServer.php
index d618825f..68c19439 100644
--- a/maintenance/getSlaveServer.php
+++ b/maintenance/getSlaveServer.php
@@ -34,6 +34,7 @@ class GetSlaveServer extends Maintenance {
$this->addOption( "group", "Query group to check specifically" );
$this->mDescription = "Report the hostname of a slave server";
}
+
public function execute() {
global $wgAllDBsAreLocalhost;
if ( $wgAllDBsAreLocalhost ) {
diff --git a/maintenance/getText.php b/maintenance/getText.php
index 9c4bdfb8..7d7c1cc4 100644
--- a/maintenance/getText.php
+++ b/maintenance/getText.php
@@ -52,7 +52,10 @@ class GetTextMaint extends Maintenance {
$titleText = $title->getPrefixedText();
$this->error( "Page $titleText does not exist.\n", true );
}
- $content = $rev->getContent( $this->hasOption( 'show-private' ) ? Revision::RAW : Revision::FOR_PUBLIC );
+ $content = $rev->getContent( $this->hasOption( 'show-private' )
+ ? Revision::RAW
+ : Revision::FOR_PUBLIC );
+
if ( $content === false ) {
$titleText = $title->getPrefixedText();
$this->error( "Couldn't extract the text from $titleText.\n", true );
diff --git a/maintenance/importDump.php b/maintenance/importDump.php
index 1f47cf12..1f75bccf 100644
--- a/maintenance/importDump.php
+++ b/maintenance/importDump.php
@@ -3,7 +3,7 @@
* Import XML dump files into the current wiki.
*
* Copyright © 2005 Brion Vibber <brion@pobox.com>
- * http://www.mediawiki.org/
+ * https://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -42,8 +42,12 @@ class BackupReader extends Maintenance {
function __construct() {
parent::__construct();
- $gz = in_array( 'compress.zlib', stream_get_wrappers() ) ? 'ok' : '(disabled; requires PHP zlib module)';
- $bz2 = in_array( 'compress.bzip2', stream_get_wrappers() ) ? 'ok' : '(disabled; requires PHP bzip2 module)';
+ $gz = in_array( 'compress.zlib', stream_get_wrappers() )
+ ? 'ok'
+ : '(disabled; requires PHP zlib module)';
+ $bz2 = in_array( 'compress.bzip2', stream_get_wrappers() )
+ ? 'ok'
+ : '(disabled; requires PHP bzip2 module)';
$this->mDescription = <<<TEXT
This script reads pages from an XML file as produced from Special:Export or
@@ -56,7 +60,7 @@ Compressed XML files may be read directly:
Note that for very large data sets, importDump.php may be slow; there are
alternate methods which can be much faster for full site restoration:
-<http://www.mediawiki.org/wiki/Manual:Importing_XML_dumps>
+<https://www.mediawiki.org/wiki/Manual:Importing_XML_dumps>
TEXT;
$this->stderr = fopen( "php://stderr", "wt" );
$this->addOption( 'report',
@@ -67,7 +71,10 @@ TEXT;
$this->addOption( 'dry-run', 'Parse dump without actually importing pages' );
$this->addOption( 'debug', 'Output extra verbose debug information' );
$this->addOption( 'uploads', 'Process file upload data if included (experimental)' );
- $this->addOption( 'no-updates', 'Disable link table updates. Is faster but leaves the wiki in an inconsistent state' );
+ $this->addOption(
+ 'no-updates',
+ 'Disable link table updates. Is faster but leaves the wiki in an inconsistent state'
+ );
$this->addOption( 'image-base-path', 'Import files from a specified path', false, true );
$this->addArg( 'file', 'Dump file to import [else use stdin]', false );
}
@@ -104,6 +111,7 @@ TEXT;
function setNsfilter( array $namespaces ) {
if ( count( $namespaces ) == 0 ) {
$this->nsFilter = false;
+
return;
}
$this->nsFilter = array_unique( array_map( array( $this, 'getNsIndex' ), $namespaces ) );
@@ -122,7 +130,7 @@ TEXT;
}
/**
- * @param $obj Title|Revision
+ * @param Title|Revision $obj
* @return bool
*/
private function skippedNamespace( $obj ) {
@@ -133,9 +141,9 @@ TEXT;
} elseif ( $obj instanceof WikiRevision ) {
$ns = $obj->title->getNamespace();
} else {
- echo wfBacktrace();
- $this->error( "Cannot get namespace of object in " . __METHOD__, true );
+ throw new MWException( "Cannot get namespace of object in " . __METHOD__ );
}
+
return is_array( $this->nsFilter ) && !in_array( $ns, $this->nsFilter );
}
@@ -144,13 +152,13 @@ TEXT;
}
/**
- * @param $rev Revision
- * @return mixed
+ * @param Revision $rev
*/
function handleRevision( $rev ) {
$title = $rev->getTitle();
if ( !$title ) {
$this->progress( "Got bogus revision with null title!" );
+
return;
}
@@ -167,13 +175,13 @@ TEXT;
}
/**
- * @param $revision Revision
+ * @param Revision $revision
* @return bool
*/
function handleUpload( $revision ) {
if ( $this->uploads ) {
if ( $this->skippedNamespace( $revision ) ) {
- return;
+ return false;
}
$this->uploadCount++;
// $this->report();
@@ -183,9 +191,12 @@ TEXT;
// bluuuh hack
// call_user_func( $this->uploadCallback, $revision );
$dbw = wfGetDB( DB_MASTER );
+
return $dbw->deadlockLoop( array( $revision, 'importUpload' ) );
}
}
+
+ return false;
}
function handleLogItem( $rev ) {
@@ -242,6 +253,7 @@ TEXT;
}
$file = fopen( $filename, 'rt' );
+
return $this->importFromHandle( $file );
}
@@ -250,6 +262,7 @@ TEXT;
if ( self::posix_isatty( $file ) ) {
$this->maybeHelp( true );
}
+
return $this->importFromHandle( $file );
}
diff --git a/maintenance/importImages.inc b/maintenance/importImages.inc
index 5ae6d6be..b803e3da 100644
--- a/maintenance/importImages.inc
+++ b/maintenance/importImages.inc
@@ -26,10 +26,10 @@
/**
* Search a directory for files with one of a set of extensions
*
- * @param $dir string Path to directory to search
- * @param $exts Array of extensions to search for
- * @param $recurse Bool Search subdirectories recursively
- * @return mixed Array of filenames on success, or false on failure
+ * @param string $dir Path to directory to search
+ * @param array $exts Array of extensions to search for
+ * @param bool $recurse Search subdirectories recursively
+ * @return array|bool Array of filenames on success, or false on failure
*/
function findFiles( $dir, $exts, $recurse = false ) {
if ( is_dir( $dir ) ) {
@@ -46,6 +46,7 @@ function findFiles( $dir, $exts, $recurse = false ) {
$files = array_merge( $files, findFiles( $dir . '/' . $file, $exts, true ) );
}
}
+
return $files;
} else {
return array();
@@ -58,14 +59,15 @@ function findFiles( $dir, $exts, $recurse = false ) {
/**
* Split a filename into filename and extension
*
- * @param $filename string Filename
+ * @param string $filename Filename
* @return array
*/
function splitFilename( $filename ) {
$parts = explode( '.', $filename );
- $ext = $parts[ count( $parts ) - 1 ];
- unset( $parts[ count( $parts ) - 1 ] );
+ $ext = $parts[count( $parts ) - 1];
+ unset( $parts[count( $parts ) - 1] );
$fname = implode( '.', $parts );
+
return array( $fname, $ext );
}
@@ -78,10 +80,10 @@ function splitFilename( $filename ) {
* files for acme.foo.bar and the extension ".txt". With $maxStrip = 2,
* acme.txt would also be acceptable.
*
- * @param $file string base path
- * @param $auxExtension string the extension to be appended to the base path
- * @param $maxStrip int the maximum number of extensions to strip from the base path (default: 1)
- * @return string or false
+ * @param string $file Base path
+ * @param string $auxExtension The extension to be appended to the base path
+ * @param int $maxStrip The maximum number of extensions to strip from the base path (default: 1)
+ * @return string|bool
*/
function findAuxFile( $file, $auxExtension, $maxStrip = 1 ) {
if ( strpos( $auxExtension, '.' ) !== 0 ) {
@@ -110,9 +112,11 @@ function findAuxFile( $file, $auxExtension, $maxStrip = 1 ) {
return false;
}
-# FIXME: Access the api in a saner way and performing just one query (preferably batching files too).
+# @todo FIXME: Access the api in a saner way and performing just one query
+# (preferably batching files too).
function getFileCommentFromSourceWiki( $wiki_host, $file ) {
- $url = $wiki_host . '/api.php?action=query&format=xml&titles=File:' . rawurlencode( $file ) . '&prop=imageinfo&&iiprop=comment';
+ $url = $wiki_host . '/api.php?action=query&format=xml&titles=File:'
+ . rawurlencode( $file ) . '&prop=imageinfo&&iiprop=comment';
$body = Http::get( $url );
if ( preg_match( '#<ii comment="([^"]*)" />#', $body, $matches ) == 0 ) {
return false;
@@ -122,7 +126,8 @@ function getFileCommentFromSourceWiki( $wiki_host, $file ) {
}
function getFileUserFromSourceWiki( $wiki_host, $file ) {
- $url = $wiki_host . '/api.php?action=query&format=xml&titles=File:' . rawurlencode( $file ) . '&prop=imageinfo&&iiprop=user';
+ $url = $wiki_host . '/api.php?action=query&format=xml&titles=File:'
+ . rawurlencode( $file ) . '&prop=imageinfo&&iiprop=user';
$body = Http::get( $url );
if ( preg_match( '#<ii user="([^"]*)" />#', $body, $matches ) == 0 ) {
return false;
diff --git a/maintenance/importImages.php b/maintenance/importImages.php
index 54fd4e2d..ae70441f 100644
--- a/maintenance/importImages.php
+++ b/maintenance/importImages.php
@@ -4,7 +4,8 @@
* using the web-based interface.
*
* "Smart import" additions:
- * - aim: preserve the essential metadata (user, description) when importing medias from an existing wiki
+ * - aim: preserve the essential metadata (user, description) when importing media
+ * files from an existing wiki.
* - process:
* - interface with the source wiki, don't use bare files only (see --source-wiki-url).
* - fetch metadata from source wiki for each file to import.
@@ -87,16 +88,24 @@ if ( isset( $options['check-userblock'] ) ) {
}
# Get --from
-$from = @$options['from'];
+wfSuppressWarnings();
+$from = $options['from'];
+wfRestoreWarnings();
# Get sleep time.
-$sleep = @$options['sleep'];
+wfSuppressWarnings();
+$sleep = $options['sleep'];
+wfRestoreWarnings();
+
if ( $sleep ) {
$sleep = (int)$sleep;
}
# Get limit number
-$limit = @$options['limit'];
+wfSuppressWarnings();
+$limit = $options['limit'];
+wfRestoreWarnings();
+
if ( $limit ) {
$limit = (int)$limit;
}
@@ -167,7 +176,8 @@ if ( $count > 0 ) {
} else {
if ( isset( $options['skip-dupes'] ) ) {
$repo = $image->getRepo();
- $sha1 = File::sha1Base36( $file ); # XXX: we end up calculating this again when actually uploading. that sucks.
+ # XXX: we end up calculating this again when actually uploading. that sucks.
+ $sha1 = FSFile::getSha1Base36FromPath( $file );
$dupes = $repo->findBySha1( $sha1 );
@@ -210,7 +220,8 @@ if ( $count > 0 ) {
if ( $commentExt ) {
$f = findAuxFile( $file, $commentExt );
if ( !$f ) {
- echo " No comment file with extension {$commentExt} found for {$file}, using default comment. ";
+ echo " No comment file with extension {$commentExt} found "
+ . "for {$file}, using default comment. ";
} else {
$commentText = file_get_contents( $f );
if ( !$commentText ) {
@@ -254,7 +265,13 @@ if ( $count > 0 ) {
if ( isset( $options['dry'] ) ) {
echo "done.\n";
- } elseif ( $image->recordUpload2( $archive->value, $summary, $commentText, $props, $timestamp ) ) {
+ } elseif ( $image->recordUpload2(
+ $archive->value,
+ $summary,
+ $commentText,
+ $props,
+ $timestamp
+ ) ) {
# We're done!
echo "done.\n";
@@ -273,25 +290,24 @@ if ( $count > 0 ) {
}
if ( $doProtect ) {
- # Protect the file
- echo "\nWaiting for slaves...\n";
- // Wait for slaves.
- sleep( 2.0 ); # Why this sleep?
- wfWaitForSlaves();
-
- echo "\nSetting image restrictions ... ";
-
- $cascade = false;
- $restrictions = array();
- foreach ( $title->getRestrictionTypes() as $type ) {
- $restrictions[$type] = $protectLevel;
- }
+ # Protect the file
+ echo "\nWaiting for slaves...\n";
+ // Wait for slaves.
+ sleep( 2.0 ); # Why this sleep?
+ wfWaitForSlaves();
+
+ echo "\nSetting image restrictions ... ";
+
+ $cascade = false;
+ $restrictions = array();
+ foreach ( $title->getRestrictionTypes() as $type ) {
+ $restrictions[$type] = $protectLevel;
+ }
- $page = WikiPage::factory( $title );
- $status = $page->doUpdateRestrictions( $restrictions, array(), $cascade, '', $user );
- echo ( $status->isOK() ? 'done' : 'failed' ) . "\n";
+ $page = WikiPage::factory( $title );
+ $status = $page->doUpdateRestrictions( $restrictions, array(), $cascade, '', $user );
+ echo ( $status->isOK() ? 'done' : 'failed' ) . "\n";
}
-
} else {
echo "failed. (at recordUpload stage)\n";
$svar = 'failed';
@@ -311,14 +327,21 @@ if ( $count > 0 ) {
# Print out some statistics
echo "\n";
- foreach ( array( 'count' => 'Found', 'limit' => 'Limit', 'ignored' => 'Ignored',
- 'added' => 'Added', 'skipped' => 'Skipped', 'overwritten' => 'Overwritten',
- 'failed' => 'Failed' ) as $var => $desc ) {
+ foreach (
+ array(
+ 'count' => 'Found',
+ 'limit' => 'Limit',
+ 'ignored' => 'Ignored',
+ 'added' => 'Added',
+ 'skipped' => 'Skipped',
+ 'overwritten' => 'Overwritten',
+ 'failed' => 'Failed'
+ ) as $var => $desc
+ ) {
if ( $$var > 0 ) {
echo "{$desc}: {$$var}\n";
}
}
-
} else {
echo "No suitable files could be found for import.\n";
}
@@ -337,28 +360,37 @@ USAGE: php importImages.php [options] <dir>
<dir> : Path to the directory containing images to be imported
Options:
---extensions=<exts> Comma-separated list of allowable extensions, defaults to \$wgFileExtensions
---overwrite Overwrite existing images with the same name (default is to skip them)
---limit=<num> Limit the number of images to process. Ignored or skipped images are not counted.
---from=<name> Ignore all files until the one with the given name. Useful for resuming
- aborted imports. <name> should be the file's canonical database form.
---skip-dupes Skip images that were already uploaded under a different name (check SHA1)
---search-recursively Search recursively for files in subdirectories
+--extensions=<exts> Comma-separated list of allowable extensions, defaults
+ to \$wgFileExtensions.
+--overwrite Overwrite existing images with the same name (default
+ is to skip them).
+--limit=<num> Limit the number of images to process. Ignored or
+ skipped images are not counted.
+--from=<name> Ignore all files until the one with the given name.
+ Useful for resuming aborted imports. <name> should be
+ the file's canonical database form.
+--skip-dupes Skip images that were already uploaded under a different
+ name (check SHA1).
+--search-recursively Search recursively for files in subdirectories.
--sleep=<sec> Sleep between files. Useful mostly for debugging.
---user=<username> Set username of uploader, default 'Maintenance script'
+--user=<username> Set username of uploader, default 'Maintenance script'.
--check-userblock Check if the user got blocked during import.
--comment=<text> Set file description, default 'Importing file'.
--comment-file=<file> Set description to the content of <file>.
---comment-ext=<ext> Causes the description for each file to be loaded from a file with the same name
- but the extension <ext>. If a global description is also given, it is appended.
---license=<code> Use an optional license template
---dry Dry run, don't import anything
---protect=<protect> Specify the protect value (autoconfirmed,sysop)
---summary=<summary> Upload summary, description will be used if not provided
---timestamp=<timestamp> Override upload time/date, all MediaWiki timestamp formats are accepted
---unprotect Unprotects all uploaded images
---source-wiki-url If specified, take User and Comment data for each imported file from this URL.
- For example, --source-wiki-url="http://en.wikipedia.org/"
+--comment-ext=<ext> Causes the description for each file to be loaded from a
+ file with the same name, but the extension <ext>. If a
+ global description is also given, it is appended.
+--license=<code> Use an optional license template.
+--dry Dry run, don't import anything.
+--protect=<protect> Specify the protect value (autoconfirmed,sysop).
+--summary=<summary> Upload summary, description will be used if not
+ provided.
+--timestamp=<timestamp> Override upload time/date, all MediaWiki timestamp
+ formats are accepted.
+--unprotect Unprotects all uploaded images.
+--source-wiki-url If specified, take User and Comment data for each
+ imported file from this URL. For example,
+ --source-wiki-url="http://en.wikipedia.org/."
TEXT;
exit( 1 );
diff --git a/maintenance/importSiteScripts.php b/maintenance/importSiteScripts.php
index fd768b34..7705ec9c 100644
--- a/maintenance/importSiteScripts.php
+++ b/maintenance/importSiteScripts.php
@@ -65,13 +65,12 @@ class ImportSiteScripts extends Maintenance {
$content = ContentHandler::makeContent( $text, $wikiPage->getTitle() );
$wikiPage->doEditContent( $content, "Importing from $url", 0, false, $user );
}
-
}
protected function fetchScriptList() {
$data = array(
'action' => 'query',
- 'format' => 'php',//'json',
+ 'format' => 'php', //'json',
'list' => 'allpages',
'apnamespace' => '8',
'aplimit' => '500',
@@ -100,7 +99,6 @@ class ImportSiteScripts extends Maintenance {
} while ( isset( $result['query-continue'] ) );
return $pages;
-
}
}
diff --git a/maintenance/importTextFile.php b/maintenance/importTextFile.php
deleted file mode 100644
index 4a07f2c7..00000000
--- a/maintenance/importTextFile.php
+++ /dev/null
@@ -1,110 +0,0 @@
-<?php
-/**
- * Create or edit pages using the contents of a text file.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- * @author Rob Church <robchur@gmail.com>
- */
-
-$options = array( 'help', 'nooverwrite', 'norc' );
-$optionsWithArgs = array( 'title', 'user', 'comment' );
-require_once __DIR__ . '/commandLine.inc';
-echo "Import Text File\n\n";
-
-if ( count( $args ) < 1 || isset( $options['help'] ) ) {
- showHelp();
-} else {
-
- $filename = $args[0];
- echo "Using {$filename}...";
- if ( is_file( $filename ) ) {
-
- $title = isset( $options['title'] ) ? $options['title'] : titleFromFilename( $filename );
- $title = Title::newFromURL( $title );
-
- if ( is_object( $title ) ) {
-
- echo "\nUsing title '" . $title->getPrefixedText() . "'...";
- if ( !$title->exists() || !isset( $options['nooverwrite'] ) ) {
- RequestContext::getMain()->setTitle( $title );
-
- $text = file_get_contents( $filename );
- $user = isset( $options['user'] ) ? $options['user'] : 'Maintenance script';
- $user = User::newFromName( $user );
-
- if ( is_object( $user ) ) {
-
- echo "\nUsing username '" . $user->getName() . "'...";
- $wgUser =& $user;
- $comment = isset( $options['comment'] ) ? $options['comment'] : 'Importing text file';
- $flags = 0 | ( isset( $options['norc'] ) ? EDIT_SUPPRESS_RC : 0 );
-
- echo "\nPerforming edit...";
- $page = WikiPage::factory( $title );
- $content = ContentHandler::makeContent( $text, $title );
- $page->doEditContent( $content, $comment, $flags, false, $user );
- echo "done.\n";
-
- } else {
- echo "invalid username.\n";
- }
-
- } else {
- echo "page exists.\n";
- }
-
- } else {
- echo "invalid title.\n";
- }
-
- } else {
- echo "does not exist.\n";
- }
-
-}
-
-function titleFromFilename( $filename ) {
- $parts = explode( '/', $filename );
- $parts = explode( '.', $parts[ count( $parts ) - 1 ] );
- return $parts[0];
-}
-
-function showHelp() {
-print <<<EOF
-USAGE: php importTextFile.php <options> <filename>
-
-<filename> : Path to the file containing page content to import
-
-Options:
-
---title <title>
- Title for the new page; default is to use the filename as a base
---user <user>
- User to be associated with the edit
---comment <comment>
- Edit summary
---nooverwrite
- Don't overwrite existing content
---norc
- Don't update recent changes
---help
- Show this information
-
-EOF;
-}
diff --git a/maintenance/initEditCount.php b/maintenance/initEditCount.php
index 4b046835..7c6e7d4f 100644
--- a/maintenance/initEditCount.php
+++ b/maintenance/initEditCount.php
@@ -47,7 +47,7 @@ in the load balancer, usually indicating a replication environment.' );
// Autodetect mode...
$backgroundMode = wfGetLB()->getServerCount() > 1 ||
- ( $dbw instanceof DatabaseMysql && version_compare( $dbver, '4.1' ) < 0 );
+ ( $dbw instanceof DatabaseMysql );
if ( $this->hasOption( 'background' ) ) {
$backgroundMode = true;
diff --git a/maintenance/initSiteStats.php b/maintenance/initSiteStats.php
index 92268b3e..49e0e9d7 100644
--- a/maintenance/initSiteStats.php
+++ b/maintenance/initSiteStats.php
@@ -34,7 +34,10 @@ class InitSiteStats extends Maintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Re-initialise the site statistics tables";
- $this->addOption( 'update', 'Update the existing statistics (preserves the ss_total_views field)' );
+ $this->addOption(
+ 'update',
+ 'Update the existing statistics (preserves the ss_total_views field)'
+ );
$this->addOption( 'noviews', "Don't update the page view counter" );
$this->addOption( 'active', 'Also update active users count' );
$this->addOption( 'use-master', 'Count using the master database' );
@@ -66,21 +69,19 @@ class InitSiteStats extends Maintenance {
$this->output( "{$views}\n" );
}
+ if ( $this->hasOption( 'update' ) ) {
+ $this->output( "\nUpdating site statistics..." );
+ $counter->refresh();
+ $this->output( "done.\n" );
+ }
+
if ( $this->hasOption( 'active' ) ) {
- $this->output( "Counting active users..." );
+ $this->output( "\nCounting and updating active users..." );
$active = SiteStatsUpdate::cacheUpdate( wfGetDB( DB_MASTER ) );
$this->output( "{$active}\n" );
}
- $this->output( "\nUpdating site statistics..." );
-
- if ( $this->hasOption( 'update' ) ) {
- $counter->update();
- } else {
- $counter->refresh();
- }
-
- $this->output( "done.\n" );
+ $this->output( "\nDone.\n" );
}
}
diff --git a/maintenance/install.php b/maintenance/install.php
index d118747a..b948b674 100644
--- a/maintenance/install.php
+++ b/maintenance/install.php
@@ -21,19 +21,20 @@
* @ingroup Maintenance
*/
-if ( !function_exists( 'version_compare' ) || ( version_compare( phpversion(), '5.3.2' ) < 0 ) ) {
- require_once dirname( __FILE__ ) . '/../includes/PHPVersionError.php';
- wfPHPVersionError( 'cli' );
-}
+// Checking for old versions of PHP is done in Maintenance.php
+// We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
+require_once dirname( __FILE__ ) . '/Maintenance.php';
define( 'MW_CONFIG_CALLBACK', 'Installer::overrideConfig' );
define( 'MEDIAWIKI_INSTALL', true );
-require_once dirname( __DIR__ ) . "/maintenance/Maintenance.php";
-
/**
* Maintenance script to install and configure MediaWiki
*
+ * Default values for the options are defined in DefaultSettings.php
+ * (see the mapping in CliInstaller.php)
+ * Default for --dbpath (SQLite-specific) is defined in SqliteInstaller::getGlobalDefaults
+ *
* @ingroup Maintenance
*/
class CommandLineInstaller extends Maintenance {
@@ -41,13 +42,26 @@ class CommandLineInstaller extends Maintenance {
parent::__construct();
global $IP;
- $this->addArg( 'name', 'The name of the wiki', true );
+ $this->addDescription( "CLI-based MediaWiki installation and configuration.\n" .
+ "Defaut options are indicated in parenthesis." );
+
+ $this->addArg( 'name', 'The name of the wiki (MediaWiki)', false );
- $this->addArg( 'admin', 'The username of the wiki administrator (WikiSysop)', true );
+ $this->addArg( 'admin', 'The username of the wiki administrator.' );
$this->addOption( 'pass', 'The password for the wiki administrator.', false, true );
- $this->addOption( 'passfile', 'An alternative way to provide pass option, as the contents of this file', false, true );
+ $this->addOption(
+ 'passfile',
+ 'An alternative way to provide pass option, as the contents of this file',
+ false,
+ true
+ );
/* $this->addOption( 'email', 'The email for the wiki administrator', false, true ); */
- $this->addOption( 'scriptpath', 'The relative path of the wiki in the web server (/wiki)', false, true );
+ $this->addOption(
+ 'scriptpath',
+ 'The relative path of the wiki in the web server (/wiki)',
+ false,
+ true
+ );
$this->addOption( 'lang', 'The language to use (en)', false, true );
/* $this->addOption( 'cont-lang', 'The content language (en)', false, true ); */
@@ -56,32 +70,42 @@ class CommandLineInstaller extends Maintenance {
$this->addOption( 'dbserver', 'The database host (localhost)', false, true );
$this->addOption( 'dbport', 'The database port; only for PostgreSQL (5432)', false, true );
$this->addOption( 'dbname', 'The database name (my_wiki)', false, true );
- $this->addOption( 'dbpath', 'The path for the SQLite DB (/var/data)', false, true );
+ $this->addOption( 'dbpath', 'The path for the SQLite DB ($IP/data)', false, true );
$this->addOption( 'dbprefix', 'Optional database table name prefix', false, true );
$this->addOption( 'installdbuser', 'The user to use for installing (root)', false, true );
- $this->addOption( 'installdbpass', 'The pasword for the DB user to install as.', false, true );
+ $this->addOption( 'installdbpass', 'The password for the DB user to install as.', false, true );
$this->addOption( 'dbuser', 'The user to use for normal operations (wikiuser)', false, true );
- $this->addOption( 'dbpass', 'The pasword for the DB user for normal operations', false, true );
- $this->addOption( 'dbpassfile', 'An alternative way to provide dbpass option, as the contents of this file', false, true );
- $this->addOption( 'confpath', "Path to write LocalSettings.php to, default $IP", false, true );
- /* $this->addOption( 'dbschema', 'The schema for the MediaWiki DB in pg (mediawiki)', false, true ); */
- /* $this->addOption( 'namespace', 'The project namespace (same as the name)', false, true ); */
+ $this->addOption( 'dbpass', 'The password for the DB user for normal operations', false, true );
+ $this->addOption(
+ 'dbpassfile',
+ 'An alternative way to provide dbpass option, as the contents of this file',
+ false,
+ true
+ );
+ $this->addOption( 'confpath', "Path to write LocalSettings.php to ($IP)", false, true );
+ $this->addOption( 'dbschema', 'The schema for the MediaWiki DB in '
+ . 'PostgreSQL/Microsoft SQL Server (mediawiki)', false, true );
+ /*
+ $this->addOption( 'namespace', 'The project namespace (same as the "name" argument)',
+ false, true );
+ */
$this->addOption( 'env-checks', "Run environment checks only, don't change anything" );
}
function execute() {
- global $IP, $wgTitle;
- $siteName = isset( $this->mArgs[0] ) ? $this->mArgs[0] : "Don't care"; // Will not be set if used with --env-checks
- $adminName = isset( $this->mArgs[1] ) ? $this->mArgs[1] : null;
- $wgTitle = Title::newFromText( 'Installer script' );
-
- $dbpassfile = $this->getOption( 'dbpassfile', false );
- if ( $dbpassfile !== false ) {
- if ( $this->getOption( 'dbpass', false ) !== false ) {
- $this->error( 'WARNING: You provide the options "dbpass" and "dbpassfile". The content of "dbpassfile" overwrites "dbpass".' );
+ global $IP;
+
+ $siteName = $this->getArg( 0, 'MediaWiki' ); // Will not be set if used with --env-checks
+ $adminName = $this->getArg( 1 );
+
+ $dbpassfile = $this->getOption( 'dbpassfile' );
+ if ( $dbpassfile !== null ) {
+ if ( $this->getOption( 'dbpass' ) !== null ) {
+ $this->error( 'WARNING: You have provided the options "dbpass" and "dbpassfile". '
+ . 'The content of "dbpassfile" overrides "dbpass".' );
}
wfSuppressWarnings();
- $dbpass = file_get_contents( $dbpassfile );
+ $dbpass = file_get_contents( $dbpassfile ); // returns false on failure
wfRestoreWarnings();
if ( $dbpass === false ) {
$this->error( "Couldn't open $dbpassfile", true );
@@ -89,30 +113,31 @@ class CommandLineInstaller extends Maintenance {
$this->mOptions['dbpass'] = trim( $dbpass, "\r\n" );
}
- $passfile = $this->getOption( 'passfile', false );
- if ( $passfile !== false ) {
- if ( $this->getOption( 'pass', false ) !== false ) {
- $this->error( 'WARNING: You provide the options "pass" and "passfile". The content of "passfile" overwrites "pass".' );
+ $passfile = $this->getOption( 'passfile' );
+ if ( $passfile !== null ) {
+ if ( $this->getOption( 'pass' ) !== null ) {
+ $this->error( 'WARNING: You have provided the options "pass" and "passfile". '
+ . 'The content of "passfile" overrides "pass".' );
}
wfSuppressWarnings();
- $pass = file_get_contents( $passfile );
+ $pass = file_get_contents( $passfile ); // returns false on failure
wfRestoreWarnings();
if ( $pass === false ) {
$this->error( "Couldn't open $passfile", true );
}
- $this->mOptions['pass'] = str_replace( array( "\n", "\r" ), "", $pass );
- } elseif ( $this->getOption( 'pass', false ) === false ) {
+ $this->mOptions['pass'] = trim( $pass, "\r\n" );
+ } elseif ( $this->getOption( 'pass' ) === null ) {
$this->error( 'You need to provide the option "pass" or "passfile"', true );
}
- $installer =
- InstallerOverrides::getCliInstaller( $siteName, $adminName, $this->mOptions );
+ $installer = InstallerOverrides::getCliInstaller( $siteName, $adminName, $this->mOptions );
$status = $installer->doEnvironmentChecks();
if ( $status->isGood() ) {
$installer->showMessage( 'config-env-good' );
} else {
$installer->showStatusMessage( $status );
+
return;
}
if ( !$this->hasOption( 'env-checks' ) ) {
@@ -128,6 +153,6 @@ class CommandLineInstaller extends Maintenance {
}
}
-$maintClass = "CommandLineInstaller";
+$maintClass = 'CommandLineInstaller';
require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/interwiki.list b/maintenance/interwiki.list
index 179fa5c6..0660e55f 100644
--- a/maintenance/interwiki.list
+++ b/maintenance/interwiki.list
@@ -1,98 +1,77 @@
# Based more or less on the public interwiki map from MeatballWiki
# Default interwiki prefixes...
-acronym|http://www.acronymfinder.com/af-query.asp?String=exact&Acronym=$1|0
+acronym|http://www.acronymfinder.com/~/search/af.aspx?string=exact&Acronym=$1|0
advogato|http://www.advogato.org/$1|0
-annotationwiki|http://www.seedwiki.com/page.cfm?wikiid=368&doc=$1|0
arxiv|http://www.arxiv.org/abs/$1|0
c2find|http://c2.com/cgi/wiki?FindPage&value=$1|0
cache|http://www.google.com/search?q=cache:$1|0
-commons|http://commons.wikimedia.org/wiki/$1|0
-corpknowpedia|http://corpknowpedia.org/wiki/index.php/$1|0
+commons|https://commons.wikimedia.org/wiki/$1|0
dictionary|http://www.dict.org/bin/Dict?Database=*&Form=Dict1&Strategy=*&Query=$1|0
-disinfopedia|http://www.disinfopedia.org/wiki.phtml?title=$1|0
-docbook|http://wiki.docbook.org/topic/$1|0
+docbook|http://wiki.docbook.org/$1|0
doi|http://dx.doi.org/$1|0
-drumcorpswiki|http://www.drumcorpswiki.com/index.php/$1|0
+drumcorpswiki|http://www.drumcorpswiki.com/$1|0
dwjwiki|http://www.suberic.net/cgi-bin/dwj/wiki.cgi?$1|0
elibre|http://enciclopedia.us.es/index.php/$1|0
emacswiki|http://www.emacswiki.org/cgi-bin/wiki.pl?$1|0
foldoc|http://foldoc.org/?$1|0
foxwiki|http://fox.wikis.com/wc.dll?Wiki~$1|0
freebsdman|http://www.FreeBSD.org/cgi/man.cgi?apropos=1&query=$1|0
-gej|http://www.esperanto.de/cgi-bin/aktivikio/wiki.pl?$1|0
+gej|http://www.esperanto.de/dej.malnova/aktivikio.pl?$1|0
gentoo-wiki|http://gentoo-wiki.com/$1|0
google|http://www.google.com/search?q=$1|0
googlegroups|http://groups.google.com/groups?q=$1|0
hammondwiki|http://www.dairiki.org/HammondWiki/$1|0
-hewikisource|http://he.wikisource.org/wiki/$1|1
-hrwiki|http://www.hrwiki.org/index.php/$1|0
-imdb|http://us.imdb.com/Title?$1|0
+hrwiki|http://www.hrwiki.org/wiki/$1|0
+imdb|http://www.imdb.com/find?q=$1&tt=on|0
jargonfile|http://sunir.org/apps/meta.pl?wiki=JargonFile&redirect=$1|0
-jspwiki|http://www.jspwiki.org/wiki/$1|0
-keiki|http://kei.ki/en/$1|0
kmwiki|http://kmwiki.wikispaces.com/$1|0
linuxwiki|http://linuxwiki.de/$1|0
lojban|http://www.lojban.org/tiki/tiki-index.php?page=$1|0
lqwiki|http://wiki.linuxquestions.org/wiki/$1|0
-lugkr|http://lug-kr.sourceforge.net/cgi-bin/lugwiki.pl?$1|0
-mathsongswiki|http://SeedWiki.com/page.cfm?wikiid=237&doc=$1|0
+lugkr|http://www.lug-kr.de/wiki/$1|0
meatball|http://www.usemod.com/cgi-bin/mb.pl?$1|0
-mediawikiwiki|http://www.mediawiki.org/wiki/$1|0
-mediazilla|https://bugzilla.wikimedia.org/$1|1
-memoryalpha|http://www.memory-alpha.org/en/index.php/$1|0
+mediawikiwiki|https://www.mediawiki.org/wiki/$1|0
+mediazilla|https://bugzilla.wikimedia.org/$1|0
+memoryalpha|http://en.memory-alpha.org/wiki/$1|0
metawiki|http://sunir.org/apps/meta.pl?$1|0
-metawikimedia|http://meta.wikimedia.org/wiki/$1|0
-moinmoin|http://purl.net/wiki/moin/$1|0
-mozillawiki|http://wiki.mozilla.org/index.php/$1|0
+metawikimedia|https://meta.wikimedia.org/wiki/$1|0
+mozillawiki|http://wiki.mozilla.org/$1|0
mw|http://www.mediawiki.org/wiki/$1|0
-oeis|http://www.research.att.com/cgi-bin/access.cgi/as/njas/sequences/eisA.cgi?Anum=$1|0
-openfacts|http://openfacts.berlios.de/index.phtml?title=$1|0
-openwiki|http://openwiki.com/?$1|0
-# patwiki|http://gauss.ffii.org/$1|0 # 2008-02-27: lots of spambots
-pmeg|http://www.bertilow.com/pmeg/$1.php|0
+oeis|http://oeis.org/$1|0
+openwiki|http://openwiki.com/ow.asp?$1|0
ppr|http://c2.com/cgi/wiki?$1|0
pythoninfo|http://wiki.python.org/moin/$1|0
rfc|http://www.rfc-editor.org/rfc/rfc$1.txt|0
-s23wiki|http://is-root.de/wiki/index.php/$1|0
-seattlewiki|http://seattle.wikia.com/wiki/$1|0
-seattlewireless|http://seattlewireless.net/?$1|0
+s23wiki|http://s23.org/wiki/$1|0
+seattlewireless|http://seattlewireless.net/$1|0
senseislibrary|http://senseis.xmp.net/?$1|0
-# slashdot|http://slashdot.org/article.pl?sid=$1|0 # 2008-02-27: update me
+shoutwiki|http://www.shoutwiki.com/wiki/$1|0
sourceforge|http://sourceforge.net/$1|0
+sourcewatch|http://www.sourcewatch.org/index.php?title=$1|0
squeak|http://wiki.squeak.org/squeak/$1|0
-susning|http://www.susning.nu/$1|0
-svgwiki|http://wiki.svg.org/$1|0
-tavi|http://tavi.sourceforge.net/$1|0
tejo|http://www.tejo.org/vikio/$1|0
tmbw|http://www.tmbw.net/wiki/$1|0
tmnet|http://www.technomanifestos.net/?$1|0
-tmwiki|http://www.EasyTopicMaps.com/?page=$1|0
theopedia|http://www.theopedia.com/$1|0
twiki|http://twiki.org/cgi-bin/view/$1|0
-uea|http://www.tejo.org/uea/$1|0
-unreal|http://wiki.beyondunreal.com/wiki/$1|0
+uea|http://uea.org/vikio/index.php/$1|0
+uncyclopedia|http://en.uncyclopedia.co/wiki/$1|0
+unreal|http://wiki.beyondunreal.com/$1|0
usemod|http://www.usemod.com/cgi-bin/wiki.pl?$1|0
-vinismo|http://vinismo.com/en/$1|0
webseitzwiki|http://webseitz.fluxent.com/wiki/$1|0
-why|http://clublet.com/c/c/why?$1|0
wiki|http://c2.com/cgi/wiki?$1|0
wikia|http://www.wikia.com/wiki/$1|0
-wikibooks|http://en.wikibooks.org/wiki/$1|1
-wikicities|http://www.wikia.com/wiki/$1|0
+wikibooks|https://en.wikibooks.org/wiki/$1|0
wikif1|http://www.wikif1.org/$1|0
wikihow|http://www.wikihow.com/$1|0
-wikinfo|http://www.wikinfo.org/index.php/$1|0
-# The following wik[it]* interwikis but wikitravel belong to the Wikimedia Family:
-wikimedia|http://wikimediafoundation.org/wiki/$1|0
-wikinews|http://en.wikinews.org/wiki/$1|1
-wikipedia|http://en.wikipedia.org/wiki/$1|1
-wikiquote|http://en.wikiquote.org/wiki/$1|1
-wikisource|http://wikisource.org/wiki/$1|1
-wikispecies|http://species.wikimedia.org/wiki/$1|1
-wikitravel|http://wikitravel.org/en/$1|0
-wikiversity|http://en.wikiversity.org/wiki/$1|1
-wikt|http://en.wiktionary.org/wiki/$1|1
-wiktionary|http://en.wiktionary.org/wiki/$1|1
-wlug|http://www.wlug.org.nz/$1|0
-zwiki|http://zwiki.org/$1|0
-zzz wiki|http://wiki.zzz.ee/index.php/$1|0
+wikinfo|http://wikinfo.co/English/index.php/$1|0
+wikimedia|https://wikimediafoundation.org/wiki/$1|0
+wikinews|https://en.wikinews.org/wiki/$1|0
+wikipedia|https://en.wikipedia.org/wiki/$1|0
+wikiquote|https://en.wikiquote.org/wiki/$1|0
+wikisource|https://wikisource.org/wiki/$1|0
+wikispecies|https://species.wikimedia.org/wiki/$1|0
+wikiversity|https://en.wikiversity.org/wiki/$1|0
+wikivoyage|https://en.wikivoyage.org/wiki/$1|0
+wikt|https://en.wiktionary.org/wiki/$1|0
+wiktionary|https://en.wiktionary.org/wiki/$1|0
diff --git a/maintenance/interwiki.sql b/maintenance/interwiki.sql
index 370460af..aad0cc3b 100644
--- a/maintenance/interwiki.sql
+++ b/maintenance/interwiki.sql
@@ -2,99 +2,79 @@
-- Default interwiki prefixes...
REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES
-('acronym','http://www.acronymfinder.com/af-query.asp?String=exact&Acronym=$1',0),
+('acronym','http://www.acronymfinder.com/~/search/af.aspx?string=exact&Acronym=$1',0),
('advogato','http://www.advogato.org/$1',0),
-('annotationwiki','http://www.seedwiki.com/page.cfm?wikiid=368&doc=$1',0),
('arxiv','http://www.arxiv.org/abs/$1',0),
('c2find','http://c2.com/cgi/wiki?FindPage&value=$1',0),
('cache','http://www.google.com/search?q=cache:$1',0),
-('commons','http://commons.wikimedia.org/wiki/$1',0),
-('corpknowpedia','http://corpknowpedia.org/wiki/index.php/$1',0),
+('commons','https://commons.wikimedia.org/wiki/$1',0),
('dictionary','http://www.dict.org/bin/Dict?Database=*&Form=Dict1&Strategy=*&Query=$1',0),
-('disinfopedia','http://www.disinfopedia.org/wiki.phtml?title=$1',0),
-('docbook','http://wiki.docbook.org/topic/$1',0),
+('docbook','http://wiki.docbook.org/$1',0),
('doi','http://dx.doi.org/$1',0),
-('drumcorpswiki','http://www.drumcorpswiki.com/index.php/$1',0),
+('drumcorpswiki','http://www.drumcorpswiki.com/$1',0),
('dwjwiki','http://www.suberic.net/cgi-bin/dwj/wiki.cgi?$1',0),
('elibre','http://enciclopedia.us.es/index.php/$1',0),
('emacswiki','http://www.emacswiki.org/cgi-bin/wiki.pl?$1',0),
('foldoc','http://foldoc.org/?$1',0),
('foxwiki','http://fox.wikis.com/wc.dll?Wiki~$1',0),
('freebsdman','http://www.FreeBSD.org/cgi/man.cgi?apropos=1&query=$1',0),
-('gej','http://www.esperanto.de/cgi-bin/aktivikio/wiki.pl?$1',0),
+('gej','http://www.esperanto.de/dej.malnova/aktivikio.pl?$1',0),
('gentoo-wiki','http://gentoo-wiki.com/$1',0),
('google','http://www.google.com/search?q=$1',0),
('googlegroups','http://groups.google.com/groups?q=$1',0),
('hammondwiki','http://www.dairiki.org/HammondWiki/$1',0),
-('hewikisource','http://he.wikisource.org/wiki/$1',1),
-('hrwiki','http://www.hrwiki.org/index.php/$1',0),
-('imdb','http://us.imdb.com/Title?$1',0),
+('hrwiki','http://www.hrwiki.org/wiki/$1',0),
+('imdb','http://www.imdb.com/find?q=$1&tt=on',0),
('jargonfile','http://sunir.org/apps/meta.pl?wiki=JargonFile&redirect=$1',0),
-('jspwiki','http://www.jspwiki.org/wiki/$1',0),
-('keiki','http://kei.ki/en/$1',0),
('kmwiki','http://kmwiki.wikispaces.com/$1',0),
('linuxwiki','http://linuxwiki.de/$1',0),
('lojban','http://www.lojban.org/tiki/tiki-index.php?page=$1',0),
('lqwiki','http://wiki.linuxquestions.org/wiki/$1',0),
-('lugkr','http://lug-kr.sourceforge.net/cgi-bin/lugwiki.pl?$1',0),
-('mathsongswiki','http://SeedWiki.com/page.cfm?wikiid=237&doc=$1',0),
+('lugkr','http://www.lug-kr.de/wiki/$1',0),
('meatball','http://www.usemod.com/cgi-bin/mb.pl?$1',0),
-('mediawikiwiki','http://www.mediawiki.org/wiki/$1',0),
-('mediazilla','https://bugzilla.wikimedia.org/$1',1),
-('memoryalpha','http://www.memory-alpha.org/en/index.php/$1',0),
+('mediawikiwiki','https://www.mediawiki.org/wiki/$1',0),
+('mediazilla','https://bugzilla.wikimedia.org/$1',0),
+('memoryalpha','http://en.memory-alpha.org/wiki/$1',0),
('metawiki','http://sunir.org/apps/meta.pl?$1',0),
-('metawikimedia','http://meta.wikimedia.org/wiki/$1',0),
-('moinmoin','http://purl.net/wiki/moin/$1',0),
-('mozillawiki','http://wiki.mozilla.org/index.php/$1',0),
+('metawikimedia','https://meta.wikimedia.org/wiki/$1',0),
+('mozillawiki','http://wiki.mozilla.org/$1',0),
('mw','http://www.mediawiki.org/wiki/$1',0),
-('oeis','http://www.research.att.com/cgi-bin/access.cgi/as/njas/sequences/eisA.cgi?Anum=$1',0),
-('openfacts','http://openfacts.berlios.de/index.phtml?title=$1',0),
-('openwiki','http://openwiki.com/?$1',0),
-('patwiki','http://gauss.ffii.org/$1',0), # 2008-02-27: lots of spambots
-('pmeg','http://www.bertilow.com/pmeg/$1.php',0),
+('oeis','http://oeis.org/$1',0),
+('openwiki','http://openwiki.com/ow.asp?$1',0),
('ppr','http://c2.com/cgi/wiki?$1',0),
('pythoninfo','http://wiki.python.org/moin/$1',0),
('rfc','http://www.rfc-editor.org/rfc/rfc$1.txt',0),
-('s23wiki','http://is-root.de/wiki/index.php/$1',0),
-('seattlewiki','http://seattle.wikia.com/wiki/$1',0),
-('seattlewireless','http://seattlewireless.net/?$1',0),
+('s23wiki','http://s23.org/wiki/$1',0),
+('seattlewireless','http://seattlewireless.net/$1',0),
('senseislibrary','http://senseis.xmp.net/?$1',0),
-('slashdot','http://slashdot.org/article.pl?sid=$1',0), # 2008-02-27: update me
+('shoutwiki','http://www.shoutwiki.com/wiki/$1',0),
('sourceforge','http://sourceforge.net/$1',0),
+('sourcewatch','http://www.sourcewatch.org/index.php?title=$1',0),
('squeak','http://wiki.squeak.org/squeak/$1',0),
-('susning','http://www.susning.nu/$1',0),
-('svgwiki','http://wiki.svg.org/$1',0),
-('tavi','http://tavi.sourceforge.net/$1',0),
('tejo','http://www.tejo.org/vikio/$1',0),
('tmbw','http://www.tmbw.net/wiki/$1',0),
('tmnet','http://www.technomanifestos.net/?$1',0),
-('tmwiki','http://www.EasyTopicMaps.com/?page=$1',0),
('theopedia','http://www.theopedia.com/$1',0),
('twiki','http://twiki.org/cgi-bin/view/$1',0),
-('uea','http://www.tejo.org/uea/$1',0),
-('unreal','http://wiki.beyondunreal.com/wiki/$1',0),
+('uea','http://uea.org/vikio/index.php/$1',0),
+('uncyclopedia','http://en.uncyclopedia.co/wiki/$1',0),
+('unreal','http://wiki.beyondunreal.com/$1',0),
('usemod','http://www.usemod.com/cgi-bin/wiki.pl?$1',0),
-('vinismo','http://vinismo.com/en/$1',0),
('webseitzwiki','http://webseitz.fluxent.com/wiki/$1',0),
-('why','http://clublet.com/c/c/why?$1',0),
('wiki','http://c2.com/cgi/wiki?$1',0),
('wikia','http://www.wikia.com/wiki/$1',0),
-('wikibooks','http://en.wikibooks.org/wiki/$1',1),
-('wikicities','http://www.wikia.com/wiki/$1',0),
+('wikibooks','https://en.wikibooks.org/wiki/$1',0),
('wikif1','http://www.wikif1.org/$1',0),
('wikihow','http://www.wikihow.com/$1',0),
-('wikinfo','http://www.wikinfo.org/index.php/$1',0),
-# The following wik[it]* interwikis but wikitravel belong to the Wikimedia Family:
-('wikimedia','http://wikimediafoundation.org/wiki/$1',0),
-('wikinews','http://en.wikinews.org/wiki/$1',1),
-('wikipedia','http://en.wikipedia.org/wiki/$1',1),
-('wikiquote','http://en.wikiquote.org/wiki/$1',1),
-('wikisource','http://wikisource.org/wiki/$1',1),
-('wikispecies','http://species.wikimedia.org/wiki/$1',1),
-('wikitravel','http://wikitravel.org/en/$1',0),
-('wikiversity','http://en.wikiversity.org/wiki/$1',1),
-('wikt','http://en.wiktionary.org/wiki/$1',1),
-('wiktionary','http://en.wiktionary.org/wiki/$1',1),
-('wlug','http://www.wlug.org.nz/$1',0),
-('zwiki','http://zwiki.org/$1',0),
-('zzz wiki','http://wiki.zzz.ee/index.php/$1',0);
+('wikinfo','http://wikinfo.co/English/index.php/$1',0),
+('wikimedia','https://wikimediafoundation.org/wiki/$1',0),
+('wikinews','https://en.wikinews.org/wiki/$1',0),
+('wikipedia','https://en.wikipedia.org/wiki/$1',0),
+('wikiquote','https://en.wikiquote.org/wiki/$1',0),
+('wikisource','https://wikisource.org/wiki/$1',0),
+('wikispecies','https://species.wikimedia.org/wiki/$1',0),
+('wikiversity','https://en.wikiversity.org/wiki/$1',0),
+('wikivoyage','https://en.wikivoyage.org/wiki/$1',0),
+('wikt','https://en.wiktionary.org/wiki/$1',0),
+('wiktionary','https://en.wiktionary.org/wiki/$1',0)
+;
diff --git a/maintenance/jsduck/CustomTags.rb b/maintenance/jsduck/CustomTags.rb
new file mode 100644
index 00000000..2aff9881
--- /dev/null
+++ b/maintenance/jsduck/CustomTags.rb
@@ -0,0 +1,116 @@
+# Custom tags for JSDuck 5.x
+# See also:
+# - https://github.com/senchalabs/jsduck/wiki/Tags
+# - https://github.com/senchalabs/jsduck/wiki/Custom-tags
+# - https://github.com/senchalabs/jsduck/wiki/Custom-tags/7f5c32e568eab9edc8e3365e935bcb836cb11f1d
+require 'jsduck/tag/tag'
+
+class CommonTag < JsDuck::Tag::Tag
+ def initialize
+ @html_position = POS_DOC + 0.1
+ @repeatable = true
+ end
+
+ def parse_doc(scanner, position)
+ if @multiline
+ return { :tagname => @tagname, :doc => :multiline }
+ else
+ text = scanner.match(/.*$/)
+ return { :tagname => @tagname, :doc => text }
+ end
+ end
+
+ def process_doc(context, tags, position)
+ context[@tagname] = tags
+ end
+
+ def format(context, formatter)
+ context[@tagname].each do |tag|
+ tag[:doc] = formatter.format(tag[:doc])
+ end
+ end
+end
+
+class SourceTag < CommonTag
+ def initialize
+ @tagname = :source
+ @pattern = "source"
+ super
+ end
+
+ def to_html(context)
+ context[@tagname].map do |source|
+ <<-EOHTML
+ <h3 class='pa'>Source</h3>
+ #{source[:doc]}
+ EOHTML
+ end.join
+ end
+end
+
+class SeeTag < CommonTag
+ def initialize
+ @tagname = :see
+ @pattern = "see"
+ super
+ end
+
+ def format(context, formatter)
+ position = context[:files][0]
+ context[@tagname].each do |tag|
+ tag[:doc] = '<li>' + render_long_see(tag[:doc], formatter, position) + '</li>'
+ end
+ end
+
+ def to_html(context)
+ <<-EOHTML
+ <h3 class="pa">Related</h3>
+ <ul>
+ #{ context[@tagname].map {|tag| tag[:doc] }.join("\n") }
+ </ul>
+ EOHTML
+ end
+
+ def render_long_see(tag, formatter, position)
+ if tag =~ /\A([^\s]+)( .*)?\Z/m
+ name = $1
+ doc = $2 ? ': ' + $2 : ''
+ return formatter.format("{@link #{name}} #{doc}")
+ else
+ JsDuck::Logger.warn(nil, 'Unexpected @see argument: "'+tag+'"', position)
+ return tag
+ end
+ end
+end
+
+class ContextTag < CommonTag
+ def initialize
+ @tagname = :context
+ @pattern = 'context'
+ super
+ end
+
+ def format(context, formatter)
+ position = context[:files][0]
+ context[@tagname].each do |tag|
+ tag[:doc] = render_long_context(tag[:doc], formatter, position)
+ end
+ end
+
+ def to_html(context)
+ <<-EOHTML
+ <h3 class="pa">Context</h3>
+ #{ context[@tagname].last[:doc] }
+ EOHTML
+ end
+
+ def render_long_context(tag, formatter, position)
+ if tag =~ /\A([^\s]+)/m
+ name = $1
+ return formatter.format("`context` : {@link #{name}}")
+ else
+ JsDuck::Logger.warn(nil, 'Unexpected @context argument: "'+tag+'"', position)
+ return tag
+ end
+ end
+end
diff --git a/maintenance/jsduck/MetaTags.rb b/maintenance/jsduck/MetaTags.rb
deleted file mode 100644
index 83cc0884..00000000
--- a/maintenance/jsduck/MetaTags.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# See also:
-# - https://github.com/senchalabs/jsduck/wiki/Tags
-# - https://github.com/senchalabs/jsduck/wiki/Custom-tags
-require 'jsduck/meta_tag'
-
-class SourceTag < JsDuck::MetaTag
- def initialize
- # This defines the name of the @tag
- @name = 'source'
- end
-
- # Generate HTML output for this tag.
- # One can make use of the #format method to easily support
- # Markdown and {@link} tags inside the contents of the tag.
- #
- # @param tags All matches of this tag on one class.
- def to_html(tags)
- '<h3 class="pa">Source</h3>' + tags.map {|tag| format(tag) }.join("\n")
- end
-end
-
-class ContextTag < JsDuck::MetaTag
- def initialize
- @name = 'context'
- end
-
- # @param tags All matches of this tag on one class.
- def to_html(tags)
- return '<h3 class="pa">Context</h3>' + render_long_context(tags.last)
- end
-
- def render_long_context(tag)
- if tag =~ /\A([^\s]+)/m
- name = $1
- return format("`this` : {@link #{name}}")
- end
- end
-end
-
-class SeeTag < JsDuck::MetaTag
- def initialize
- @name = 'see'
- @multiline = true
- end
-
- # @param tags All matches of this tag on one class.
- def to_html(tags)
- doc = []
- doc << '<h3 class="pa">Related</h3>'
- doc << [
- '<ul>',
- tags.map {|tag| render_long_see(tag) },
- '</ul>',
- ]
- doc
- end
-
- def render_long_see(tag)
- if tag =~ /\A([^\s]+)( .*)?\Z/m
- name = $1
- doc = $2 ? ': ' + $2 : ''
- return [
- '<li>',
- format("{@link #{name}} #{doc}"),
- '</li>'
- ]
- end
- end
-end
diff --git a/maintenance/jsduck/categories.json b/maintenance/jsduck/categories.json
index f96902d8..d6163bde 100644
--- a/maintenance/jsduck/categories.json
+++ b/maintenance/jsduck/categories.json
@@ -9,7 +9,7 @@
"mw.Map",
"mw.Message",
"mw.loader",
- "mw.log",
+ "mw.loader.store",
"mw.html",
"mw.html.Cdata",
"mw.html.Raw",
@@ -20,12 +20,13 @@
"name": "General",
"classes": [
"mw.Title",
- "mw.inspect",
- "mw.inspect.reports",
+ "mw.Uri",
"mw.notification",
+ "mw.Notification_",
"mw.user",
"mw.util",
- "mw.plugin.*"
+ "mw.plugin.*",
+ "mw.cookie"
]
},
{
@@ -35,6 +36,42 @@
{
"name": "API",
"classes": ["mw.Api*"]
+ },
+ {
+ "name": "Language",
+ "classes": [
+ "mw.language*",
+ "mw.cldr",
+ "mw.jqueryMsg"
+ ]
+ },
+ {
+ "name": "Page",
+ "classes": [
+ "mw.page*"
+ ]
+ },
+ {
+ "name": "Interfaces",
+ "classes": [
+ "mw.Feedback"
+ ]
+ },
+ {
+ "name": "Special",
+ "classes": [
+ "mw.special*"
+ ]
+ },
+ {
+ "name": "Development",
+ "classes": [
+ "mw.log",
+ "mw.inspect",
+ "mw.inspect.reports",
+ "mw.Debug",
+ "mw.Debug.profile"
+ ]
}
]
},
@@ -43,7 +80,11 @@
"groups": [
{
"name": "Plugins",
- "classes": ["jQuery.plugin.*"]
+ "classes": [
+ "jQuery.client",
+ "jQuery.colorUtil",
+ "jQuery.plugin.*"
+ ]
}
]
},
@@ -51,6 +92,10 @@
"name": "Upstream",
"groups": [
{
+ "name": "OOJS",
+ "classes": ["OO", "OO.*"]
+ },
+ {
"name": "jQuery",
"classes": ["jQuery", "jQuery.Event", "jQuery.Callbacks", "jQuery.Promise", "jQuery.Deferred", "jQuery.jqXHR", "QUnit"]
},
diff --git a/maintenance/jsduck/config.json b/maintenance/jsduck/config.json
index e6e0f658..e97f2923 100644
--- a/maintenance/jsduck/config.json
+++ b/maintenance/jsduck/config.json
@@ -1,27 +1,40 @@
{
"--title": "MediaWiki core - Documentation",
- "--footer": "Documentation for MediaWiki core. Generated on {DATE} by {JSDUCK} {VERSION}.",
"--categories": "./categories.json",
- "--meta-tags": "./MetaTags.rb",
"--eg-iframe": "./eg-iframe.html",
- "--warnings": ["-no_doc"],
+ "--tags": "./CustomTags.rb",
+ "--warnings": ["-nodoc(class,public)"],
"--builtin-classes": true,
+ "--warnings-exit-nonzero": true,
+ "--external": "HTMLElement,HTMLDocument,Window,File",
+ "--footer": "Documentation for MediaWiki core. Generated on {DATE} by {JSDUCK} {VERSION}.",
"--output": "../../docs/js",
"--": [
"./external.js",
- "../../resources/mediawiki/mediawiki.js",
- "../../resources/mediawiki/mediawiki.log.js",
- "../../resources/mediawiki/mediawiki.util.js",
- "../../resources/mediawiki/mediawiki.Title.js",
- "../../resources/mediawiki/mediawiki.inspect.js",
- "../../resources/mediawiki/mediawiki.notify.js",
- "../../resources/mediawiki/mediawiki.notification.js",
- "../../resources/mediawiki/mediawiki.user.js",
- "../../resources/mediawiki.action/mediawiki.action.edit.js",
- "../../resources/mediawiki.action/mediawiki.action.view.postEdit.js",
- "../../resources/mediawiki.page/mediawiki.page.startup.js",
- "../../resources/mediawiki.api",
- "../../resources/jquery/jquery.localize.js",
- "../../resources/jquery/jquery.spinner.js"
+ "../../resources/src/mediawiki",
+ "../../resources/src/mediawiki.action",
+ "../../resources/src/mediawiki.api",
+ "../../resources/src/mediawiki.language",
+ "../../resources/src/mediawiki.page",
+ "../../resources/src/mediawiki.special",
+ "../../resources/src/jquery/jquery.accessKeyLabel.js",
+ "../../resources/src/jquery/jquery.arrowSteps.js",
+ "../../resources/src/jquery/jquery.autoEllipsis.js",
+ "../../resources/src/jquery/jquery.badge.js",
+ "../../resources/src/jquery/jquery.byteLength.js",
+ "../../resources/src/jquery/jquery.byteLimit.js",
+ "../../resources/src/jquery/jquery.checkboxShiftClick.js",
+ "../../resources/src/jquery/jquery.client.js",
+ "../../resources/src/jquery/jquery.colorUtil.js",
+ "../../resources/src/jquery/jquery.confirmable.js",
+ "../../resources/src/jquery/jquery.footHovzer.js",
+ "../../resources/src/jquery/jquery.getAttrs.js",
+ "../../resources/src/jquery/jquery.hidpi.js",
+ "../../resources/src/jquery/jquery.localize.js",
+ "../../resources/src/jquery/jquery.makeCollapsible.js",
+ "../../resources/src/jquery/jquery.spinner.js",
+ "../../resources/src/jquery/jquery.tabIndex.js",
+ "../../resources/lib/oojs",
+ "../../resources/lib/oojs-ui"
]
}
diff --git a/maintenance/jsduck/eg-iframe.html b/maintenance/jsduck/eg-iframe.html
index 86eae4b6..7dc4afa8 100644
--- a/maintenance/jsduck/eg-iframe.html
+++ b/maintenance/jsduck/eg-iframe.html
@@ -1,88 +1,88 @@
<!DOCTYPE html>
<html>
<head>
- <meta charset="utf-8">
- <title>MediaWiki Code Example</title>
- <script src="modules/startup.js"></script>
- <script>
- function startUp() {
- mw.config = new mw.Map();
- }
- </script>
- <script src="modules/jquery/jquery.js"></script>
- <script src="modules/mediawiki/mediawiki.js"></script>
- <style>
- .mw-jsduck-log {
- position: relative;
- min-height: 3em;
- margin-top: 2em;
- background: #f7f7f7;
- border: 1px solid #e4e4e4;
- }
+ <meta charset="utf-8">
+ <title>MediaWiki Code Example</title>
+ <script src="modules/startup.js"></script>
+ <script>
+ function startUp() {
+ mw.config = new mw.Map();
+ }
+ </script>
+ <script src="modules/jquery/jquery.js"></script>
+ <script src="modules/mediawiki/mediawiki.js"></script>
+ <style>
+ .mw-jsduck-log {
+ position: relative;
+ min-height: 3em;
+ margin-top: 2em;
+ background: #f7f7f7;
+ border: 1px solid #e4e4e4;
+ }
- .mw-jsduck-log::after {
- position: absolute;
- bottom: 100%;
- right: -1px;
- padding: 0.5em;
- background: #fff;
- border: 1px solid #e4e4e4;
- border-bottom: 0;
- border-radius: 0.5em 0.5em 0 0;
- font: normal 0.5em sans-serif;
- content: 'console';
- }
+ .mw-jsduck-log::after {
+ position: absolute;
+ bottom: 100%;
+ right: -1px;
+ padding: 0.5em;
+ background: #fff;
+ border: 1px solid #e4e4e4;
+ border-bottom: 0;
+ border-radius: 0.5em 0.5em 0 0;
+ font: normal 0.5em sans-serif;
+ content: 'console';
+ }
- .mw-jsduck-log-line {
- padding: 0.2em 0.5em;
- white-space: pre-wrap;
- }
+ .mw-jsduck-log-line {
+ padding: 0.2em 0.5em;
+ white-space: pre-wrap;
+ }
- .mw-jsduck-log-line:nth-child(odd) {
- background: #fff;
- }
- </style>
+ .mw-jsduck-log-line:nth-child(odd) {
+ background: #fff;
+ }
+ </style>
</head>
<body>
- <script>
- /**
- * Basic log console for the example iframe in documentation pages.
- */
- ( function () {
- var pre;
- mw.log = function () {
- var str, i, len, line;
- if ( !pre ) {
- pre = document.createElement( 'pre' );
- pre.className = 'mw-jsduck-log';
- document.body.appendChild( pre );
- }
- str = [];
- for ( i = 0, len = arguments.length; i < len; i++ ) {
- str.push( String( arguments[ i ] ) );
- }
- line = document.createElement( 'div' );
- line.className = 'mw-jsduck-log-line';
- line.appendChild(
- document.createTextNode( str.join( ' , ' ) + '\n' )
- );
- pre.appendChild( line );
- };
- }() );
+<script>
+ /**
+ * Basic log console for the example iframe in documentation pages.
+ */
+ ( function () {
+ var pre;
+ mw.log = function () {
+ var str, i, len, line;
+ if ( !pre ) {
+ pre = document.createElement( 'pre' );
+ pre.className = 'mw-jsduck-log';
+ document.body.appendChild( pre );
+ }
+ str = [];
+ for ( i = 0, len = arguments.length; i < len; i++ ) {
+ str.push( String( arguments[ i ] ) );
+ }
+ line = document.createElement( 'div' );
+ line.className = 'mw-jsduck-log-line';
+ line.appendChild(
+ document.createTextNode( str.join( ' , ' ) + '\n' )
+ );
+ pre.appendChild( line );
+ };
+ }() );
- /**
- * Method called by jsduck to execute the example code.
- */
- function loadInlineExample( code, options, callback ) {
- try {
- eval( code );
- callback && callback( true );
- } catch (e) {
- mw.log( 'Uncaught exception: ' + e );
- callback && callback( false, e );
- throw e;
- }
- }
- </script>
+ /**
+ * Method called by jsduck to execute the example code.
+ */
+ function loadInlineExample( code, options, callback ) {
+ try {
+ eval( code );
+ callback && callback( true );
+ } catch ( e ) {
+ mw.log( 'Uncaught exception: ' + e );
+ callback && callback( false, e );
+ throw e;
+ }
+ }
+</script>
</body>
</html>
diff --git a/maintenance/lag.php b/maintenance/lag.php
index 410bf756..52f8201a 100644
--- a/maintenance/lag.php
+++ b/maintenance/lag.php
@@ -39,7 +39,9 @@ class DatabaseLag extends Maintenance {
if ( $this->hasOption( 'r' ) ) {
$lb = wfGetLB();
echo 'time ';
- for ( $i = 1; $i < $lb->getServerCount(); $i++ ) {
+
+ $serverCount = $lb->getServerCount();
+ for ( $i = 1; $i < $serverCount; $i++ ) {
$hostname = $lb->getServerName( $i );
printf( "%-12s ", $hostname );
}
diff --git a/maintenance/language/StatOutputs.php b/maintenance/language/StatOutputs.php
index e9d8c86d..31ce7024 100644
--- a/maintenance/language/StatOutputs.php
+++ b/maintenance/language/StatOutputs.php
@@ -1,7 +1,4 @@
<?php
-if ( !defined( 'MEDIAWIKI' ) ) {
- die();
-}
/**
* Statistic output classes.
*
@@ -27,57 +24,78 @@ if ( !defined( 'MEDIAWIKI' ) ) {
*/
/** A general output object. Need to be overriden */
-class statsOutput {
+class StatsOutput {
function formatPercent( $subset, $total, $revert = false, $accuracy = 2 ) {
- return @sprintf( '%.' . $accuracy . 'f%%', 100 * $subset / $total );
+ wfSuppressWarnings();
+ $return = sprintf( '%.' . $accuracy . 'f%%', 100 * $subset / $total );
+ wfRestoreWarnings();
+
+ return $return;
}
# Override the following methods
function heading() {
}
+
function footer() {
}
+
function blockstart() {
}
+
function blockend() {
}
+
function element( $in, $heading = false ) {
}
}
/** Outputs WikiText */
-class wikiStatsOutput extends statsOutput {
+class WikiStatsOutput extends StatsOutput {
function heading() {
global $wgDummyLanguageCodes;
$version = SpecialVersion::getVersion( 'nodb' );
echo "'''Statistics are based on:''' <code>" . $version . "</code>\n\n";
- echo "'''Note:''' These statistics can be generated by running <code>php maintenance/language/transstat.php</code>.\n\n";
- echo "For additional information on specific languages (the message names, the actual problems, etc.), run <code>php maintenance/language/checkLanguage.php --lang=foo</code>.\n\n";
+ echo "'''Note:''' These statistics can be generated by running " .
+ "<code>php maintenance/language/transstat.php</code>.\n\n";
+ echo "For additional information on specific languages (the message names, the actual " .
+ "problems, etc.), run <code>php maintenance/language/checkLanguage.php --lang=foo</code>.\n\n";
echo 'English (en) is excluded because it is the default localization';
if ( is_array( $wgDummyLanguageCodes ) ) {
$dummyCodes = array();
foreach ( $wgDummyLanguageCodes as $dummyCode => $correctCode ) {
$dummyCodes[] = Language::fetchLanguageName( $dummyCode ) . ' (' . $dummyCode . ')';
}
- echo ', as well as the following languages that are not intended for system message translations, usually because they redirect to other language codes: ' . implode( ', ', $dummyCodes );
+ echo ', as well as the following languages that are not intended for ' .
+ 'system message translations, usually because they redirect to other ' .
+ 'language codes: ' . implode( ', ', $dummyCodes );
}
echo ".\n\n"; # dot to end sentence
- echo '{| class="sortable wikitable" border="2" style="background-color: #F9F9F9; border: 1px #AAAAAA solid; border-collapse: collapse; clear:both; width:100%;"' . "\n";
+ echo '{| class="sortable wikitable" border="2" style="background-color: #F9F9F9; ' .
+ 'border: 1px #AAAAAA solid; border-collapse: collapse; clear:both; width:100%;"' . "\n";
}
+
function footer() {
echo "|}\n";
}
+
function blockstart() {
echo "|-\n";
}
+
function blockend() {
echo '';
}
+
function element( $in, $heading = false ) {
echo ( $heading ? '!' : '|' ) . "$in\n";
}
+
function formatPercent( $subset, $total, $revert = false, $accuracy = 2 ) {
- $v = @round( 255 * $subset / $total );
+ wfSuppressWarnings();
+ $v = round( 255 * $subset / $total );
+ wfRestoreWarnings();
+
if ( $revert ) {
# Weigh reverse with factor 20 so coloring takes effect more quickly as
# this option is used solely for reporting 'bad' percentages.
@@ -100,25 +118,28 @@ class wikiStatsOutput extends statsOutput {
$color = $red . $green . $blue;
$percent = parent::formatPercent( $subset, $total, $revert, $accuracy );
+
return 'style="background-color:#' . $color . ';"|' . $percent;
}
}
/** Output text. To be used on a terminal for example. */
-class textStatsOutput extends statsOutput {
+class TextStatsOutput extends StatsOutput {
function element( $in, $heading = false ) {
echo $in . "\t";
}
+
function blockend() {
echo "\n";
}
}
/** csv output. Some people love excel */
-class csvStatsOutput extends statsOutput {
+class CsvStatsOutput extends StatsOutput {
function element( $in, $heading = false ) {
echo $in . ";";
}
+
function blockend() {
echo "\n";
}
diff --git a/maintenance/language/checkDupeMessages.php b/maintenance/language/checkDupeMessages.php
index 381ddae1..5d482442 100644
--- a/maintenance/language/checkDupeMessages.php
+++ b/maintenance/language/checkDupeMessages.php
@@ -67,8 +67,7 @@ if ( $runTest ) {
$messagesFileC = $messagesDir . 'Messages' . $langCodeFC . '.php';
if ( file_exists( $messagesFile ) && file_exists( $messagesFileC ) ) {
$run = true;
- }
- else {
+ } else {
echo "Messages file(s) could not be found.\nMake sure both files are exists.\n";
}
}
diff --git a/maintenance/language/checkLanguage.inc b/maintenance/language/checkLanguage.inc
index 4b49ada3..990f2585 100644
--- a/maintenance/language/checkLanguage.inc
+++ b/maintenance/language/checkLanguage.inc
@@ -41,7 +41,7 @@ class CheckLanguageCLI {
/**
* Constructor.
- * @param $options array Options for script.
+ * @param array $options Options for script.
*/
public function __construct( array $options ) {
if ( isset( $options['help'] ) ) {
@@ -89,7 +89,7 @@ class CheckLanguageCLI {
$this->output = $options['output'];
}
- $this->L = new languages( $this->includeExif );
+ $this->L = new Languages( $this->includeExif );
}
/**
@@ -118,7 +118,7 @@ class CheckLanguageCLI {
/**
* Get the checks that can easily be treated by non-speakers of the language.
- * @return Array A list of the easy checks.
+ * @return array A list of the easy checks.
*/
protected function easyChecks() {
return array(
@@ -182,21 +182,25 @@ class CheckLanguageCLI {
return array(
'untranslated' => '$1 message(s) of $2 are not translated to $3, but exist in en:',
'duplicate' => '$1 message(s) of $2 are translated the same in en and $3:',
- 'obsolete' => '$1 message(s) of $2 do not exist in en or are in the ignore list, but exist in $3:',
+ 'obsolete' =>
+ '$1 message(s) of $2 do not exist in en or are in the ignore list, but exist in $3:',
'variables' => '$1 message(s) of $2 in $3 don\'t match the variables used in en:',
'plural' => '$1 message(s) of $2 in $3 don\'t use {{plural}} while en uses:',
'empty' => '$1 message(s) of $2 in $3 are empty or -:',
'whitespace' => '$1 message(s) of $2 in $3 have trailing whitespace:',
'xhtml' => '$1 message(s) of $2 in $3 contain illegal XHTML:',
- 'chars' => '$1 message(s) of $2 in $3 include hidden chars which should not be used in the messages:',
+ 'chars' =>
+ '$1 message(s) of $2 in $3 include hidden chars which should not be used in the messages:',
'links' => '$1 message(s) of $2 in $3 have problematic link(s):',
'unbalanced' => '$1 message(s) of $2 in $3 have unbalanced {[]}:',
'namespace' => '$1 namespace name(s) of $2 are not translated to $3, but exist in en:',
- 'projecttalk' => '$1 namespace name(s) and alias(es) in $3 are project talk namespaces without the parameter:',
+ 'projecttalk' =>
+ '$1 namespace name(s) and alias(es) in $3 are project talk namespaces without the parameter:',
'magic' => '$1 magic word(s) of $2 are not translated to $3, but exist in en:',
'magic-old' => '$1 magic word(s) of $2 do not exist in en, but exist in $3:',
'magic-over' => '$1 magic word(s) of $2 in $3 do not contain the original en word(s):',
- 'magic-case' => '$1 magic word(s) of $2 in $3 change the case-sensitivity of the original en word:',
+ 'magic-case' =>
+ '$1 magic word(s) of $2 in $3 change the case-sensitivity of the original en word:',
'special' => '$1 special page alias(es) of $2 are not translated to $3, but exist in en:',
'special-old' => '$1 special page alias(es) of $2 do not exist in en, but exist in $3:',
);
@@ -216,35 +220,49 @@ Parameters:
--all: Check all customized languages.
--level: Show the following display level (default: 2):
* 0: Skip the checks (useful for checking syntax).
- * 1: Show only the stub headers and number of wrong messages, without list of messages.
- * 2: Show only the headers and the message keys, without the message values.
- * 3: Show both the headers and the complete messages, with both keys and values.
+ * 1: Show only the stub headers and number of wrong messages, without
+ list of messages.
+ * 2: Show only the headers and the message keys, without the message
+ values.
+ * 3: Show both the headers and the complete messages, with both keys and
+ values.
--links: Link the message values (default off).
--prefix: prefix to add to links.
- --wikilang: For the links, what is the content language of the wiki to display the output in (default en).
- --noexif: Do not check for Exif messages (a bit hard and boring to translate), if you know
- that they are currently not translated and want to focus on other problems (default off).
+ --wikilang: For the links, what is the content language of the wiki to
+ display the output in (default en).
+ --noexif: Do not check for Exif messages (a bit hard and boring to
+ translate), if you know what they are currently not translated and want
+ to focus on other problems (default off).
--whitelist: Do only the following checks (form: code,code).
--blacklist: Do not do the following checks (form: code,code).
- --easy: Do only the easy checks, which can be treated by non-speakers of the language.
-
-Check codes (ideally, all of them should result 0; all the checks are executed by default (except language-specific check blacklists in checkLanguage.inc):
- * untranslated: Messages which are required to translate, but are not translated.
- * duplicate: Messages which translation equal to fallback
- * obsolete: Messages which are untranslatable or do not exist, but are translated.
- * variables: Messages without variables which should be used, or with variables which should not be used.
+ --easy: Do only the easy checks, which can be treated by non-speakers of
+ the language.
+
+Check codes (ideally, all of them should result 0; all the checks are executed
+by default (except language-specific check blacklists in checkLanguage.inc):
+ * untranslated: Messages which are required to translate, but are not
+ translated.
+ * duplicate: Messages which translation equal to fallback.
+ * obsolete: Messages which are untranslatable or do not exist, but are
+ translated.
+ * variables: Messages without variables which should be used, or with
+ variables which should not be used.
* empty: Empty messages and messages that contain only -.
* whitespace: Messages which have trailing whitespace.
- * xhtml: Messages which are not well-formed XHTML (checks only few common errors).
+ * xhtml: Messages which are not well-formed XHTML (checks only few common
+ errors).
* chars: Messages with hidden characters.
* links: Messages which contains broken links to pages (does not find all).
- * unbalanced: Messages which contains unequal numbers of opening {[ and closing ]}.
+ * unbalanced: Messages which contains unequal numbers of opening {[ and
+ closing ]}.
* namespace: Namespace names that were not translated.
- * projecttalk: Namespace names and aliases where the project talk does not contain $1.
+ * projecttalk: Namespace names and aliases where the project talk does not
+ contain $1.
* magic: Magic words that were not translated.
* magic-old: Magic words which do not exist.
* magic-over: Magic words that override the original English word.
- * magic-case: Magic words whose translation changes the case-sensitivity of the original English word.
+ * magic-case: Magic words whose translation changes the case-sensitivity of
+ the original English word.
* special: Special page names that were not translated.
* special-old: Special page names which do not exist.
@@ -291,6 +309,17 @@ ENDS;
$this->results[$this->code] = $this->checkLanguage( $this->code );
}
}
+
+ $results = $this->results;
+ foreach ( $results as $code => $checks ) {
+ foreach ( $checks as $check => $messages ) {
+ foreach ( $messages as $key => $details ) {
+ if ( $this->isCheckBlacklisted( $check, $code, $key ) ) {
+ unset( $this->results[$code][$check][$key] );
+ }
+ }
+ }
+ }
}
/**
@@ -298,14 +327,58 @@ ENDS;
* @return array The list of checks which should not be executed.
*/
protected function getCheckBlacklist() {
+ static $blacklist = null;
+
+ if ( $blacklist !== null ) {
+ return $blacklist;
+ }
+
+ // @codingStandardsIgnoreStart Ignore that globals should have a "wg" prefix.
global $checkBlacklist;
+ // @codingStandardsIgnoreEnd
+
+ $blacklist = $checkBlacklist;
+
+ wfRunHooks( 'LocalisationChecksBlacklist', array( &$blacklist ) );
+
+ return $blacklist;
+ }
+
+ /**
+ * Verify whether a check is blacklisted.
+ *
+ * @param string $check Check name
+ * @param string $code Language code
+ * @param string|bool $message Message name, or False for a whole language
+ * @return bool Whether the check is blacklisted
+ */
+ protected function isCheckBlacklisted( $check, $code, $message ) {
+ $blacklist = $this->getCheckBlacklist();
+
+ foreach ( $blacklist as $item ) {
+ if ( isset( $item['check'] ) && $check !== $item['check'] ) {
+ continue;
+ }
- return $checkBlacklist;
+ if ( isset( $item['code'] ) && !in_array( $code, $item['code'] ) ) {
+ continue;
+ }
+
+ if ( isset( $item['message'] ) &&
+ ( $message === false || !in_array( $message, $item['message'] ) )
+ ) {
+ continue;
+ }
+
+ return true;
+ }
+
+ return false;
}
/**
* Check a language.
- * @param $code string The language code.
+ * @param string $code The language code.
* @throws MWException
* @return array The results.
*/
@@ -319,11 +392,8 @@ ENDS;
}
$checkFunctions = $this->getChecks();
- $checkBlacklist = $this->getCheckBlacklist();
foreach ( $this->checks as $check ) {
- if ( isset( $checkBlacklist[$code] ) &&
- in_array( $check, $checkBlacklist[$code] )
- ) {
+ if ( $this->isCheckBlacklisted( $check, $code, false ) ) {
$results[$check] = array();
continue;
}
@@ -340,8 +410,8 @@ ENDS;
/**
* Format a message key.
- * @param $key string The message key.
- * @param $code string The language code.
+ * @param string $key The message key.
+ * @param string $code The language code.
* @return string The formatted message key.
*/
protected function formatKey( $key, $code ) {
@@ -407,7 +477,8 @@ ENDS;
*/
function outputWiki() {
$detailText = '';
- $rows[] = '! Language !! Code !! Total !! ' . implode( ' !! ', array_diff( $this->checks, $this->nonMessageChecks() ) );
+ $rows[] = '! Language !! Code !! Total !! ' .
+ implode( ' !! ', array_diff( $this->checks, $this->nonMessageChecks() ) );
foreach ( $this->results as $code => $results ) {
$detailTextForLang = "==$code==\n";
$numbers = array();
@@ -447,6 +518,7 @@ ENDS;
$tableRows = implode( "\n|-\n", $rows );
$version = SpecialVersion::getVersion( 'nodb' );
+ // @codingStandardsIgnoreStart Long line.
echo <<<EOL
'''Check results are for:''' <code>$version</code>
@@ -458,6 +530,7 @@ $tableRows
$detailText
EOL;
+ // @codingStandardsIgnoreEnd
}
/**
@@ -485,8 +558,8 @@ class CheckExtensionsCLI extends CheckLanguageCLI {
/**
* Constructor.
- * @param $options array Options for script.
- * @param $extension string The extension name (or names).
+ * @param array $options Options for script.
+ * @param string $extension The extension name (or names).
*/
public function __construct( array $options, $extension ) {
if ( isset( $options['help'] ) ) {
@@ -539,19 +612,19 @@ class CheckExtensionsCLI extends CheckLanguageCLI {
if ( $extension == 'all' ) {
foreach ( MessageGroups::singleton()->getGroups() as $group ) {
if ( strpos( $group->getId(), 'ext-' ) === 0 && !$group->isMeta() ) {
- $this->extensions[] = new extensionLanguages( $group );
+ $this->extensions[] = new ExtensionLanguages( $group );
}
}
} elseif ( $extension == 'wikimedia' ) {
$wikimedia = MessageGroups::getGroup( 'ext-0-wikimedia' );
foreach ( $wikimedia->wmfextensions() as $extension ) {
$group = MessageGroups::getGroup( $extension );
- $this->extensions[] = new extensionLanguages( $group );
+ $this->extensions[] = new ExtensionLanguages( $group );
}
} elseif ( $extension == 'flaggedrevs' ) {
foreach ( MessageGroups::singleton()->getGroups() as $group ) {
if ( strpos( $group->getId(), 'ext-flaggedrevs-' ) === 0 && !$group->isMeta() ) {
- $this->extensions[] = new extensionLanguages( $group );
+ $this->extensions[] = new ExtensionLanguages( $group );
}
}
} else {
@@ -559,7 +632,7 @@ class CheckExtensionsCLI extends CheckLanguageCLI {
foreach ( $extensions as $extension ) {
$group = MessageGroups::getGroup( 'ext-' . $extension );
if ( $group ) {
- $extension = new extensionLanguages( $group );
+ $extension = new ExtensionLanguages( $group );
$this->extensions[] = $extension;
} else {
print "No such extension $extension.\n";
@@ -589,7 +662,7 @@ class CheckExtensionsCLI extends CheckLanguageCLI {
/**
* Get the checks that can easily be treated by non-speakers of the language.
- * @return arrayA list of the easy checks.
+ * @return array A list of the easy checks.
*/
protected function easyChecks() {
return array(
@@ -603,34 +676,50 @@ class CheckExtensionsCLI extends CheckLanguageCLI {
*/
protected function help() {
return <<<ENDS
-Run this script to check the status of a specific language in extensions, or all of them.
-Command line settings are in form --parameter[=value], except for the first one.
+Run this script to check the status of a specific language in extensions, or
+all of them. Command line settings are in form --parameter[=value], except for
+the first one.
Parameters:
- * First parameter (mandatory): Extension name, multiple extension names (separated by commas), "all" for all the extensions, "wikimedia" for extensions used by Wikimedia or "flaggedrevs" for all FLaggedRevs extension messages.
+ * First parameter (mandatory): Extension name, multiple extension names
+ (separated by commas), "all" for all the extensions, "wikimedia" for
+ extensions used by Wikimedia or "flaggedrevs" for all FLaggedRevs
+ extension messages.
* lang: Language code (default: the installation default language).
* help: Show this help.
* level: Show the following display level (default: 2).
* links: Link the message values (default off).
- * wikilang: For the links, what is the content language of the wiki to display the output in (default en).
+ * wikilang: For the links, what is the content language of the wiki to
+ display the output in (default en).
* whitelist: Do only the following checks (form: code,code).
* blacklist: Do not perform the following checks (form: code,code).
- * easy: Do only the easy checks, which can be treated by non-speakers of the language.
-Check codes (ideally, all of them should result 0; all the checks are executed by default (except language-specific check blacklists in checkLanguage.inc):
- * untranslated: Messages which are required to translate, but are not translated.
- * duplicate: Messages which translation equal to fallback
+ * easy: Do only the easy checks, which can be treated by non-speakers of
+ the language.
+
+Check codes (ideally, all of them should result 0; all the checks are executed
+by default (except language-specific check blacklists in checkLanguage.inc):
+ * untranslated: Messages which are required to translate, but are not
+ translated.
+ * duplicate: Messages which translation equal to fallback.
* obsolete: Messages which are untranslatable, but translated.
- * variables: Messages without variables which should be used, or with variables which should not be used.
+ * variables: Messages without variables which should be used, or with
+ variables which should not be used.
* empty: Empty messages.
* whitespace: Messages which have trailing whitespace.
- * xhtml: Messages which are not well-formed XHTML (checks only few common errors).
+ * xhtml: Messages which are not well-formed XHTML (checks only few common
+ errors).
* chars: Messages with hidden characters.
* links: Messages which contains broken links to pages (does not find all).
- * unbalanced: Messages which contains unequal numbers of opening {[ and closing ]}.
+ * unbalanced: Messages which contains unequal numbers of opening {[ and
+ closing ]}.
+
Display levels (default: 2):
* 0: Skip the checks (useful for checking syntax).
- * 1: Show only the stub headers and number of wrong messages, without list of messages.
- * 2: Show only the headers and the message keys, without the message values.
- * 3: Show both the headers and the complete messages, with both keys and values.
+ * 1: Show only the stub headers and number of wrong messages, without list
+ of messages.
+ * 2: Show only the headers and the message keys, without the message
+ values.
+ * 3: Show both the headers and the complete messages, with both keys and
+ values.
ENDS;
}
@@ -644,7 +733,7 @@ ENDS;
/**
* Check a language and show the results.
- * @param $code string The language code.
+ * @param string $code The language code.
* @throws MWException
*/
protected function checkLanguage( $code ) {
@@ -675,52 +764,21 @@ ENDS;
}
}
-# Blacklist some checks for some languages
+// Blacklist some checks for some languages or some messages
+// Possible keys of the sub arrays are: 'check', 'code' and 'message'.
$checkBlacklist = array(
-#'code' => array( 'check1', 'check2' ... )
- 'az' => array( 'plural' ),
- 'bo' => array( 'plural' ),
- 'cdo' => array( 'plural' ),
- 'dz' => array( 'plural' ),
- 'id' => array( 'plural' ),
- 'fa' => array( 'plural' ),
- 'gan' => array( 'plural' ),
- 'gan-hans' => array( 'plural' ),
- 'gan-hant' => array( 'plural' ),
- 'gn' => array( 'plural' ),
- 'hak' => array( 'plural' ),
- 'hu' => array( 'plural' ),
- 'ja' => array( 'plural' ), // Does not use plural
- 'jv' => array( 'plural' ),
- 'ka' => array( 'plural' ),
- 'kk-arab' => array( 'plural' ),
- 'kk-cyrl' => array( 'plural' ),
- 'kk-latn' => array( 'plural' ),
- 'km' => array( 'plural' ),
- 'kn' => array( 'plural' ),
- 'ko' => array( 'plural' ),
- 'lzh' => array( 'plural' ),
- 'mn' => array( 'plural' ),
- 'ms' => array( 'plural' ),
- 'my' => array( 'plural', 'chars' ), // Uses a lot zwnj
- 'sah' => array( 'plural' ),
- 'sq' => array( 'plural' ),
- 'tet' => array( 'plural' ),
- 'th' => array( 'plural' ),
- 'to' => array( 'plural' ),
- 'tr' => array( 'plural' ),
- 'vi' => array( 'plural' ),
- 'wuu' => array( 'plural' ),
- 'xmf' => array( 'plural' ),
- 'yo' => array( 'plural' ),
- 'yue' => array( 'plural' ),
- 'zh' => array( 'plural' ),
- 'zh-classical' => array( 'plural' ),
- 'zh-cn' => array( 'plural' ),
- 'zh-hans' => array( 'plural' ),
- 'zh-hant' => array( 'plural' ),
- 'zh-hk' => array( 'plural' ),
- 'zh-sg' => array( 'plural' ),
- 'zh-tw' => array( 'plural' ),
- 'zh-yue' => array( 'plural' ),
+ array(
+ 'check' => 'plural',
+ 'code' => array( 'az', 'bo', 'cdo', 'dz', 'id', 'fa', 'gan', 'gan-hans',
+ 'gan-hant', 'gn', 'hak', 'hu', 'ja', 'jv', 'ka', 'kk-arab',
+ 'kk-cyrl', 'kk-latn', 'km', 'kn', 'ko', 'lzh', 'mn', 'ms',
+ 'my', 'sah', 'sq', 'tet', 'th', 'to', 'tr', 'vi', 'wuu', 'xmf',
+ 'yo', 'yue', 'zh', 'zh-classical', 'zh-cn', 'zh-hans',
+ 'zh-hant', 'zh-hk', 'zh-sg', 'zh-tw', 'zh-yue'
+ ),
+ ),
+ array(
+ 'check' => 'chars',
+ 'code' => array( 'my' ),
+ ),
);
diff --git a/maintenance/language/countMessages.php b/maintenance/language/countMessages.php
deleted file mode 100644
index 95a7154b..00000000
--- a/maintenance/language/countMessages.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-/**
- * Count how many messages we have defined for each language.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup MaintenanceLanguage
- */
-
-require_once __DIR__ . '/../Maintenance.php';
-
-/**
- * Maintenance script that counts how many messages we have defined
- * for each language.
- *
- * @ingroup MaintenanceLanguage
- */
-class CountMessages extends Maintenance {
- public function __construct() {
- parent::__construct();
- $this->mDescription = "Count how many messages we have defined for each language";
- }
-
- public function execute() {
- global $IP;
- $dir = $this->getArg( 0, "$IP/languages/messages" );
- $total = 0;
- $nonZero = 0;
- foreach ( glob( "$dir/*.php" ) as $file ) {
- $baseName = basename( $file );
- if ( !preg_match( '/Messages([A-Z][a-z_]+)\.php$/', $baseName, $m ) ) {
- continue;
- }
-
- $numMessages = $this->getNumMessages( $file );
- // print "$code: $numMessages\n";
- $total += $numMessages;
- if ( $numMessages > 0 ) {
- $nonZero ++;
- }
- }
- $this->output( "\nTotal: $total\n" );
- $this->output( "Languages: $nonZero\n" );
- }
-
- private function getNumMessages( $file ) {
- // Separate function to limit scope
- require $file;
- if ( isset( $messages ) ) {
- return count( $messages );
- } else {
- return 0;
- }
- }
-}
-
-$maintClass = "CountMessages";
-require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/language/generateCollationData.php b/maintenance/language/generateCollationData.php
index fcf2c960..973cf7bc 100644
--- a/maintenance/language/generateCollationData.php
+++ b/maintenance/language/generateCollationData.php
@@ -48,7 +48,7 @@ class GenerateCollationData extends Maintenance {
* Important tertiary weights from UTS #10 section 7.2
*/
const NORMAL_UPPERCASE = 0x08;
- const NORMAL_HIRAGANA = 0X0E;
+ const NORMAL_HIRAGANA = 0x0E;
public function __construct() {
parent::__construct();
@@ -158,7 +158,8 @@ class GenerateCollationData extends Maintenance {
// people like to use that as a fake no header symbol.
$category = substr( $data['gc'], 0, 1 );
if ( strpos( 'LNPS', $category ) === false
- && $data['cp'] !== '0020' ) {
+ && $data['cp'] !== '0020'
+ ) {
return;
}
$cp = hexdec( $data['cp'] );
@@ -178,8 +179,8 @@ class GenerateCollationData extends Maintenance {
// Calculate implicit weight per UTS #10 v6.0.0, sec 7.1.3
if ( $data['UIdeo'] === 'Y' ) {
if ( $data['block'] == 'CJK Unified Ideographs'
- || $data['block'] == 'CJK Compatibility Ideographs' )
- {
+ || $data['block'] == 'CJK Compatibility Ideographs'
+ ) {
$base = 0xFB40;
} else {
$base = 0xFB80;
@@ -248,8 +249,8 @@ class GenerateCollationData extends Maintenance {
}
$this->weights[$cp] = $primary;
if ( $tertiary === '.0008'
- || $tertiary === '.000E' )
- {
+ || $tertiary === '.000E'
+ ) {
$goodTertiaryChars[$cp] = true;
}
}
@@ -325,7 +326,7 @@ class GenerateCollationData extends Maintenance {
$char = codepointToUtf8( $cp );
$headerChars[] = $char;
if ( $primaryCollator->compare( $char, $prevChar ) <= 0 ) {
- $numOutOfOrder ++;
+ $numOutOfOrder++;
/*
printf( "Out of order: U+%05X > U+%05X\n",
utf8ToCodepoint( $prevChar ),
@@ -390,6 +391,7 @@ class UcdXmlReader {
}
while ( $this->xml->name !== 'ucd' && $this->xml->read() );
$this->xml->read();
+
return $this->xml;
}
@@ -403,6 +405,7 @@ class UcdXmlReader {
while ( $this->xml->moveToNextAttribute() ) {
$attrs[$this->xml->name] = $this->xml->value;
}
+
return $attrs;
}
@@ -460,9 +463,9 @@ class UcdXmlReader {
}
}
$xml->close();
+
return $this->blocks;
}
-
}
$maintClass = 'GenerateCollationData';
diff --git a/maintenance/language/generateNormalizerData.php b/maintenance/language/generateNormalizerDataAr.php
index 216445e4..ece0450f 100644
--- a/maintenance/language/generateNormalizerData.php
+++ b/maintenance/language/generateNormalizerDataAr.php
@@ -1,6 +1,6 @@
<?php
/**
- * Generates normalizer data files for Arabic and Malayalam.
+ * Generates the normalizer data file for Arabic.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,46 +21,43 @@
* @ingroup MaintenanceLanguage
*/
-require_once __DIR__ . '/../../includes/normal/UtfNormalUtil.php';
-
require_once __DIR__ . '/../Maintenance.php';
/**
- * Generates normalizer data files for Arabic and Malayalam.
+ * Generates the normalizer data file for Arabic.
* For NFC see includes/normal.
*
* @ingroup MaintenanceLanguage
*/
-class GenerateNormalizerData extends Maintenance {
- public $dataFile;
-
+class GenerateNormalizerDataAr extends Maintenance {
public function __construct() {
parent::__construct();
+ $this->mDescription = 'Generate the normalizer data file for Arabic';
$this->addOption( 'unicode-data-file', 'The local location of the data file ' .
'from http://unicode.org/Public/UNIDATA/UnicodeData.txt', false, true );
}
+ public function getDbType() {
+ return Maintenance::DB_NONE;
+ }
+
public function execute() {
if ( !$this->hasOption( 'unicode-data-file' ) ) {
- $this->dataFile = 'UnicodeData.txt';
- if ( !file_exists( $this->dataFile ) ) {
- $this->error( "Unable to find UnicodeData.txt. Please specify its location with --unicode-data-file=<FILE>" );
+ $dataFile = 'UnicodeData.txt';
+ if ( !file_exists( $dataFile ) ) {
+ $this->error( "Unable to find UnicodeData.txt. Please specify " .
+ "its location with --unicode-data-file=<FILE>" );
exit( 1 );
}
} else {
- $this->dataFile = $this->getOption( 'unicode-data-file' );
- if ( !file_exists( $this->dataFile ) ) {
+ $dataFile = $this->getOption( 'unicode-data-file' );
+ if ( !file_exists( $dataFile ) ) {
$this->error( 'Unable to find the specified data file.' );
exit( 1 );
}
}
- $this->generateArabic();
- $this->generateMalayalam();
- }
-
- function generateArabic() {
- $file = fopen( $this->dataFile, 'r' );
+ $file = fopen( $dataFile, 'r' );
if ( !$file ) {
$this->error( 'Unable to open the data file.' );
exit( 1 );
@@ -74,7 +71,9 @@ class GenerateNormalizerData extends Maintenance {
'Canonical_Combining_Class',
'Bidi_Class',
'Decomposition_Type_Mapping',
- 'Numeric_Type_Value',
+ 'Numeric_Type_Value_6',
+ 'Numeric_Type_Value_7',
+ 'Numeric_Type_Value_8',
'Bidi_Mirrored',
'Unicode_1_Name',
'ISO_Comment',
@@ -104,15 +103,15 @@ class GenerateNormalizerData extends Maintenance {
$code = base_convert( $data['Code'], 16, 10 );
if ( ( $code >= 0xFB50 && $code <= 0xFDFF ) # Arabic presentation forms A
- || ( $code >= 0xFE70 && $code <= 0xFEFF ) ) # Arabic presentation forms B
- {
+ || ( $code >= 0xFE70 && $code <= 0xFEFF ) # Arabic presentation forms B
+ ) {
if ( $data['Decomposition_Type_Mapping'] === '' ) {
// No decomposition
continue;
}
if ( !preg_match( '/^ *(<\w*>) +([0-9A-F ]*)$/',
- $data['Decomposition_Type_Mapping'], $m ) )
- {
+ $data['Decomposition_Type_Mapping'], $m )
+ ) {
$this->error( "Can't parse Decomposition_Type/Mapping on line $lineNum" );
$this->error( $line );
continue;
@@ -128,32 +127,7 @@ class GenerateNormalizerData extends Maintenance {
file_put_contents( "$IP/serialized/normalize-ar.ser", serialize( $pairs ) );
echo "ar: " . count( $pairs ) . " pairs written.\n";
}
-
- function generateMalayalam() {
- $hexPairs = array(
- # From http://unicode.org/versions/Unicode5.1.0/#Malayalam_Chillu_Characters
- '0D23 0D4D 200D' => '0D7A',
- '0D28 0D4D 200D' => '0D7B',
- '0D30 0D4D 200D' => '0D7C',
- '0D32 0D4D 200D' => '0D7D',
- '0D33 0D4D 200D' => '0D7E',
-
- # From http://permalink.gmane.org/gmane.science.linguistics.wikipedia.technical/46413
- '0D15 0D4D 200D' => '0D7F',
- );
-
- $pairs = array();
- foreach ( $hexPairs as $hexSource => $hexDest ) {
- $source = hexSequenceToUtf8( $hexSource );
- $dest = hexSequenceToUtf8( $hexDest );
- $pairs[$source] = $dest;
- }
-
- global $IP;
- file_put_contents( "$IP/serialized/normalize-ml.ser", serialize( $pairs ) );
- echo "ml: " . count( $pairs ) . " pairs written.\n";
- }
}
-$maintClass = 'GenerateNormalizerData';
+$maintClass = 'GenerateNormalizerDataAr';
require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/language/generateNormalizerDataMl.php b/maintenance/language/generateNormalizerDataMl.php
new file mode 100644
index 00000000..c7237cfe
--- /dev/null
+++ b/maintenance/language/generateNormalizerDataMl.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Generates the normalizer data file for Malayalam.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup MaintenanceLanguage
+ */
+
+require_once __DIR__ . '/../Maintenance.php';
+
+/**
+ * Generates the normalizer data file for Malayalam.
+ * For NFC see includes/normal.
+ *
+ * @ingroup MaintenanceLanguage
+ */
+class GenerateNormalizerDataMl extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = 'Generate the normalizer data file for Malayalam';
+ }
+
+ public function getDbType() {
+ return Maintenance::DB_NONE;
+ }
+
+ public function execute() {
+ $hexPairs = array(
+ # From http://unicode.org/versions/Unicode5.1.0/#Malayalam_Chillu_Characters
+ '0D23 0D4D 200D' => '0D7A',
+ '0D28 0D4D 200D' => '0D7B',
+ '0D30 0D4D 200D' => '0D7C',
+ '0D32 0D4D 200D' => '0D7D',
+ '0D33 0D4D 200D' => '0D7E',
+
+ # From http://permalink.gmane.org/gmane.science.linguistics.wikipedia.technical/46413
+ '0D15 0D4D 200D' => '0D7F',
+ );
+
+ $pairs = array();
+ foreach ( $hexPairs as $hexSource => $hexDest ) {
+ $source = hexSequenceToUtf8( $hexSource );
+ $dest = hexSequenceToUtf8( $hexDest );
+ $pairs[$source] = $dest;
+ }
+
+ global $IP;
+ file_put_contents( "$IP/serialized/normalize-ml.ser", serialize( $pairs ) );
+ echo "ml: " . count( $pairs ) . " pairs written.\n";
+ }
+}
+
+$maintClass = 'GenerateNormalizerDataMl';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/language/generateUtf8Case.php b/maintenance/language/generateUtf8Case.php
new file mode 100644
index 00000000..0fd32427
--- /dev/null
+++ b/maintenance/language/generateUtf8Case.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * Generates Utf8Case.ser from the Unicode Character Database and
+ * supplementary files.
+ *
+ * Copyright © 2004, 2008 Brion Vibber <brion@pobox.com>
+ * https://www.mediawiki.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup MaintenanceLanguage
+ */
+
+require_once __DIR__ . '/../Maintenance.php';
+
+/**
+ * Generates Utf8Case.ser from the Unicode Character Database and
+ * supplementary files.
+ *
+ * @ingroup MaintenanceLanguage
+ */
+class GenerateUtf8Case extends Maintenance {
+
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = 'Generate Utf8Case.ser from the Unicode Character Database ' .
+ 'and supplementary files';
+ $this->addOption( 'unicode-data-file', 'The local location of the data file ' .
+ 'from http://unicode.org/Public/UNIDATA/UnicodeData.txt', false, true );
+ }
+
+ public function getDbType() {
+ return Maintenance::DB_NONE;
+ }
+
+ public function execute() {
+ if ( !$this->hasOption( 'unicode-data-file' ) ) {
+ $dataFile = 'UnicodeData.txt';
+ if ( !file_exists( $dataFile ) ) {
+ $this->error( "Unable to find UnicodeData.txt. Please specify " .
+ "its location with --unicode-data-file=<FILE>" );
+ exit( 1 );
+ }
+ } else {
+ $dataFile = $this->getOption( 'unicode-data-file' );
+ if ( !file_exists( $dataFile ) ) {
+ $this->error( 'Unable to find the specified data file.' );
+ exit( 1 );
+ }
+ }
+
+ $file = fopen( $dataFile, 'r' );
+ if ( !$file ) {
+ $this->error( 'Unable to open the data file.' );
+ exit( 1 );
+ }
+
+ // For the file format, see http://www.unicode.org/reports/tr44/
+ $fieldNames = array(
+ 'Code',
+ 'Name',
+ 'General_Category',
+ 'Canonical_Combining_Class',
+ 'Bidi_Class',
+ 'Decomposition_Type_Mapping',
+ 'Numeric_Type_Value_6',
+ 'Numeric_Type_Value_7',
+ 'Numeric_Type_Value_8',
+ 'Bidi_Mirrored',
+ 'Unicode_1_Name',
+ 'ISO_Comment',
+ 'Simple_Uppercase_Mapping',
+ 'Simple_Lowercase_Mapping',
+ 'Simple_Titlecase_Mapping'
+ );
+
+ $upper = array();
+ $lower = array();
+
+ $lineNum = 0;
+ while ( false !== ( $line = fgets( $file ) ) ) {
+ ++$lineNum;
+
+ # Strip comments
+ $line = trim( substr( $line, 0, strcspn( $line, '#' ) ) );
+ if ( $line === '' ) {
+ continue;
+ }
+
+ # Split fields
+ $numberedData = explode( ';', $line );
+ $data = array();
+ foreach ( $fieldNames as $number => $name ) {
+ $data[$name] = $numberedData[$number];
+ }
+
+ $source = hexSequenceToUtf8( $data['Code'] );
+ if ( $data['Simple_Uppercase_Mapping'] ) {
+ $upper[$source] = hexSequenceToUtf8( $data['Simple_Uppercase_Mapping'] );
+ }
+ if ( $data['Simple_Lowercase_Mapping'] ) {
+ $lower[$source] = hexSequenceToUtf8( $data['Simple_Lowercase_Mapping'] );
+ }
+ }
+
+ global $IP;
+ file_put_contents( "$IP/serialized/Utf8Case.ser", serialize( array(
+ 'wikiUpperChars' => $upper,
+ 'wikiLowerChars' => $lower,
+ ) ) );
+ }
+}
+
+$maintClass = 'GenerateUtf8Case';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/language/langmemusage.php b/maintenance/language/langmemusage.php
index 14485f98..32cfcd7d 100644
--- a/maintenance/language/langmemusage.php
+++ b/maintenance/language/langmemusage.php
@@ -43,7 +43,7 @@ class LangMemUsage extends Maintenance {
$this->error( "You must compile PHP with --enable-memory-limit", true );
}
- $langtool = new languages();
+ $langtool = new Languages();
$memlast = $memstart = memory_get_usage();
$this->output( "Base memory usage: $memstart\n" );
diff --git a/maintenance/language/languages.inc b/maintenance/language/languages.inc
index 6070f4ab..fb496cbc 100644
--- a/maintenance/language/languages.inc
+++ b/maintenance/language/languages.inc
@@ -24,35 +24,47 @@
/**
* @ingroup MaintenanceLanguage
*/
-class languages {
- protected $mLanguages; # List of languages
+class Languages {
+ /** @var array List of languages */
+ protected $mLanguages;
- protected $mRawMessages; # Raw list of the messages in each language
- protected $mMessages; # Messages in each language (except for English), divided to groups
- protected $mFallback; # Fallback language in each language
- protected $mGeneralMessages; # General messages in English, divided to groups
- protected $mIgnoredMessages; # All the messages which should be exist only in the English file
- protected $mOptionalMessages; # All the messages which may be translated or not, depending on the language
+ /** @var array Raw list of the messages in each language */
+ protected $mRawMessages;
- protected $mNamespaceNames; # Namespace names
- protected $mNamespaceAliases; # Namespace aliases
- protected $mMagicWords; # Magic words
- protected $mSpecialPageAliases; # Special page aliases
+ /** @var array Messages in each language (except for English), divided to groups */
+ protected $mMessages;
+
+ /** @var array Fallback language in each language */
+ protected $mFallback;
+
+ /** @var array General messages in English, divided to groups */
+ protected $mGeneralMessages;
+
+ /** @var array All the messages which should be exist only in the English file */
+ protected $mIgnoredMessages;
+
+ /** @var array All the messages which may be translated or not, depending on the language */
+ protected $mOptionalMessages;
+
+ /** @var array Namespace names */
+ protected $mNamespaceNames;
+
+ /** @var array Namespace aliases */
+ protected $mNamespaceAliases;
+
+ /** @var array Magic words */
+ protected $mMagicWords;
+
+ /** @var array Special page aliases */
+ protected $mSpecialPageAliases;
/**
* Load the list of languages: all the Messages*.php
* files in the languages directory.
- *
- * @param $exif bool Treat the Exif messages?
*/
- function __construct( $exif = true ) {
- require __DIR__ . '/messageTypes.inc';
- $this->mIgnoredMessages = $wgIgnoredMessages;
- if ( $exif ) {
- $this->mOptionalMessages = array_merge( $wgOptionalMessages );
- } else {
- $this->mOptionalMessages = array_merge( $wgOptionalMessages, $wgEXIFMessages );
- }
+ function __construct() {
+ wfRunHooks( 'LocalisationIgnoredOptionalMessages',
+ array( &$this->mIgnoredMessages, &$this->mOptionalMessages ) );
$this->mLanguages = array_keys( Language::fetchLanguageNames( null, 'mwfile' ) );
sort( $this->mLanguages );
@@ -88,7 +100,7 @@ class languages {
/**
* Load the language file.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*/
protected function loadFile( $code ) {
if ( isset( $this->mRawMessages[$code] ) &&
@@ -96,7 +108,8 @@ class languages {
isset( $this->mNamespaceNames[$code] ) &&
isset( $this->mNamespaceAliases[$code] ) &&
isset( $this->mMagicWords[$code] ) &&
- isset( $this->mSpecialPageAliases[$code] ) ) {
+ isset( $this->mSpecialPageAliases[$code] )
+ ) {
return;
}
$this->mRawMessages[$code] = array();
@@ -105,12 +118,16 @@ class languages {
$this->mNamespaceAliases[$code] = array();
$this->mMagicWords[$code] = array();
$this->mSpecialPageAliases[$code] = array();
+
+ $jsonfilename = Language::getJsonMessagesFileName( $code );
+ if ( file_exists( $jsonfilename ) ) {
+ $json = Language::getLocalisationCache()->readJSONFile( $jsonfilename );
+ $this->mRawMessages[$code] = $json['messages'];
+ }
+
$filename = Language::getMessagesFileName( $code );
if ( file_exists( $filename ) ) {
require $filename;
- if ( isset( $messages ) ) {
- $this->mRawMessages[$code] = $messages;
- }
if ( isset( $fallback ) ) {
$this->mFallback[$code] = $fallback;
}
@@ -130,14 +147,18 @@ class languages {
}
/**
- * Load the messages for a specific language (which is not English) and divide them to groups:
+ * Load the messages for a specific language (which is not English) and divide them to
+ * groups:
* all - all the messages.
* required - messages which should be translated in order to get a complete translation.
- * optional - messages which can be translated, the fallback translation is used if not translated.
- * obsolete - messages which should not be translated, either because they do not exist, or they are ignored messages.
- * translated - messages which are either required or optional, but translated from English and needed.
+ * optional - messages which can be translated, the fallback translation is used if not
+ * translated.
+ * obsolete - messages which should not be translated, either because they do not exist,
+ * or they are ignored messages.
+ * translated - messages which are either required or optional, but translated from
+ * English and needed.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*/
private function loadMessages( $code ) {
if ( isset( $this->mMessages[$code] ) ) {
@@ -166,10 +187,13 @@ class languages {
/**
* Load the messages for English and divide them to groups:
* all - all the messages.
- * required - messages which should be translated to other languages in order to get a complete translation.
- * optional - messages which can be translated to other languages, but it's not required for a complete translation.
+ * required - messages which should be translated to other languages in order to get a
+ * complete translation.
+ * optional - messages which can be translated to other languages, but it's not required
+ * for a complete translation.
* ignored - messages which should not be translated to other languages.
- * translatable - messages which are either required or optional, but can be translated from English.
+ * translatable - messages which are either required or optional, but can be translated
+ * from English.
*/
private function loadGeneralMessages() {
if ( isset( $this->mGeneralMessages ) ) {
@@ -199,111 +223,125 @@ class languages {
* fallback language messages, divided to groups:
* all - all the messages.
* required - messages which should be translated in order to get a complete translation.
- * optional - messages which can be translated, the fallback translation is used if not translated.
- * obsolete - messages which should not be translated, either because they do not exist, or they are ignored messages.
- * translated - messages which are either required or optional, but translated from English and needed.
+ * optional - messages which can be translated, the fallback translation is used if not
+ * translated.
+ * obsolete - messages which should not be translated, either because they do not exist,
+ * or they are ignored messages.
+ * translated - messages which are either required or optional, but translated from
+ * English and needed.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return string The messages in this language.
*/
public function getMessages( $code ) {
$this->loadMessages( $code );
+
return $this->mMessages[$code];
}
/**
* Get all the general English messages, divided to groups:
* all - all the messages.
- * required - messages which should be translated to other languages in order to get a complete translation.
- * optional - messages which can be translated to other languages, but it's not required for a complete translation.
+ * required - messages which should be translated to other languages in
+ * order to get a complete translation.
+ * optional - messages which can be translated to other languages, but it's
+ * not required for a complete translation.
* ignored - messages which should not be translated to other languages.
- * translatable - messages which are either required or optional, but can be translated from English.
+ * translatable - messages which are either required or optional, but can be
+ * translated from English.
*
* @return array The general English messages.
*/
public function getGeneralMessages() {
$this->loadGeneralMessages();
+
return $this->mGeneralMessages;
}
/**
* Get fallback language code for a specific language.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return string Fallback code.
*/
public function getFallback( $code ) {
$this->loadFile( $code );
+
return $this->mFallback[$code];
}
/**
* Get namespace names for a specific language.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array Namespace names.
*/
public function getNamespaceNames( $code ) {
$this->loadFile( $code );
+
return $this->mNamespaceNames[$code];
}
/**
* Get namespace aliases for a specific language.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array Namespace aliases.
*/
public function getNamespaceAliases( $code ) {
$this->loadFile( $code );
+
return $this->mNamespaceAliases[$code];
}
/**
* Get magic words for a specific language.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array Magic words.
*/
public function getMagicWords( $code ) {
$this->loadFile( $code );
+
return $this->mMagicWords[$code];
}
/**
* Get special page aliases for a specific language.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array Special page aliases.
*/
public function getSpecialPageAliases( $code ) {
$this->loadFile( $code );
+
return $this->mSpecialPageAliases[$code];
}
/**
* Get the untranslated messages for a specific language.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The untranslated messages for this language.
*/
public function getUntranslatedMessages( $code ) {
$this->loadGeneralMessages();
$this->loadMessages( $code );
+
return array_diff_key( $this->mGeneralMessages['required'], $this->mMessages[$code]['required'] );
}
/**
* Get the duplicate messages for a specific language.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The duplicate messages for this language.
*/
@@ -316,26 +354,28 @@ class languages {
$duplicateMessages[$key] = $value;
}
}
+
return $duplicateMessages;
}
/**
* Get the obsolete messages for a specific language.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The obsolete messages for this language.
*/
public function getObsoleteMessages( $code ) {
$this->loadGeneralMessages();
$this->loadMessages( $code );
+
return $this->mMessages[$code]['obsolete'];
}
/**
* Get the messages whose variables do not match the original ones.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The messages whose variables do not match the original ones.
*/
@@ -348,11 +388,13 @@ class languages {
$missing = false;
foreach ( $variables as $var ) {
if ( preg_match( "/$var/sU", $this->mGeneralMessages['translatable'][$key] ) &&
- !preg_match( "/$var/sU", $value ) ) {
+ !preg_match( "/$var/sU", $value )
+ ) {
$missing = true;
}
if ( !preg_match( "/$var/sU", $this->mGeneralMessages['translatable'][$key] ) &&
- preg_match( "/$var/sU", $value ) ) {
+ preg_match( "/$var/sU", $value )
+ ) {
$missing = true;
}
}
@@ -360,13 +402,14 @@ class languages {
$mismatchMessages[$key] = $value;
}
}
+
return $mismatchMessages;
}
/**
* Get the messages which do not use plural.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The messages which do not use plural in this language.
*/
@@ -375,17 +418,20 @@ class languages {
$this->loadMessages( $code );
$messagesWithoutPlural = array();
foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
- if ( stripos( $this->mGeneralMessages['translatable'][$key], '{{plural:' ) !== false && stripos( $value, '{{plural:' ) === false ) {
+ if ( stripos( $this->mGeneralMessages['translatable'][$key], '{{plural:' ) !== false &&
+ stripos( $value, '{{plural:' ) === false
+ ) {
$messagesWithoutPlural[$key] = $value;
}
}
+
return $messagesWithoutPlural;
}
/**
* Get the empty messages.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The empty messages for this language.
*/
@@ -398,13 +444,14 @@ class languages {
$emptyMessages[$key] = $value;
}
}
+
return $emptyMessages;
}
/**
* Get the messages with trailing whitespace.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The messages with trailing whitespace in this language.
*/
@@ -417,13 +464,14 @@ class languages {
$messagesWithWhitespace[$key] = $value;
}
}
+
return $messagesWithWhitespace;
}
/**
* Get the non-XHTML messages.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The non-XHTML messages for this language.
*/
@@ -445,13 +493,14 @@ class languages {
$nonXHTMLMessages[$key] = $value;
}
}
+
return $nonXHTMLMessages;
}
/**
* Get the messages which include wrong characters.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The messages which include wrong characters in this language.
*/
@@ -482,13 +531,14 @@ class languages {
$wrongCharsMessages[$key] = $value;
}
}
+
return $wrongCharsMessages;
}
/**
* Get the messages which include dubious links.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The messages which include dubious links in this language.
*/
@@ -500,24 +550,25 @@ class languages {
foreach ( $this->mMessages[$code]['translated'] as $key => $value ) {
$matches = array();
preg_match_all( "/\[\[([{$tc}]+)(?:\\|(.+?))?]]/sDu", $value, $matches );
- for ( $i = 0; $i < count( $matches[0] ); $i++ ) {
+ $numMatches = count( $matches[0] );
+ for ( $i = 0; $i < $numMatches; $i++ ) {
if ( preg_match( "/.*project.*/isDu", $matches[1][$i] ) ) {
$messages[$key][] = $matches[0][$i];
}
}
-
if ( isset( $messages[$key] ) ) {
$messages[$key] = implode( $messages[$key], ", " );
}
}
+
return $messages;
}
/**
* Get the messages which include unbalanced brackets.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The messages which include unbalanced brackets in this language.
*/
@@ -547,15 +598,15 @@ class languages {
if ( $a !== $b || $c !== $d ) {
$messages[$key] = "$a, $b, $c, $d";
}
-
}
+
return $messages;
}
/**
* Get the untranslated namespace names.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The untranslated namespace names in this language.
*/
@@ -566,13 +617,14 @@ class languages {
if ( isset( $namespacesDiff[NS_MAIN] ) ) {
unset( $namespacesDiff[NS_MAIN] );
}
+
return $namespacesDiff;
}
/**
* Get the project talk namespace names with no $1.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The problematic project talk namespaces in this language.
*/
@@ -601,7 +653,7 @@ class languages {
/**
* Get the untranslated magic words.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The untranslated magic words in this language.
*/
@@ -614,13 +666,14 @@ class languages {
$magicWords[$key] = $value[1];
}
}
+
return $magicWords;
}
/**
* Get the obsolete magic words.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The obsolete magic words in this language.
*/
@@ -633,13 +686,14 @@ class languages {
$magicWords[$key] = $value[1];
}
}
+
return $magicWords;
}
/**
* Get the magic words that override the original English magic word.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The overriding magic words in this language.
*/
@@ -662,13 +716,14 @@ class languages {
}
}
}
+
return $magicWords;
}
/**
* Get the magic words which do not match the case-sensitivity of the original words.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The magic words whose case does not match in this language.
*/
@@ -685,13 +740,14 @@ class languages {
$magicWords[$key] = $local[0];
}
}
+
return $magicWords;
}
/**
* Get the untranslated special page names.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The untranslated special page names in this language.
*/
@@ -704,13 +760,14 @@ class languages {
$specialPageAliases[$key] = $value[0];
}
}
+
return $specialPageAliases;
}
/**
* Get the obsolete special page names.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*
* @return array The obsolete special page names in this language.
*/
@@ -723,12 +780,12 @@ class languages {
$specialPageAliases[$key] = $value[0];
}
}
+
return $specialPageAliases;
}
}
-class extensionLanguages extends languages {
-
+class ExtensionLanguages extends Languages {
/**
* @var MessageGroup
*/
@@ -736,7 +793,7 @@ class extensionLanguages extends languages {
/**
* Load the messages group.
- * @param $group MessageGroup The messages group.
+ * @param MessageGroup $group The messages group.
*/
function __construct( MessageGroup $group ) {
$this->mMessageGroup = $group;
@@ -757,7 +814,7 @@ class extensionLanguages extends languages {
/**
* Load the language file.
*
- * @param $code string The language code.
+ * @param string $code The language code.
*/
protected function loadFile( $code ) {
if ( !isset( $this->mRawMessages[$code] ) ) {
diff --git a/maintenance/language/listVariants.php b/maintenance/language/listVariants.php
new file mode 100644
index 00000000..4bff8916
--- /dev/null
+++ b/maintenance/language/listVariants.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Lists all language variants
+ *
+ * Copyright © 2014 MediaWiki developers
+ * https://www.mediawiki.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+require_once dirname( __DIR__ ) . '/Maintenance.php';
+
+/**
+ * @since 1.24
+ */
+class ListVariants extends Maintenance {
+
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = 'Outputs a list of language variants';
+ $this->addOption( 'flat', 'Output variants in a flat list' );
+ $this->addOption( 'json', 'Output variants as JSON' );
+ }
+
+ public function execute() {
+ $variantLangs = array();
+ $variants = array();
+ foreach ( LanguageConverter::$languagesWithVariants as $langCode ) {
+ $lang = Language::factory( $langCode );
+ if ( count( $lang->getVariants() ) > 1 ) {
+ $variants += array_flip( $lang->getVariants() );
+ $variantLangs[$langCode] = $lang->getVariants();
+ }
+ }
+ $variants = array_keys( $variants );
+ sort( $variants );
+ $result = $this->hasOption( 'flat' ) ? $variants : $variantLangs;
+
+ // Not using $this->output() because muting makes no sense here
+ if ( $this->hasOption( 'json' ) ) {
+ echo FormatJson::encode( $result, true ) . "\n";
+ } else {
+ foreach ( $result as $key => $value ) {
+ if ( is_array( $value ) ) {
+ echo "$key\n";
+ foreach ( $value as $variant ) {
+ echo " $variant\n";
+ }
+ } else {
+ echo "$value\n";
+ }
+ }
+ }
+ }
+}
+
+$maintClass = 'ListVariants';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/maintenance/language/messageTypes.inc b/maintenance/language/messageTypes.inc
deleted file mode 100644
index f9239b1c..00000000
--- a/maintenance/language/messageTypes.inc
+++ /dev/null
@@ -1,872 +0,0 @@
-<?php
-/**
- * Several types of messages.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup MaintenanceLanguage
- */
-
-/** Ignored messages, which should exist only in the English messages file. */
-$wgIgnoredMessages = array(
- 'sidebar',
- 'accesskey-pt-userpage',
- 'accesskey-pt-anonuserpage',
- 'accesskey-pt-mytalk',
- 'accesskey-pt-anontalk',
- 'accesskey-pt-preferences',
- 'accesskey-pt-watchlist',
- 'accesskey-pt-mycontris',
- 'accesskey-pt-login',
- 'accesskey-pt-anonlogin',
- 'accesskey-pt-logout',
- 'accesskey-ca-talk',
- 'accesskey-ca-edit',
- 'accesskey-ca-addsection',
- 'accesskey-ca-viewsource',
- 'accesskey-ca-history',
- 'accesskey-ca-protect',
- 'accesskey-ca-unprotect',
- 'accesskey-ca-delete',
- 'accesskey-ca-undelete',
- 'accesskey-ca-move',
- 'accesskey-ca-watch',
- 'accesskey-ca-unwatch',
- 'accesskey-search',
- 'accesskey-search-go',
- 'accesskey-search-fulltext',
- 'accesskey-p-logo',
- 'accesskey-n-mainpage',
- 'accesskey-n-mainpage-description',
- 'accesskey-n-portal',
- 'accesskey-n-currentevents',
- 'accesskey-n-recentchanges',
- 'accesskey-n-randompage',
- 'accesskey-n-help',
- 'accesskey-t-whatlinkshere',
- 'accesskey-t-recentchangeslinked',
- 'accesskey-feed-rss',
- 'accesskey-feed-atom',
- 'accesskey-t-contributions',
- 'accesskey-t-emailuser',
- 'accesskey-t-permalink',
- 'accesskey-t-print',
- 'accesskey-t-upload',
- 'accesskey-t-specialpages',
- 'accesskey-ca-nstab-main',
- 'accesskey-ca-nstab-user',
- 'accesskey-ca-nstab-media',
- 'accesskey-ca-nstab-special',
- 'accesskey-ca-nstab-project',
- 'accesskey-ca-nstab-image',
- 'accesskey-ca-nstab-mediawiki',
- 'accesskey-ca-nstab-template',
- 'accesskey-ca-nstab-help',
- 'accesskey-ca-nstab-category',
- 'accesskey-minoredit',
- 'accesskey-save',
- 'accesskey-preview',
- 'accesskey-diff',
- 'accesskey-compareselectedversions',
- 'accesskey-watch',
- 'accesskey-upload',
- 'accesskey-preferences-save',
- 'accesskey-summary',
- 'accesskey-userrights-set',
- 'accesskey-blockip-block',
- 'accesskey-export',
- 'accesskey-import',
- 'accesskey-watchlistedit-normal-submit',
- 'accesskey-watchlistedit-raw-submit',
- 'addsection',
- 'talkpageheader',
- 'anonnotice',
- 'autoblock_whitelist',
- 'searchmenu-new-nocreate',
- 'googlesearch',
- 'opensearch-desc',
- 'exif-make-value',
- 'exif-model-value',
- 'exif-software-value',
- 'exif-software-version-value',
- 'history_copyright',
- 'licenses',
- 'loginstart',
- 'loginend-https',
- 'loginend',
- 'loginlanguagelinks',
- 'pear-mail-error',
- 'php-mail-error',
- 'markaspatrolledlink',
- 'newarticletextanon',
- 'newsectionheaderdefaultlevel',
- 'mainpage-nstab',
- 'newtalkseparator',
- 'noarticletextanon',
- 'number_of_watching_users_RCview',
- 'pagecategorieslink',
- 'pubmedurl',
- 'randompage-url',
- 'recentchanges-url',
- 'recentchangestext',
- 'revision-info-current',
- 'revision-nav',
- 'rfcurl',
- 'shareddescriptionfollows',
- 'signature-anon',
- 'signupstart',
- 'signupend',
- 'signupend-https',
- 'sitenotice',
- 'sitesubtitle',
- 'sitetitle',
- 'sp-contributions-footer',
- 'sp-contributions-footer-anon',
- 'sp-contributions-footer-newbies',
- 'statistics-summary',
- 'statistics-footer',
- 'talkpagetext',
- 'uploadfooter',
- 'upload-default-description',
- 'listgrouprights-link',
- 'search-interwiki-custom',
- 'allpages-summary',
- 'booksources-summary',
- 'categories-summary',
- 'blocklist-summary',
- 'protectedtitles-summary',
- 'listusers-summary',
- 'longpages-summary',
- 'preferences-summary',
- 'specialpages-summary',
- 'whatlinkshere-summary',
- 'listredirects-summary',
- 'uncategorizedpages-summary',
- 'uncategorizedcategories-summary',
- 'uncategorizedimages-summary',
- 'uncategorizedtemplates-summary',
- 'popularpages-summary',
- 'wantedcategories-summary',
- 'wantedfiles-summary',
- 'wantedpages-summary',
- 'watchlist-summary',
- 'mostlinked-summary',
- 'mostlinkedcategories-summary',
- 'mostlinkedtemplates-summary',
- 'mostcategories-summary',
- 'mostimages-summary',
- 'mostinterwikis-summary',
- 'mostrevisions-summary',
- 'prefixindex-summary',
- 'shortpages-summary',
- 'newpages-summary',
- 'ancientpages-summary',
- 'unwatchedpages-summary',
- 'userrights-summary',
- 'brokenredirects-summary',
- 'deadendpages-summary',
- 'protectedpages-summary',
- 'disambiguations-summary',
- 'pageswithprop-summary',
- 'doubleredirects-summary',
- 'lonelypages-summary',
- 'unusedtemplates-summary',
- 'fewestrevisions-summary',
- 'upload-summary',
- 'wantedtemplates-summary',
- 'activeusers-summary',
- 'search-summary',
- 'editpage-head-copy-warn',
- 'editpage-tos-summary',
- 'addsection-preload',
- 'addsection-editintro',
- 'longpage-hint',
- 'javascripttest-backlink',
- 'javascripttest-qunit-name',
- 'revdelete-logentry',
- 'logdelete-logentry',
- 'revdelete-content',
- 'revdelete-summary',
- 'revdelete-uname',
- 'revdelete-hid',
- 'revdelete-unhid',
- 'revdelete-log-message',
- 'logdelete-log-message',
- 'deletedarticle',
- 'suppressedarticle',
- 'undeletedarticle',
- 'patrol-log-line',
- 'patrol-log-auto',
- 'patrol-log-diff',
- '1movedto2',
- '1movedto2_redir',
- 'move-redirect-suppressed',
- 'newuserlog-create-entry',
- 'newuserlog-create2-entry',
- 'newuserlog-autocreate-entry',
- 'rightslogentry',
- 'rightslogentry-autopromote',
- 'suppressedarticle',
- 'deletedarticle',
- // 'uploadedimage',
- // 'overwroteimage',
- 'createacct-helpusername',
- 'createacct-imgcaptcha-help',
- 'userlogout-summary',
- 'changeemail-summary',
- 'changepassword-summary',
- 'unusedcategories-summary',
- 'unusedimages-summary',
- 'deletedcontributions-summary',
- 'linksearch-summary',
- 'emailuser-summary',
- 'undelete-summary',
- 'contributions-summary',
- 'unblock-summary',
- 'movepage-summary',
- 'export-summary',
- 'import-summary',
- 'editwatchlist-summary',
- 'version-summary',
- 'tags-summary',
- 'comparepages-summary',
- 'resettokens-summary',
- 'version-db-mysql-url',
- 'version-db-mariadb-url',
- 'version-db-percona-url',
- 'version-db-postgres-url',
- 'version-db-oracle-url',
- 'version-db-sqlite-url',
- 'version-db-mssql-url',
- 'version-entrypoints-index-php',
- 'version-entrypoints-api-php',
- 'version-entrypoints-load-php',
- 'ipb-default-expiry',
- 'pageinfo-header',
- 'pageinfo-footer',
- 'createacct-benefit-head1',
- 'createacct-benefit-icon1',
- 'createacct-benefit-head2',
- 'createacct-benefit-icon2',
- 'createacct-benefit-head3',
- 'createacct-benefit-icon3',
- 'today-at',
- 'redirect-text',
- 'helppage',
- 'edithelppage',
- 'helplogin-url',
- 'autocomment-prefix',
- 'move-redirect-text',
-);
-
-/** Optional messages, which may be translated only if changed in the target language. */
-$wgOptionalMessages = array(
- 'linkprefix',
- 'feed-atom',
- 'feed-rss',
- 'unit-pixel',
- 'userrights-irreversible-marker',
- 'tog-noconvertlink',
- 'variantname-zh-hans',
- 'variantname-zh-hant',
- 'variantname-zh-cn',
- 'variantname-zh-tw',
- 'variantname-zh-hk',
- 'variantname-zh-mo',
- 'variantname-zh-my',
- 'variantname-zh-sg',
- 'variantname-zh',
- 'variantname-gan-hans',
- 'variantname-gan-hant',
- 'variantname-gan',
- 'variantname-sr-ec',
- 'variantname-sr-el',
- 'variantname-sr',
- 'variantname-kk-arab',
- 'variantname-kk-cyrl',
- 'variantname-kk-latn',
- 'variantname-kk-tr',
- 'variantname-kk-kz',
- 'variantname-kk-cn',
- 'variantname-kk',
- 'variantname-ku-latn',
- 'variantname-ku-arab',
- 'variantname-ku',
- 'variantname-tg-cyrl',
- 'variantname-tg-latn',
- 'variantname-tg',
- 'variantname-ike-cans',
- 'variantname-ike-latn',
- 'variantname-iu',
- 'variantname-shi-tfng',
- 'variantname-shi-latn',
- 'variantname-shi',
- 'rc-change-size',
- 'resetpass_text',
- 'image_sample',
- 'media_sample',
- 'skinname-cologneblue',
- 'skinname-monobook',
- 'skinname-modern',
- 'skinname-vector',
- 'common.css',
- 'cologneblue.css',
- 'monobook.css',
- 'modern.css',
- 'vector.css',
- 'print.css',
- 'noscript.css',
- 'group-autoconfirmed.css',
- 'group-bot.css',
- 'group-sysop.css',
- 'group-bureaucrat.css',
- 'common.js',
- 'cologneblue.js',
- 'monobook.js',
- 'modern.js',
- 'vector.js',
- 'group-autoconfirmed.js',
- 'group-bot.js',
- 'group-sysop.js',
- 'group-bureaucrat.js',
- 'widthheight',
- 'exif-fnumber-format',
- 'exif-focallength-format',
- 'exif-compression-5',
- 'exif-compression-6',
- 'exif-compression-7',
- 'exif-compression-8',
- 'exif-compression-32773',
- 'exif-compression-32946',
- 'exif-compression-34712',
- 'exif-photometricinterpretation-2',
- 'exif-photometricinterpretation-6',
- 'exif-xyresolution-i',
- 'exif-xyresolution-c',
- 'exif-colorspace-1',
- 'exif-componentsconfiguration-1',
- 'exif-componentsconfiguration-2',
- 'exif-componentsconfiguration-3',
- 'exif-componentsconfiguration-4',
- 'exif-componentsconfiguration-5',
- 'exif-componentsconfiguration-6',
- 'exif-contact-value',
- 'exif-coordinate-format',
- 'exif-lightsource-20',
- 'exif-lightsource-21',
- 'exif-lightsource-22',
- 'exif-lightsource-23',
- 'exif-maxaperturevalue-value',
- 'exif-subjectnewscode-value',
- 'booksources-isbn',
- 'protect-summary-desc',
- 'sp-contributions-explain',
- 'sorbs',
- 'video-dims',
- 'seconds-abbrev',
- 'minutes-abbrev',
- 'hours-abbrev',
- 'days-abbrev',
- 'pagetitle',
- 'filename-prefix-blacklist',
- 'edittools',
- 'edittools-upload',
- 'size-bytes',
- 'size-kilobytes',
- 'size-megabytes',
- 'size-gigabytes',
- 'size-terabytes',
- 'size-petabytes',
- 'size-exabytes',
- 'size-zetabytes',
- 'size-yottabytes',
- 'bitrate-bits',
- 'bitrate-kilobits',
- 'bitrate-megabits',
- 'bitrate-gigabits',
- 'bitrate-terabits',
- 'bitrate-petabits',
- 'bitrate-exabits',
- 'bitrate-zetabits',
- 'bitrate-yottabits',
- 'iranian-calendar-m1',
- 'iranian-calendar-m2',
- 'iranian-calendar-m3',
- 'iranian-calendar-m4',
- 'iranian-calendar-m5',
- 'iranian-calendar-m6',
- 'iranian-calendar-m7',
- 'iranian-calendar-m8',
- 'iranian-calendar-m9',
- 'iranian-calendar-m10',
- 'iranian-calendar-m11',
- 'iranian-calendar-m12',
- 'hijri-calendar-m1',
- 'hijri-calendar-m2',
- 'hijri-calendar-m3',
- 'hijri-calendar-m4',
- 'hijri-calendar-m5',
- 'hijri-calendar-m6',
- 'hijri-calendar-m7',
- 'hijri-calendar-m8',
- 'hijri-calendar-m9',
- 'hijri-calendar-m10',
- 'hijri-calendar-m11',
- 'hijri-calendar-m12',
- 'hebrew-calendar-m1',
- 'hebrew-calendar-m2',
- 'hebrew-calendar-m3',
- 'hebrew-calendar-m4',
- 'hebrew-calendar-m5',
- 'hebrew-calendar-m6',
- 'hebrew-calendar-m6a',
- 'hebrew-calendar-m6b',
- 'hebrew-calendar-m7',
- 'hebrew-calendar-m8',
- 'hebrew-calendar-m9',
- 'hebrew-calendar-m10',
- 'hebrew-calendar-m11',
- 'hebrew-calendar-m12',
- 'hebrew-calendar-m1-gen',
- 'hebrew-calendar-m2-gen',
- 'hebrew-calendar-m3-gen',
- 'hebrew-calendar-m4-gen',
- 'hebrew-calendar-m5-gen',
- 'hebrew-calendar-m6-gen',
- 'hebrew-calendar-m6a-gen',
- 'hebrew-calendar-m6b-gen',
- 'hebrew-calendar-m7-gen',
- 'hebrew-calendar-m8-gen',
- 'hebrew-calendar-m9-gen',
- 'hebrew-calendar-m10-gen',
- 'hebrew-calendar-m11-gen',
- 'hebrew-calendar-m12-gen',
- 'version-api',
- 'version-svn-revision',
- 'semicolon-separator',
- 'comma-separator',
- 'colon-separator',
- 'pipe-separator',
- 'word-separator',
- 'ellipsis',
- 'percent',
- 'parentheses',
- 'brackets',
- 'listgrouprights-right-display',
- 'listgrouprights-right-revoked',
- 'timezone-utc',
- 'unpatrolledletter',
- 'diff-with-additional',
- 'pagetitle-view-mainpage',
- 'backlinksubtitle',
- 'prefs-registration-date-time',
- 'prefs-memberingroups-type',
- 'userrights-groupsmember-type',
- 'shared-repo-name-wikimediacommons',
- 'usermessage-template',
- 'filepage.css',
- 'metadata-langitem',
- 'metadata-langitem-default',
- 'nocookiesforlogin',
- 'version-entrypoints-articlepath',
- 'version-entrypoints-scriptpath',
- 'mergehistory-revisionrow',
- 'categoryviewer-pagedlinks',
- 'undelete-revisionrow',
- 'pageinfo-redirects-value',
- 'created', // @deprecated. Remove in MediaWiki 1.23.
- 'changed', // @deprecated. Remove in MediaWiki 1.23.
- 'limitreport-ppvisitednodes-value',
- 'limitreport-ppgeneratednodes-value',
- 'limitreport-expansiondepth-value',
- 'limitreport-expensivefunctioncount-value',
- 'tooltip-iwiki',
-);
-
-/** Exif messages, which may be set as optional in several checks, but are generally mandatory */
-$wgEXIFMessages = array(
- 'exif-imagewidth',
- 'exif-imagelength',
- 'exif-bitspersample',
- 'exif-compression',
- 'exif-photometricinterpretation',
- 'exif-orientation',
- 'exif-samplesperpixel',
- 'exif-planarconfiguration',
- 'exif-ycbcrsubsampling',
- 'exif-ycbcrpositioning',
- 'exif-xresolution',
- 'exif-yresolution',
- 'exif-stripoffsets',
- 'exif-rowsperstrip',
- 'exif-stripbytecounts',
- 'exif-jpeginterchangeformat',
- 'exif-jpeginterchangeformatlength',
- 'exif-whitepoint',
- 'exif-primarychromaticities',
- 'exif-ycbcrcoefficients',
- 'exif-referenceblackwhite',
- 'exif-datetime',
- 'exif-imagedescription',
- 'exif-make',
- 'exif-model',
- 'exif-software',
- 'exif-artist',
- 'exif-copyright',
- 'exif-exifversion',
- 'exif-flashpixversion',
- 'exif-colorspace',
- 'exif-componentsconfiguration',
- 'exif-compressedbitsperpixel',
- 'exif-pixelydimension',
- 'exif-pixelxdimension',
- 'exif-usercomment',
- 'exif-relatedsoundfile',
- 'exif-datetimeoriginal',
- 'exif-datetimedigitized',
- 'exif-subsectime',
- 'exif-subsectimeoriginal',
- 'exif-subsectimedigitized',
- 'exif-exposuretime',
- 'exif-exposuretime-format',
- 'exif-fnumber',
- 'exif-fnumber-format',
- 'exif-exposureprogram',
- 'exif-spectralsensitivity',
- 'exif-isospeedratings',
- 'exif-shutterspeedvalue',
- 'exif-aperturevalue',
- 'exif-brightnessvalue',
- 'exif-exposurebiasvalue',
- 'exif-maxaperturevalue',
- 'exif-subjectdistance',
- 'exif-meteringmode',
- 'exif-lightsource',
- 'exif-flash',
- 'exif-focallength',
- 'exif-focallength-format',
- 'exif-subjectarea',
- 'exif-flashenergy',
- 'exif-focalplanexresolution',
- 'exif-focalplaneyresolution',
- 'exif-focalplaneresolutionunit',
- 'exif-subjectlocation',
- 'exif-exposureindex',
- 'exif-sensingmethod',
- 'exif-filesource',
- 'exif-scenetype',
- 'exif-customrendered',
- 'exif-exposuremode',
- 'exif-whitebalance',
- 'exif-digitalzoomratio',
- 'exif-focallengthin35mmfilm',
- 'exif-scenecapturetype',
- 'exif-gaincontrol',
- 'exif-contrast',
- 'exif-saturation',
- 'exif-sharpness',
- 'exif-devicesettingdescription',
- 'exif-subjectdistancerange',
- 'exif-imageuniqueid',
- 'exif-gpsversionid',
- 'exif-gpslatituderef',
- 'exif-gpslatitude',
- 'exif-gpslongituderef',
- 'exif-gpslongitude',
- 'exif-gpsaltituderef',
- 'exif-gpsaltitude',
- 'exif-gpstimestamp',
- 'exif-gpssatellites',
- 'exif-gpsstatus',
- 'exif-gpsmeasuremode',
- 'exif-gpsdop',
- 'exif-gpsspeedref',
- 'exif-gpsspeed',
- 'exif-gpstrackref',
- 'exif-gpstrack',
- 'exif-gpsimgdirectionref',
- 'exif-gpsimgdirection',
- 'exif-gpsmapdatum',
- 'exif-gpsdestlatituderef',
- 'exif-gpsdestlatitude',
- 'exif-gpsdestlongituderef',
- 'exif-gpsdestlongitude',
- 'exif-gpsdestbearingref',
- 'exif-gpsdestbearing',
- 'exif-gpsdestdistanceref',
- 'exif-gpsdestdistance',
- 'exif-gpsprocessingmethod',
- 'exif-gpsareainformation',
- 'exif-gpsdatestamp',
- 'exif-gpsdifferential',
- 'exif-coordinate-format',
- 'exif-jpegfilecomment',
- 'exif-keywords',
- 'exif-worldregioncreated',
- 'exif-countrycreated',
- 'exif-countrycodecreated',
- 'exif-provinceorstatecreated',
- 'exif-citycreated',
- 'exif-sublocationcreated',
- 'exif-worldregiondest',
- 'exif-countrydest',
- 'exif-countrycodedest',
- 'exif-provinceorstatedest',
- 'exif-citydest',
- 'exif-sublocationdest',
- 'exif-objectname',
- 'exif-specialinstructions',
- 'exif-headline',
- 'exif-credit',
- 'exif-source',
- 'exif-editstatus',
- 'exif-urgency',
- 'exif-fixtureidentifier',
- 'exif-locationdest',
- 'exif-locationdestcode',
- 'exif-objectcycle',
- 'exif-contact',
- 'exif-writer',
- 'exif-languagecode',
- 'exif-iimversion',
- 'exif-iimcategory',
- 'exif-iimsupplementalcategory',
- 'exif-datetimeexpires',
- 'exif-datetimereleased',
- 'exif-originaltransmissionref',
- 'exif-identifier',
- 'exif-lens',
- 'exif-serialnumber',
- 'exif-cameraownername',
- 'exif-label',
- 'exif-datetimemetadata',
- 'exif-nickname',
- 'exif-rating',
- 'exif-rightscertificate',
- 'exif-copyrighted',
- 'exif-copyrightowner',
- 'exif-usageterms',
- 'exif-webstatement',
- 'exif-originaldocumentid',
- 'exif-licenseurl',
- 'exif-morepermissionsurl',
- 'exif-attributionurl',
- 'exif-preferredattributionname',
- 'exif-pngfilecomment',
- 'exif-disclaimer',
- 'exif-contentwarning',
- 'exif-giffilecomment',
- 'exif-intellectualgenre',
- 'exif-subjectnewscode',
- 'exif-scenecode',
- 'exif-event',
- 'exif-organisationinimage',
- 'exif-personinimage',
- 'exif-originalimageheight',
- 'exif-originalimagewidth',
- 'exif-make-value',
- 'exif-model-value',
- 'exif-software-value',
- 'exif-software-version-value',
- 'exif-contact-value',
- 'exif-subjectnewscode-value',
- 'exif-compression-1',
- 'exif-compression-2',
- 'exif-compression-3',
- 'exif-compression-4',
- 'exif-compression-5',
- 'exif-compression-6',
- 'exif-compression-7',
- 'exif-compression-8',
- 'exif-compression-32773',
- 'exif-compression-32946',
- 'exif-compression-34712',
- 'exif-copyrighted-true',
- 'exif-copyrighted-false',
- 'exif-photometricinterpretation-2',
- 'exif-photometricinterpretation-6',
- 'exif-unknowndate',
- 'exif-orientation-1',
- 'exif-orientation-2',
- 'exif-orientation-3',
- 'exif-orientation-4',
- 'exif-orientation-5',
- 'exif-orientation-6',
- 'exif-orientation-7',
- 'exif-orientation-8',
- 'exif-planarconfiguration-1',
- 'exif-planarconfiguration-2',
- 'exif-xyresolution-i',
- 'exif-xyresolution-c',
- 'exif-colorspace-1',
- 'exif-colorspace-65535',
- 'exif-componentsconfiguration-0',
- 'exif-componentsconfiguration-1',
- 'exif-componentsconfiguration-2',
- 'exif-componentsconfiguration-3',
- 'exif-componentsconfiguration-4',
- 'exif-componentsconfiguration-5',
- 'exif-componentsconfiguration-6',
- 'exif-exposureprogram-0',
- 'exif-exposureprogram-1',
- 'exif-exposureprogram-2',
- 'exif-exposureprogram-3',
- 'exif-exposureprogram-4',
- 'exif-exposureprogram-5',
- 'exif-exposureprogram-6',
- 'exif-exposureprogram-7',
- 'exif-exposureprogram-8',
- 'exif-subjectdistance-value',
- 'exif-meteringmode-0',
- 'exif-meteringmode-1',
- 'exif-meteringmode-2',
- 'exif-meteringmode-3',
- 'exif-meteringmode-4',
- 'exif-meteringmode-5',
- 'exif-meteringmode-6',
- 'exif-meteringmode-255',
- 'exif-lightsource-0',
- 'exif-lightsource-1',
- 'exif-lightsource-2',
- 'exif-lightsource-3',
- 'exif-lightsource-4',
- 'exif-lightsource-9',
- 'exif-lightsource-10',
- 'exif-lightsource-11',
- 'exif-lightsource-12',
- 'exif-lightsource-13',
- 'exif-lightsource-14',
- 'exif-lightsource-15',
- 'exif-lightsource-17',
- 'exif-lightsource-18',
- 'exif-lightsource-19',
- 'exif-lightsource-20',
- 'exif-lightsource-21',
- 'exif-lightsource-22',
- 'exif-lightsource-23',
- 'exif-lightsource-24',
- 'exif-lightsource-255',
- 'exif-flash-fired-0',
- 'exif-flash-fired-1',
- 'exif-flash-return-0',
- 'exif-flash-return-2',
- 'exif-flash-return-3',
- 'exif-flash-mode-1',
- 'exif-flash-mode-2',
- 'exif-flash-mode-3',
- 'exif-flash-function-1',
- 'exif-flash-redeye-1',
- 'exif-focalplaneresolutionunit-2',
- 'exif-sensingmethod-1',
- 'exif-sensingmethod-2',
- 'exif-sensingmethod-3',
- 'exif-sensingmethod-4',
- 'exif-sensingmethod-5',
- 'exif-sensingmethod-7',
- 'exif-sensingmethod-8',
- 'exif-filesource-3',
- 'exif-scenetype-1',
- 'exif-customrendered-0',
- 'exif-customrendered-1',
- 'exif-exposuremode-0',
- 'exif-exposuremode-1',
- 'exif-exposuremode-2',
- 'exif-whitebalance-0',
- 'exif-whitebalance-1',
- 'exif-scenecapturetype-0',
- 'exif-scenecapturetype-1',
- 'exif-scenecapturetype-2',
- 'exif-scenecapturetype-3',
- 'exif-gaincontrol-0',
- 'exif-gaincontrol-1',
- 'exif-gaincontrol-2',
- 'exif-gaincontrol-3',
- 'exif-gaincontrol-4',
- 'exif-contrast-0',
- 'exif-contrast-1',
- 'exif-contrast-2',
- 'exif-saturation-0',
- 'exif-saturation-1',
- 'exif-saturation-2',
- 'exif-sharpness-0',
- 'exif-sharpness-1',
- 'exif-sharpness-2',
- 'exif-subjectdistancerange-0',
- 'exif-subjectdistancerange-1',
- 'exif-subjectdistancerange-2',
- 'exif-subjectdistancerange-3',
- 'exif-gpslatitude-n',
- 'exif-gpslatitude-s',
- 'exif-gpslongitude-e',
- 'exif-gpslongitude-w',
- 'exif-gpsaltitude-above-sealevel',
- 'exif-gpsaltitude-below-sealevel',
- 'exif-gpsstatus-a',
- 'exif-gpsstatus-v',
- 'exif-gpsmeasuremode-2',
- 'exif-gpsmeasuremode-3',
- 'exif-gpsspeed-k',
- 'exif-gpsspeed-m',
- 'exif-gpsspeed-n',
- 'exif-gpsdestdistance-k',
- 'exif-gpsdestdistance-m',
- 'exif-gpsdestdistance-n',
- 'exif-gpsdop-excellent',
- 'exif-gpsdop-good',
- 'exif-gpsdop-moderate',
- 'exif-gpsdop-fair',
- 'exif-gpsdop-poor',
- 'exif-objectcycle-a',
- 'exif-objectcycle-p',
- 'exif-objectcycle-b',
- 'exif-gpsdirection-t',
- 'exif-gpsdirection-m',
- 'exif-ycbcrpositioning-1',
- 'exif-ycbcrpositioning-2',
- 'exif-dc-contributor',
- 'exif-dc-coverage',
- 'exif-dc-date',
- 'exif-dc-publisher',
- 'exif-dc-relation',
- 'exif-dc-rights',
- 'exif-dc-source',
- 'exif-dc-type',
- 'exif-rating-rejected',
- 'exif-isospeedratings-overflow',
- 'exif-maxaperturevalue-value',
- 'exif-iimcategory-ace',
- 'exif-iimcategory-clj',
- 'exif-iimcategory-dis',
- 'exif-iimcategory-fin',
- 'exif-iimcategory-edu',
- 'exif-iimcategory-evn',
- 'exif-iimcategory-hth',
- 'exif-iimcategory-hum',
- 'exif-iimcategory-lab',
- 'exif-iimcategory-lif',
- 'exif-iimcategory-pol',
- 'exif-iimcategory-rel',
- 'exif-iimcategory-sci',
- 'exif-iimcategory-soi',
- 'exif-iimcategory-spo',
- 'exif-iimcategory-war',
- 'exif-iimcategory-wea',
- 'exif-urgency-normal',
- 'exif-urgency-low',
- 'exif-urgency-high',
- 'exif-urgency-other',
-);
diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc
deleted file mode 100644
index e351549b..00000000
--- a/maintenance/language/messages.inc
+++ /dev/null
@@ -1,4239 +0,0 @@
-<?php
-/**
- * Define the messages structure in the messages file, for an automated rewriting.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup MaintenanceLanguage
- */
-
-/** The structure of the messages, divided to blocks */
-$wgMessageStructure = array(
- 'sidebar' => array(
- 'sidebar',
- ),
- 'toggles' => array(
- 'tog-underline',
- 'tog-justify',
- 'tog-hideminor',
- 'tog-hidepatrolled',
- 'tog-newpageshidepatrolled',
- 'tog-extendwatchlist',
- 'tog-usenewrc',
- 'tog-numberheadings',
- 'tog-showtoolbar',
- 'tog-editondblclick',
- 'tog-editsection',
- 'tog-editsectiononrightclick',
- 'tog-showtoc',
- 'tog-rememberpassword',
- 'tog-watchcreations',
- 'tog-watchdefault',
- 'tog-watchmoves',
- 'tog-watchdeletion',
- 'tog-minordefault',
- 'tog-previewontop',
- 'tog-previewonfirst',
- 'tog-nocache',
- 'tog-enotifwatchlistpages',
- 'tog-enotifusertalkpages',
- 'tog-enotifminoredits',
- 'tog-enotifrevealaddr',
- 'tog-shownumberswatching',
- 'tog-oldsig',
- 'tog-fancysig',
- 'tog-uselivepreview',
- 'tog-forceeditsummary',
- 'tog-watchlisthideown',
- 'tog-watchlisthidebots',
- 'tog-watchlisthideminor',
- 'tog-watchlisthideliu',
- 'tog-watchlisthideanons',
- 'tog-watchlisthidepatrolled',
- 'tog-ccmeonemails',
- 'tog-diffonly',
- 'tog-showhiddencats',
- 'tog-noconvertlink',
- 'tog-norollbackdiff',
- 'tog-useeditwarning',
- 'tog-prefershttps'
- ),
- 'underline' => array(
- 'underline-always',
- 'underline-never',
- 'underline-default',
- ),
- 'editfont' => array(
- 'editfont-style',
- 'editfont-default',
- 'editfont-monospace',
- 'editfont-sansserif',
- 'editfont-serif',
- ),
- 'dates' => array(
- 'sunday',
- 'monday',
- 'tuesday',
- 'wednesday',
- 'thursday',
- 'friday',
- 'saturday',
- 'sun',
- 'mon',
- 'tue',
- 'wed',
- 'thu',
- 'fri',
- 'sat',
- 'january',
- 'february',
- 'march',
- 'april',
- 'may_long',
- 'june',
- 'july',
- 'august',
- 'september',
- 'october',
- 'november',
- 'december',
- 'january-gen',
- 'february-gen',
- 'march-gen',
- 'april-gen',
- 'may-gen',
- 'june-gen',
- 'july-gen',
- 'august-gen',
- 'september-gen',
- 'october-gen',
- 'november-gen',
- 'december-gen',
- 'jan',
- 'feb',
- 'mar',
- 'apr',
- 'may',
- 'jun',
- 'jul',
- 'aug',
- 'sep',
- 'oct',
- 'nov',
- 'dec',
- 'january-date',
- 'february-date',
- 'march-date',
- 'april-date',
- 'may-date',
- 'june-date',
- 'july-date',
- 'august-date',
- 'september-date',
- 'october-date',
- 'november-date',
- 'december-date',
- ),
- 'categorypages' => array(
- 'pagecategories',
- 'pagecategorieslink',
- 'category_header',
- 'subcategories',
- 'category-media-header',
- 'category-empty',
- 'hidden-categories',
- 'hidden-category-category',
- 'category-subcat-count',
- 'category-subcat-count-limited',
- 'category-article-count',
- 'category-article-count-limited',
- 'category-file-count',
- 'category-file-count-limited',
- 'listingcontinuesabbrev',
- 'index-category',
- 'noindex-category',
- 'broken-file-category',
- 'categoryviewer-pagedlinks',
- ),
- 'mainpage' => array(
- 'linkprefix',
- ),
- 'miscellaneous1' => array(
- 'about',
- 'article',
- 'newwindow',
- 'cancel',
- 'moredotdotdot',
- 'morenotlisted',
- 'mypage',
- 'mytalk',
- 'anontalk',
- 'navigation',
- 'and',
- ),
- 'cologneblue' => array(
- 'qbfind',
- 'qbbrowse',
- 'qbedit',
- 'qbpageoptions',
- 'qbmyoptions',
- 'qbspecialpages',
- 'faq',
- 'faqpage',
- 'sitetitle',
- 'sitesubtitle',
- ),
- 'vector' => array(
- 'vector-action-addsection',
- 'vector-action-delete',
- 'vector-action-move',
- 'vector-action-protect',
- 'vector-action-undelete',
- 'vector-action-unprotect',
- 'vector-simplesearch-preference',
- 'vector-view-create',
- 'vector-view-edit',
- 'vector-view-history',
- 'vector-view-view',
- 'vector-view-viewsource',
- 'actions',
- 'namespaces',
- 'variants',
- ),
- 'miscellaneous2' => array(
- 'navigation-heading',
- 'errorpagetitle',
- 'returnto',
- 'tagline',
- 'help',
- 'search',
- 'searchbutton',
- 'go',
- 'searcharticle',
- 'history',
- 'history_short',
- 'updatedmarker',
- 'printableversion',
- 'permalink',
- 'print',
- 'view',
- 'edit',
- 'create',
- 'editthispage',
- 'create-this-page',
- 'delete',
- 'deletethispage',
- 'undeletethispage',
- 'undelete_short',
- 'viewdeleted_short',
- 'protect',
- 'protect_change',
- 'protectthispage',
- 'unprotect',
- 'unprotectthispage',
- 'newpage',
- 'talkpage',
- 'talkpagelinktext',
- 'specialpage',
- 'personaltools',
- 'postcomment',
- 'addsection',
- 'articlepage',
- 'talk',
- 'views',
- 'toolbox',
- 'userpage',
- 'projectpage',
- 'imagepage',
- 'mediawikipage',
- 'templatepage',
- 'viewhelppage',
- 'categorypage',
- 'viewtalkpage',
- 'otherlanguages',
- 'redirectedfrom',
- 'redirectpagesub',
- 'talkpageheader',
- 'lastmodifiedat',
- 'viewcount',
- 'protectedpage',
- 'jumpto',
- 'jumptonavigation',
- 'jumptosearch',
- 'view-pool-error',
- 'pool-timeout',
- 'pool-queuefull',
- 'pool-errorunknown',
- ),
- 'links' => array(
- 'aboutsite',
- 'aboutpage',
- 'copyright',
- 'copyrightpage',
- 'currentevents',
- 'currentevents-url',
- 'disclaimers',
- 'disclaimerpage',
- 'edithelp',
- 'edithelppage',
- 'help',
- 'helppage',
- 'mainpage',
- 'mainpage-description',
- 'policy-url',
- 'portal',
- 'portal-url',
- 'privacy',
- 'privacypage',
- ),
- 'badaccess' => array(
- 'badaccess',
- 'badaccess-group0',
- 'badaccess-groups',
- ),
- 'versionrequired' => array(
- 'versionrequired',
- 'versionrequiredtext',
- ),
- 'miscellaneous3' => array(
- 'ok',
- 'pagetitle',
- 'pagetitle-view-mainpage',
- 'backlinksubtitle',
- 'retrievedfrom',
- 'youhavenewmessages',
- 'newmessageslink',
- 'newmessagesdifflink',
- 'youhavenewmessagesfromusers',
- 'youhavenewmessagesmanyusers',
- 'newmessageslinkplural',
- 'newmessagesdifflinkplural',
- 'youhavenewmessagesmulti',
- 'newtalkseparator',
- 'editsection',
- 'editold',
- 'viewsourceold',
- 'editlink',
- 'viewsourcelink',
- 'editsectionhint',
- 'toc',
- 'showtoc',
- 'hidetoc',
- 'collapsible-collapse',
- 'collapsible-expand',
- 'thisisdeleted',
- 'viewdeleted',
- 'restorelink',
- 'feedlinks',
- 'feed-invalid',
- 'feed-unavailable',
- 'site-rss-feed',
- 'site-atom-feed',
- 'page-rss-feed',
- 'page-atom-feed',
- 'feed-atom',
- 'feed-rss',
- 'sitenotice',
- 'anonnotice',
- 'newsectionheaderdefaultlevel',
- 'red-link-title',
- 'sort-descending',
- 'sort-ascending',
-
- ),
- 'nstab' => array(
- 'nstab-main',
- 'nstab-user',
- 'nstab-media',
- 'nstab-special',
- 'nstab-project',
- 'nstab-image',
- 'nstab-mediawiki',
- 'nstab-template',
- 'nstab-help',
- 'nstab-category',
- 'mainpage-nstab',
- ),
- 'main' => array(
- 'nosuchaction',
- 'nosuchactiontext',
- 'nosuchspecialpage',
- 'nospecialpagetext',
- ),
- 'errors' => array(
- 'error',
- 'databaseerror',
- 'databaseerror-text',
- 'databaseerror-textcl',
- 'databaseerror-query',
- 'databaseerror-function',
- 'databaseerror-error',
- 'laggedslavemode',
- 'readonly',
- 'enterlockreason',
- 'readonlytext',
- 'missing-article', // not used anymore in core, but kept for extensions
- 'missingarticle-rev', // not used anymore in core, but kept for extensions
- 'missingarticle-diff', // not used anymore in core, but kept for extensions
- 'readonly_lag',
- 'internalerror',
- 'internalerror_info',
- 'fileappenderrorread',
- 'fileappenderror',
- 'filecopyerror',
- 'filerenameerror',
- 'filedeleteerror',
- 'directorycreateerror',
- 'filenotfound',
- 'fileexistserror',
- 'unexpected',
- 'formerror',
- 'badarticleerror',
- 'cannotdelete',
- 'cannotdelete-title',
- 'delete-hook-aborted',
- 'no-null-revision',
- 'badtitle',
- 'badtitletext',
- 'perfcached',
- 'perfcachedts',
- 'querypage-no-updates',
- 'wrong_wfQuery_params',
- 'viewsource',
- 'viewsource-title',
- 'actionthrottled',
- 'actionthrottledtext',
- 'protectedpagetext',
- 'viewsourcetext',
- 'viewyourtext',
- 'protectedinterface',
- 'editinginterface',
- 'cascadeprotected',
- 'namespaceprotected',
- 'customcssprotected',
- 'customjsprotected',
- 'mycustomcssprotected',
- 'mycustomjsprotected',
- 'myprivateinfoprotected',
- 'mypreferencesprotected',
- 'ns-specialprotected',
- 'titleprotected',