summaryrefslogtreecommitdiff
path: root/maintenance
diff options
context:
space:
mode:
Diffstat (limited to 'maintenance')
-rw-r--r--maintenance/FiveUpgrade.inc10
-rw-r--r--maintenance/archives/patch-backlinkindexes.sql19
-rw-r--r--maintenance/archives/patch-externallinks.sql4
-rw-r--r--maintenance/archives/patch-filearchive.sql2
-rw-r--r--maintenance/archives/patch-ipb_anon_only.sql8
-rw-r--r--maintenance/archives/patch-ipb_optional_autoblock.sql3
-rw-r--r--maintenance/archives/patch-job.sql2
-rw-r--r--maintenance/archives/patch-log_params.sql2
-rw-r--r--maintenance/archives/patch-logging.sql2
-rw-r--r--maintenance/archives/patch-querycachetwo.sql22
-rw-r--r--maintenance/archives/patch-rc_len.sql9
-rw-r--r--maintenance/archives/patch-rc_user_text-index.sql7
-rw-r--r--maintenance/archives/patch-redirect.sql28
-rw-r--r--maintenance/archives/patch-rename-user_groups-and_rights.sql2
-rw-r--r--maintenance/archives/patch-restructure.sql8
-rw-r--r--maintenance/archives/patch-searchindex.sql2
-rw-r--r--maintenance/archives/patch-user_editcount.sql5
-rw-r--r--maintenance/archives/patch-user_newpass_time.sql4
-rw-r--r--maintenance/archives/patch-user_rights.sql2
-rw-r--r--maintenance/backup.inc2
-rw-r--r--maintenance/checkUsernames.php3
-rw-r--r--maintenance/commandLine.inc13
-rw-r--r--maintenance/deleteBatch.php11
-rw-r--r--maintenance/deleteDefaultMessages.php45
-rw-r--r--maintenance/dumpHTML.inc103
-rw-r--r--maintenance/dumpHTML.php13
-rw-r--r--maintenance/edit.php68
-rw-r--r--maintenance/fuzz-tester.php138
-rw-r--r--maintenance/generateSitemap.php10
-rw-r--r--maintenance/getLagTimes.php23
-rw-r--r--maintenance/getSlaveServer.php7
-rw-r--r--maintenance/importDump.php2
-rw-r--r--maintenance/importImages.php6
-rw-r--r--maintenance/importTextFile.php117
-rw-r--r--maintenance/initEditCount.php85
-rw-r--r--maintenance/initStats.php1
-rw-r--r--maintenance/interwiki.sql5
-rw-r--r--maintenance/language/langmemusage.php2
-rw-r--r--maintenance/language/languages.inc350
-rw-r--r--maintenance/language/messageTypes.inc346
-rw-r--r--maintenance/language/messages.inc2081
-rw-r--r--maintenance/language/rebuildLanguage.php82
-rw-r--r--maintenance/language/splitLanguageFiles.inc4
-rw-r--r--maintenance/language/transstat.php8
-rw-r--r--maintenance/language/writeMessagesArray.inc145
-rw-r--r--maintenance/moveBatch.php28
-rw-r--r--maintenance/mysql5/tables-binary.sql1095
-rw-r--r--maintenance/mysql5/tables.sql258
-rw-r--r--maintenance/namespace2sql.php4
-rw-r--r--maintenance/oracle/tables.sql6
-rw-r--r--maintenance/ourusers.php22
-rw-r--r--maintenance/parserTests.inc464
-rw-r--r--maintenance/parserTests.php35
-rw-r--r--maintenance/parserTests.txt691
-rw-r--r--maintenance/postgres/compare_schemas.pl106
-rw-r--r--maintenance/postgres/tables.sql58
-rw-r--r--maintenance/postgres/wp_mysql2postgres.pl4
-rw-r--r--maintenance/purgeList.php34
-rw-r--r--maintenance/showStats.php46
-rw-r--r--maintenance/stats.php4
-rw-r--r--maintenance/tables.sql125
-rw-r--r--maintenance/testRunner.sql35
-rw-r--r--maintenance/update.php11
-rw-r--r--maintenance/updateArticleCount.inc.php19
-rw-r--r--maintenance/updateSpecialPages.php12
-rw-r--r--maintenance/updaters.inc165
-rw-r--r--maintenance/userDupes.inc2
67 files changed, 6097 insertions, 938 deletions
diff --git a/maintenance/FiveUpgrade.inc b/maintenance/FiveUpgrade.inc
index 4bbf0733..d21d8b43 100644
--- a/maintenance/FiveUpgrade.inc
+++ b/maintenance/FiveUpgrade.inc
@@ -98,7 +98,7 @@ class FiveUpgrade {
# http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT
static $cp1252 = array(
0x80 => 0x20AC, #EURO SIGN
- 0x81 => UNICODE_REPLACEMENT,
+ 0x81 => 0xFFFD, #REPLACEMENT CHARACTER (no mapping)
0x82 => 0x201A, #SINGLE LOW-9 QUOTATION MARK
0x83 => 0x0192, #LATIN SMALL LETTER F WITH HOOK
0x84 => 0x201E, #DOUBLE LOW-9 QUOTATION MARK
@@ -110,10 +110,10 @@ class FiveUpgrade {
0x8A => 0x0160, #LATIN CAPITAL LETTER S WITH CARON
0x8B => 0x2039, #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
0x8C => 0x0152, #LATIN CAPITAL LIGATURE OE
- 0x8D => UNICODE_REPLACEMENT,
+ 0x8D => 0xFFFD, #REPLACEMENT CHARACTER (no mapping)
0x8E => 0x017D, #LATIN CAPITAL LETTER Z WITH CARON
- 0x8F => UNICODE_REPLACEMENT,
- 0x90 => UNICODE_REPLACEMENT,
+ 0x8F => 0xFFFD, #REPLACEMENT CHARACTER (no mapping)
+ 0x90 => 0xFFFD, #REPLACEMENT CHARACTER (no mapping)
0x91 => 0x2018, #LEFT SINGLE QUOTATION MARK
0x92 => 0x2019, #RIGHT SINGLE QUOTATION MARK
0x93 => 0x201C, #LEFT DOUBLE QUOTATION MARK
@@ -126,7 +126,7 @@ class FiveUpgrade {
0x9A => 0x0161, #LATIN SMALL LETTER S WITH CARON
0x9B => 0x203A, #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
0x9C => 0x0153, #LATIN SMALL LIGATURE OE
- 0x9D => UNICODE_REPLACEMENT,
+ 0x9D => 0xFFFD, #REPLACEMENT CHARACTER (no mapping)
0x9E => 0x017E, #LATIN SMALL LETTER Z WITH CARON
0x9F => 0x0178, #LATIN CAPITAL LETTER Y WITH DIAERESIS
);
diff --git a/maintenance/archives/patch-backlinkindexes.sql b/maintenance/archives/patch-backlinkindexes.sql
new file mode 100644
index 00000000..5facd9ea
--- /dev/null
+++ b/maintenance/archives/patch-backlinkindexes.sql
@@ -0,0 +1,19 @@
+--
+-- patch-backlinkindexes.sql
+--
+-- Per bug 6440 / http://bugzilla.wikimedia.org/show_bug.cgi?id=6440
+--
+-- Improve performance of the "what links here"-type queries
+--
+
+ALTER TABLE /*$wgDBprefix*/pagelinks
+ DROP INDEX pl_namespace,
+ ADD INDEX pl_namespace(pl_namespace, pl_title, pl_from);
+
+ALTER TABLE /*$wgDBprefix*/templatelinks
+ DROP INDEX tl_namespace,
+ ADD INDEX tl_namespace(tl_namespace, tl_title, tl_from);
+
+ALTER TABLE /*$wgDBprefix*/imagelinks
+ DROP INDEX il_to,
+ ADD INDEX il_to(il_to, il_from);
diff --git a/maintenance/archives/patch-externallinks.sql b/maintenance/archives/patch-externallinks.sql
index d1aa5764..52fb5bae 100644
--- a/maintenance/archives/patch-externallinks.sql
+++ b/maintenance/archives/patch-externallinks.sql
@@ -3,8 +3,8 @@
--
CREATE TABLE /*$wgDBprefix*/externallinks (
el_from int(8) unsigned NOT NULL default '0',
- el_to blob NOT NULL default '',
- el_index blob NOT NULL default '',
+ el_to blob NOT NULL,
+ el_index blob NOT NULL,
KEY (el_from, el_to(40)),
KEY (el_to(60), el_from),
diff --git a/maintenance/archives/patch-filearchive.sql b/maintenance/archives/patch-filearchive.sql
index 4bf09366..cc50f2ae 100644
--- a/maintenance/archives/patch-filearchive.sql
+++ b/maintenance/archives/patch-filearchive.sql
@@ -37,7 +37,7 @@ CREATE TABLE /*$wgDBprefix*/filearchive (
fa_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
fa_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") default "unknown",
fa_minor_mime varchar(32) default "unknown",
- fa_description tinyblob default '',
+ fa_description tinyblob,
fa_user int(5) unsigned default '0',
fa_user_text varchar(255) binary default '',
fa_timestamp char(14) binary default '',
diff --git a/maintenance/archives/patch-ipb_anon_only.sql b/maintenance/archives/patch-ipb_anon_only.sql
index 709308a2..b3738168 100644
--- a/maintenance/archives/patch-ipb_anon_only.sql
+++ b/maintenance/archives/patch-ipb_anon_only.sql
@@ -11,17 +11,17 @@ DROP TABLE IF EXISTS /*$wgDBprefix*/ipblocks_newunique;
CREATE TABLE /*$wgDBprefix*/ipblocks_newunique (
ipb_id int(8) NOT NULL auto_increment,
- ipb_address tinyblob NOT NULL default '',
+ ipb_address tinyblob NOT NULL,
ipb_user int(8) unsigned NOT NULL default '0',
ipb_by int(8) unsigned NOT NULL default '0',
- ipb_reason tinyblob NOT NULL default '',
+ ipb_reason tinyblob NOT NULL,
ipb_timestamp char(14) binary NOT NULL default '',
ipb_auto bool NOT NULL default 0,
ipb_anon_only bool NOT NULL default 0,
ipb_create_account bool NOT NULL default 1,
ipb_expiry char(14) binary NOT NULL default '',
- ipb_range_start tinyblob NOT NULL default '',
- ipb_range_end tinyblob NOT NULL default '',
+ ipb_range_start tinyblob NOT NULL,
+ ipb_range_end tinyblob NOT NULL,
PRIMARY KEY ipb_id (ipb_id),
UNIQUE INDEX ipb_address_unique (ipb_address(255), ipb_user, ipb_auto),
diff --git a/maintenance/archives/patch-ipb_optional_autoblock.sql b/maintenance/archives/patch-ipb_optional_autoblock.sql
new file mode 100644
index 00000000..f31b8359
--- /dev/null
+++ b/maintenance/archives/patch-ipb_optional_autoblock.sql
@@ -0,0 +1,3 @@
+-- Add an extra option field "ipb_enable_autoblock" into the ipblocks table. This allows a block to be placed that does not trigger any autoblocks.
+
+ALTER TABLE /*$wgDBprefix*/ipblocks ADD COLUMN ipb_enable_autoblock bool NOT NULL default '1';
diff --git a/maintenance/archives/patch-job.sql b/maintenance/archives/patch-job.sql
index 89918456..d904fbeb 100644
--- a/maintenance/archives/patch-job.sql
+++ b/maintenance/archives/patch-job.sql
@@ -13,7 +13,7 @@ CREATE TABLE /*$wgDBprefix*/job (
-- Any other parameters to the command
-- Presently unused, format undefined
- job_params blob NOT NULL default '',
+ job_params blob NOT NULL,
PRIMARY KEY job_id (job_id),
KEY (job_cmd, job_namespace, job_title)
diff --git a/maintenance/archives/patch-log_params.sql b/maintenance/archives/patch-log_params.sql
index aa00a673..ff6527ec 100644
--- a/maintenance/archives/patch-log_params.sql
+++ b/maintenance/archives/patch-log_params.sql
@@ -1 +1 @@
-ALTER TABLE /*$wgDBprefix*/logging ADD log_params blob NOT NULL default '';
+ALTER TABLE /*$wgDBprefix*/logging ADD log_params blob NOT NULL;
diff --git a/maintenance/archives/patch-logging.sql b/maintenance/archives/patch-logging.sql
index 79bb53b5..54146fb7 100644
--- a/maintenance/archives/patch-logging.sql
+++ b/maintenance/archives/patch-logging.sql
@@ -23,7 +23,7 @@ CREATE TABLE /*$wgDBprefix*/logging (
log_comment varchar(255) NOT NULL default '',
-- LF separated list of miscellaneous parameters
- log_params blob NOT NULL default '',
+ log_params blob NOT NULL,
KEY type_time (log_type, log_timestamp),
KEY user_time (log_user, log_timestamp),
diff --git a/maintenance/archives/patch-querycachetwo.sql b/maintenance/archives/patch-querycachetwo.sql
new file mode 100644
index 00000000..cda5b90d
--- /dev/null
+++ b/maintenance/archives/patch-querycachetwo.sql
@@ -0,0 +1,22 @@
+-- Used for caching expensive grouped queries that need two links (for example double-redirects)
+
+CREATE TABLE /*$wgDBprefix*/querycachetwo (
+ -- A key name, generally the base name of of the special page.
+ qcc_type char(32) NOT NULL,
+
+ -- Some sort of stored value. Sizes, counts...
+ qcc_value int(5) unsigned NOT NULL default '0',
+
+ -- Target namespace+title
+ qcc_namespace int NOT NULL default '0',
+ qcc_title char(255) binary NOT NULL default '',
+
+ -- Target namespace+title2
+ qcc_namespacetwo int NOT NULL default '0',
+ qcc_titletwo char(255) binary NOT NULL default '',
+
+ KEY qcc_type (qcc_type,qcc_value),
+ KEY qcc_title (qcc_type,qcc_namespace,qcc_title),
+ KEY qcc_titletwo (qcc_type,qcc_namespacetwo,qcc_titletwo)
+
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-rc_len.sql b/maintenance/archives/patch-rc_len.sql
new file mode 100644
index 00000000..920f755b
--- /dev/null
+++ b/maintenance/archives/patch-rc_len.sql
@@ -0,0 +1,9 @@
+--
+-- patch-rc_len.sql
+-- Adds two rows to recentchanges to hold the text size befor and after the edit
+-- 2006-12-03
+--
+
+ALTER TABLE /*$wgDBprefix*/recentchanges
+ ADD COLUMN rc_old_len int(10), ADD COLUMN rc_new_len int(10);
+
diff --git a/maintenance/archives/patch-rc_user_text-index.sql b/maintenance/archives/patch-rc_user_text-index.sql
new file mode 100644
index 00000000..f6acc992
--- /dev/null
+++ b/maintenance/archives/patch-rc_user_text-index.sql
@@ -0,0 +1,7 @@
+-- Add an index to recentchanges on rc_user_text
+--
+-- Added 2006-11-08
+--
+
+ ALTER TABLE /*$wgDBprefix*/recentchanges
+ADD INDEX rc_user_text(rc_user_text, rc_timestamp); \ No newline at end of file
diff --git a/maintenance/archives/patch-redirect.sql b/maintenance/archives/patch-redirect.sql
new file mode 100644
index 00000000..d377f1b1
--- /dev/null
+++ b/maintenance/archives/patch-redirect.sql
@@ -0,0 +1,28 @@
+--
+-- Create the new redirect table.
+-- For each redirect, this table contains exactly one row defining its target
+--
+CREATE TABLE /*$wgDBprefix*/redirect (
+ -- Key to the page_id of the redirect page
+ rd_from int(8) unsigned NOT NULL default '0',
+
+ -- Key to page_namespace/page_title of the target page.
+ -- The target page may or may not exist, and due to renames
+ -- and deletions may refer to different page records as time
+ -- goes by.
+ rd_namespace int NOT NULL default '0',
+ rd_title varchar(255) binary NOT NULL default '',
+
+ PRIMARY KEY rd_from (rd_from),
+ KEY rd_ns_title (rd_namespace,rd_title,rd_from)
+) TYPE=InnoDB;
+
+-- Import existing redirects
+-- Using ignore because some of the redirect pages contain more than one link
+INSERT IGNORE
+ INTO /*$wgDBprefix*/redirect (rd_from,rd_namespace,rd_title)
+ SELECT pl_from,pl_namespace,pl_title
+ FROM /*$wgDBprefix*/pagelinks, /*$wgDBprefix*/page
+ WHERE pl_from=page_id AND page_is_redirect=1;
+
+
diff --git a/maintenance/archives/patch-rename-user_groups-and_rights.sql b/maintenance/archives/patch-rename-user_groups-and_rights.sql
index abd59319..650f2604 100644
--- a/maintenance/archives/patch-rename-user_groups-and_rights.sql
+++ b/maintenance/archives/patch-rename-user_groups-and_rights.sql
@@ -5,5 +5,5 @@ ALTER TABLE /*$wgDBprefix*/user_groups
ALTER TABLE /*$wgDBprefix*/user_rights
CHANGE user_id ur_user INT(5) UNSIGNED NOT NULL,
- CHANGE user_rights ur_rights TINYBLOB NOT NULL DEFAULT '';
+ CHANGE user_rights ur_rights TINYBLOB NOT NULL;
diff --git a/maintenance/archives/patch-restructure.sql b/maintenance/archives/patch-restructure.sql
index 53f1836b..acf306c2 100644
--- a/maintenance/archives/patch-restructure.sql
+++ b/maintenance/archives/patch-restructure.sql
@@ -13,7 +13,7 @@ CREATE TABLE /*$wgDBprefix*/page (
page_id int(8) unsigned NOT NULL auto_increment,
page_namespace tinyint NOT NULL,
page_title varchar(255) binary NOT NULL,
- page_restrictions tinyblob NOT NULL default '',
+ page_restrictions tinyblob NOT NULL,
page_counter bigint(20) unsigned NOT NULL default '0',
page_is_redirect tinyint(1) unsigned NOT NULL default '0',
page_is_new tinyint(1) unsigned NOT NULL default '0',
@@ -31,7 +31,7 @@ CREATE TABLE /*$wgDBprefix*/page (
CREATE TABLE /*$wgDBprefix*/revision (
rev_id int(8) unsigned NOT NULL auto_increment,
rev_page int(8) unsigned NOT NULL,
- rev_comment tinyblob NOT NULL default '',
+ rev_comment tinyblob NOT NULL,
rev_user int(5) unsigned NOT NULL default '0',
rev_user_text varchar(255) binary NOT NULL default '',
rev_timestamp char(14) binary NOT NULL default '',
@@ -51,8 +51,8 @@ CREATE TABLE /*$wgDBprefix*/revision (
--
-- CREATE TABLE /*$wgDBprefix*/text (
-- old_id int(8) unsigned NOT NULL auto_increment,
--- old_text mediumtext NOT NULL default '',
--- old_flags tinyblob NOT NULL default '',
+-- old_text mediumtext NOT NULL,
+-- old_flags tinyblob NOT NULL,
--
-- PRIMARY KEY old_id (old_id)
-- );
diff --git a/maintenance/archives/patch-searchindex.sql b/maintenance/archives/patch-searchindex.sql
index fb54dbbe..2b9b6702 100644
--- a/maintenance/archives/patch-searchindex.sql
+++ b/maintenance/archives/patch-searchindex.sql
@@ -15,7 +15,7 @@ CREATE TABLE /*$wgDBprefix*/searchindex (
si_title varchar(255) NOT NULL default '',
-- Munged version of body text
- si_text mediumtext NOT NULL default '',
+ si_text mediumtext NOT NULL,
UNIQUE KEY (si_page)
diff --git a/maintenance/archives/patch-user_editcount.sql b/maintenance/archives/patch-user_editcount.sql
new file mode 100644
index 00000000..cdde36dc
--- /dev/null
+++ b/maintenance/archives/patch-user_editcount.sql
@@ -0,0 +1,5 @@
+ALTER TABLE /*$wgDBprefix*/user
+ ADD COLUMN user_editcount int;
+
+-- Don't initialize values immediately... or should we?
+-- They will be lazy-evaluated, or batch-filled via maintenance/initEditCount.php
diff --git a/maintenance/archives/patch-user_newpass_time.sql b/maintenance/archives/patch-user_newpass_time.sql
new file mode 100644
index 00000000..47b332ba
--- /dev/null
+++ b/maintenance/archives/patch-user_newpass_time.sql
@@ -0,0 +1,4 @@
+-- Timestamp of the last time when a new password was
+-- sent, for throttling purposes
+ALTER TABLE /*$wgDBprefix*/user ADD user_newpass_time char(14) binary;
+
diff --git a/maintenance/archives/patch-user_rights.sql b/maintenance/archives/patch-user_rights.sql
index 36f0102a..a32ef457 100644
--- a/maintenance/archives/patch-user_rights.sql
+++ b/maintenance/archives/patch-user_rights.sql
@@ -10,7 +10,7 @@ CREATE TABLE /*$wgDBprefix*/user_rights (
ur_user int(5) unsigned NOT NULL,
-- Comma-separated list of permission keys
- ur_rights tinyblob NOT NULL default '',
+ ur_rights tinyblob NOT NULL,
UNIQUE KEY ur_user (ur_user)
diff --git a/maintenance/backup.inc b/maintenance/backup.inc
index 8b4b6726..1a8ff4fe 100644
--- a/maintenance/backup.inc
+++ b/maintenance/backup.inc
@@ -175,7 +175,7 @@ class BackupDumper {
$this->initProgress( $history );
$db =& $this->backupDb();
- $exporter = new WikiExporter( $db, $history, MW_EXPORT_STREAM, $text );
+ $exporter = new WikiExporter( $db, $history, WikiExporter::STREAM, $text );
$wrapper = new ExportProgressFilter( $this->sink, $this );
$exporter->setOutputSink( $wrapper );
diff --git a/maintenance/checkUsernames.php b/maintenance/checkUsernames.php
index 4c0ecdce..60e52181 100644
--- a/maintenance/checkUsernames.php
+++ b/maintenance/checkUsernames.php
@@ -7,7 +7,6 @@ class checkUsernames {
function checkUsernames() {
$this->stderr = fopen( 'php://stderr', 'wt' );
- $this->log = fopen( '/home/wikipedia/logs/checkUsernames.log', 'at' );
}
function main() {
$fname = 'checkUsernames::main';
@@ -24,7 +23,7 @@ class checkUsernames {
if ( ! User::isValidUserName( $row->user_name ) ) {
$out = sprintf( "%s: %6d: '%s'\n", wfWikiID(), $row->user_id, $row->user_name );
fwrite( $this->stderr, $out );
- fwrite( $this->log, $out );
+ wfDebugLog( 'checkUsernames', $out );
}
}
}
diff --git a/maintenance/commandLine.inc b/maintenance/commandLine.inc
index 2549057e..18a1d712 100644
--- a/maintenance/commandLine.inc
+++ b/maintenance/commandLine.inc
@@ -14,6 +14,15 @@ if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) {
exit();
}
+if( version_compare( PHP_VERSION, '5.0.0' ) < 0 ) {
+ print "Sorry! This version of MediaWiki requires PHP 5; you are running " .
+ PHP_VERSION . ".\n\n" .
+ "If you are sure you already have PHP 5 installed, it may be " .
+ "installed\n" .
+ "in a different path from PHP 4. Check with your system administrator.\n";
+ die( -1 );
+}
+
define('MEDIAWIKI',true);
# Process command line arguments
@@ -179,7 +188,9 @@ if ( file_exists( '/home/wikipedia/common/langlist' ) ) {
}
# Turn off output buffering again, it might have been turned on in the settings files
-@ob_end_flush();
+if( ob_get_level() ) {
+ ob_end_flush();
+}
# Same with these
$wgCommandLineMode = true;
diff --git a/maintenance/deleteBatch.php b/maintenance/deleteBatch.php
index 234744c3..14da6d84 100644
--- a/maintenance/deleteBatch.php
+++ b/maintenance/deleteBatch.php
@@ -3,11 +3,10 @@
# delete a batch of pages
# Usage: php deleteBatch.php [-u <user>] [-r <reason>] [-i <interval>] <listfile>
# where
-# <listfile> is a file where each line has two titles separated by a pipe
-# character. The first title is the source, the second is the destination.
+# <listfile> is a file where each line contains the title of a page to be deleted.
# <user> is the username
-# <reason> is the move reason
-# <interval> is the number of seconds to sleep for after each move
+# <reason> is the delete reason
+# <interval> is the number of seconds to sleep for after each delete
$oldCwd = getcwd();
$optionsWithArgs = array( 'u', 'r', 'i' );
@@ -50,8 +49,8 @@ $dbw =& wfGetDB( DB_MASTER );
for ( $linenum = 1; !feof( $file ); $linenum++ ) {
$line = trim( fgets( $file ) );
- if ( $line === false ) {
- break;
+ if ( $line == '' ) {
+ continue;
}
$page = Title::newFromText( $line );
if ( is_null( $page ) ) {
diff --git a/maintenance/deleteDefaultMessages.php b/maintenance/deleteDefaultMessages.php
new file mode 100644
index 00000000..76924002
--- /dev/null
+++ b/maintenance/deleteDefaultMessages.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * Deletes all pages in the MediaWiki namespace which were last edited by
+ * "MediaWiki default".
+ */
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ require_once( 'commandLine.inc' );
+ deleteDefaultMessages();
+}
+
+function deleteDefaultMessages() {
+ $user = 'MediaWiki default';
+ $reason = 'No longer required';
+
+ global $wgUser;
+ $wgUser = User::newFromName( $user );
+ $wgUser->addGroup( 'bot' );
+
+ $dbr =& wfGetDB( DB_SLAVE );
+ $res = $dbr->select( array( 'page', 'revision' ),
+ array( 'page_namespace', 'page_title' ),
+ array(
+ 'page_namespace' => NS_MEDIAWIKI,
+ 'page_latest=rev_id',
+ 'rev_user_text' => 'MediaWiki default',
+ )
+ );
+
+ $dbw =& wfGetDB( DB_MASTER );
+
+ while ( $row = $dbr->fetchObject( $res ) ) {
+ if ( function_exists( 'wfWaitForSlaves' ) ) {
+ wfWaitForSlaves( 5 );
+ }
+ $dbw->ping();
+ $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+ $article = new Article( $title );
+ $dbw->begin();
+ $article->doDeleteArticle( $reason );
+ $dbw->commit();
+ }
+}
+?>
diff --git a/maintenance/dumpHTML.inc b/maintenance/dumpHTML.inc
index ca2a62dc..702c7df9 100644
--- a/maintenance/dumpHTML.inc
+++ b/maintenance/dumpHTML.inc
@@ -38,6 +38,9 @@ class DumpHTML {
# Make a copy of all images encountered
var $makeSnapshot = false;
+ # Don't image description pages in doEverything()
+ var $noSharedDesc = false;
+
# Make links assuming the script path is in the same directory as
# the destination
var $alternateScriptPath = false;
@@ -67,6 +70,9 @@ class DumpHTML {
# Max page ID, lazy initialised
var $maxPageID = false;
+ # UDP profiling
+ var $udpProfile, $udpProfileCounter = 0, $udpProfileInit = false;
+
function DumpHTML( $settings = array() ) {
foreach ( $settings as $var => $value ) {
$this->$var = $value;
@@ -124,13 +130,16 @@ class DumpHTML {
return;
}
$this->doArticles();
- $this->doLocalImageDescriptions();
- $this->doSharedImageDescriptions();
$this->doCategories();
$this->doRedirects();
if ( $this->sliceNumerator == 1 ) {
$this->doSpecials();
}
+ $this->doLocalImageDescriptions();
+
+ if ( !$this->noSharedDesc ) {
+ $this->doSharedImageDescriptions();
+ }
$this->setCheckpoint( 'everything', 'done' );
}
@@ -179,7 +188,8 @@ class DumpHTML {
$title = Title::newFromID( $id );
if ( $title ) {
$ns = $title->getNamespace() ;
- if ( $ns != NS_CATEGORY && $title->getPrefixedDBkey() != $mainPage ) {
+ if ( $ns != NS_CATEGORY && $ns != NS_MEDIAWIKI &&
+ $title->getPrefixedDBkey() != $mainPage ) {
$this->doArticle( $title );
}
}
@@ -193,7 +203,7 @@ class DumpHTML {
$this->setupGlobals();
print "Special:Categories...";
- $this->doArticle( Title::makeTitle( NS_SPECIAL, 'Categories' ) );
+ $this->doArticle( SpecialPage::getTitleFor( 'Categories' ) );
print "\n";
}
@@ -224,7 +234,9 @@ class DumpHTML {
function doImageDescriptions() {
$this->doLocalImageDescriptions();
- $this->doSharedImageDescriptions();
+ if ( !$this->noSharedDesc ) {
+ $this->doSharedImageDescriptions();
+ }
}
/**
@@ -309,19 +321,23 @@ class DumpHTML {
for ( $hash = $start; $hash <= $end; $hash++ ) {
$this->setCheckpoint( 'shared image', $hash );
- $dir = sprintf( "%01x/%02x", intval( $hash / 16 ), $hash );
- $paths = array_merge( glob( "{$this->sharedStaticDirectory}/$dir/*" ),
- glob( "{$this->sharedStaticDirectory}/thumb/$dir/*" ) );
-
- foreach ( $paths as $path ) {
- $file = wfBaseName( $path );
+ $dir = sprintf( "%s/%01x/%02x", $this->sharedStaticDirectory,
+ intval( $hash / 16 ), $hash );
+ $handle = @opendir( $dir );
+ while ( $handle && $file = readdir( $handle ) ) {
+ if ( $file[0] == '.' ) {
+ continue;
+ }
if ( !(++$i % REPORTING_INTERVAL ) ) {
print "$i\r";
}
- $title = Title::makeTitle( NS_IMAGE, $file );
+ $title = Title::makeTitleSafe( NS_IMAGE, $file );
$this->doArticle( $title );
}
+ if ( $handle ) {
+ closedir( $handle );
+ }
}
$this->setCheckpoint( 'shared image', 'done' );
print "\n";
@@ -437,6 +453,8 @@ class DumpHTML {
}
}
+ $this->profile();
+
$this->rawPages = array();
$text = $this->getArticleHTML( $title );
@@ -473,11 +491,26 @@ class DumpHTML {
fclose( $file );
}
}
+
+ wfIncrStats( 'dumphtml_article' );
}
/** Write the given text to the file identified by the given title object */
function writeArticle( &$title, $text ) {
$filename = $this->getHashedFilename( $title );
+
+ # Temporary hack for current dump, this should be moved to
+ # getFriendlyName() at the earliest opportunity.
+ #
+ # Limit filename length to 255 characters, so it works on ext3.
+ # Titles are in fact limited to 255 characters, but dumpHTML
+ # adds a suffix which may put them over the limit.
+ $length = strlen( $filename );
+ if ( $length > 255 ) {
+ print "Warning: Filename too long ($length bytes). Skipping.\n";
+ return;
+ }
+
$fullName = "{$this->dest}/$filename";
$fullDir = dirname( $fullName );
@@ -579,13 +612,11 @@ class DumpHTML {
$wgUser->setOption( 'skin', $this->skin );
$wgUser->setOption( 'editsection', 0 );
- if ( $this->makeSnapshot ) {
- $this->destUploadDirectory = "{$this->dest}/{$this->imageRel}";
- if ( realpath( $this->destUploadDirectory == $wgUploadDirectory ) ) {
- $this->makeSnapshot = false;
- }
+ $this->destUploadDirectory = "{$this->dest}/{$this->imageRel}";
+ if ( realpath( $this->destUploadDirectory ) == realpath( $wgUploadDirectory ) ) {
+ print "Disabling image snapshot because the destination is the same as the source\n";
+ $this->makeSnapshot = false;
}
-
$this->sharedStaticDirectory = "{$this->destUploadDirectory}/shared";
$this->setupDone = true;
@@ -683,9 +714,13 @@ ENDTEXT;
if ( !file_exists( $destLoc ) ) {
wfMkdirParents( dirname( $destLoc ), 0755 );
if ( function_exists( 'symlink' ) && !$this->forceCopy ) {
- symlink( $sourceLoc, $destLoc );
+ if ( !symlink( $sourceLoc, $destLoc ) ) {
+ print "Warning: unable to create symlink at $destLoc\n";
+ }
} else {
- copy( $sourceLoc, $destLoc );
+ if ( !copy( $sourceLoc, $destLoc ) ) {
+ print "Warning: unable to copy $sourceLoc to $destLoc\n";
+ }
}
}
}
@@ -928,7 +963,33 @@ ENDTEXT;
}
return $this->maxPageID;
}
-
+
+ function profile() {
+ global $wgProfiler;
+
+ if ( !$this->udpProfile ) {
+ return;
+ }
+ if ( !$this->udpProfileInit ) {
+ $this->udpProfileInit = true;
+ } elseif ( $this->udpProfileCounter == 1 % $this->udpProfile ) {
+ $wgProfiler->getFunctionReport();
+ $wgProfiler = new DumpHTML_ProfilerStub;
+ }
+ if ( $this->udpProfileCounter == 0 ) {
+ $wgProfiler = new ProfilerSimpleUDP;
+ $wgProfiler->setProfileID( 'dumpHTML' );
+ }
+ $this->udpProfileCounter = ( $this->udpProfileCounter + 1 ) % $this->udpProfile;
+ }
+}
+
+class DumpHTML_ProfilerStub {
+ function profileIn() {}
+ function profileOut() {}
+ function getOutput() {}
+ function close() {}
+ function getFunctionReport() {}
}
/** XML parser callback */
diff --git a/maintenance/dumpHTML.php b/maintenance/dumpHTML.php
index 5e347e4b..2c0c29c4 100644
--- a/maintenance/dumpHTML.php
+++ b/maintenance/dumpHTML.php
@@ -17,6 +17,8 @@
* --checkpoint <file> use a checkpoint file to allow restarting of interrupted dumps
* --slice <n/m> split the job into m segments and do the n'th one
* --images only do image description pages
+ * --shared-desc only do shared (commons) image description pages
+ * --no-shared-desc don't do shared image description pages
* --categories only do category pages
* --redirects only do redirects
* --special only do miscellaneous stuff
@@ -24,10 +26,11 @@
* --interlang allow interlanguage links
* --image-snapshot copy all images used to the destination directory
* --compress generate compressed version of the html pages
+ * --udp-profile <N> profile 1/N rendering operations using ProfilerSimpleUDP
*/
-$optionsWithArgs = array( 's', 'd', 'e', 'k', 'checkpoint', 'slice' );
+$optionsWithArgs = array( 's', 'd', 'e', 'k', 'checkpoint', 'slice', 'udp-profile' );
$profiling = false;
@@ -41,6 +44,10 @@ if ( $profiling ) {
}
}
+if ( in_array( '--udp-profile', $argv ) ) {
+ define( 'MW_FORCE_PROFILE', 1 );
+}
+
require_once( "commandLine.inc" );
require_once( "dumpHTML.inc" );
@@ -93,6 +100,8 @@ $wgHTMLDump = new DumpHTML( array(
'sliceDenominator' => $sliceDenominator,
'noOverwrite' => $options['no-overwrite'],
'compress' => $options['compress'],
+ 'noSharedDesc' => $options['no-shared-desc'],
+ 'udpProfile' => $options['udp-profile'],
));
@@ -104,6 +113,8 @@ if ( $options['special'] ) {
$wgHTMLDump->doCategories();
} elseif ( $options['redirects'] ) {
$wgHTMLDump->doRedirects();
+} elseif ( $options['shared-desc'] ) {
+ $wgHTMLDump->doSharedImageDescriptions();
} else {
print "Creating static HTML dump in directory $dest. \n";
$dbr =& wfGetDB( DB_SLAVE );
diff --git a/maintenance/edit.php b/maintenance/edit.php
new file mode 100644
index 00000000..33e0607b
--- /dev/null
+++ b/maintenance/edit.php
@@ -0,0 +1,68 @@
+<?php
+
+$optionsWithArgs = array( 'u', 's' );
+
+require_once( 'commandLine.inc' );
+
+if ( count( $args ) == 0 || isset( $options['help'] ) ) {
+ print <<<EOT
+Edit an article from the command line
+
+Usage: php edit.php [options...] <title>
+
+Options:
+ -u <user> Username
+ -s <summary> Edit summary
+ -m Minor edit
+ -b Bot (hidden) edit
+ -a Enable autosummary
+ --no-rc Do not show the change in recent changes
+
+If the specified user does not exist, it will be created.
+The text for the edit will be read from stdin.
+
+EOT;
+ exit( 1 );
+}
+
+$userName = isset( $options['u'] ) ? $options['u'] : 'Maintenance script';
+$summary = isset( $options['s'] ) ? $options['s'] : '';
+$minor = isset( $options['m'] );
+$bot = isset( $options['b'] );
+$autoSummary = isset( $options['a'] );
+$noRC = isset( $options['no-rc'] );
+
+$wgUser = User::newFromName( $userName );
+if ( !$wgUser ) {
+ print "Invalid username\n";
+ exit( 1 );
+}
+if ( $wgUser->isAnon() ) {
+ $wgUser->addToDatabase();
+}
+
+$wgTitle = Title::newFromText( $args[0] );
+if ( !$wgTitle ) {
+ print "Invalid title\n";
+ exit( 1 );
+}
+
+$wgArticle = new Article( $wgTitle );
+
+# Read the text
+$text = file_get_contents( 'php://stdin' );
+
+# Do the edit
+print "Saving... ";
+$success = $wgArticle->doEdit( $text, $summary,
+ ( $minor ? EDIT_MINOR : 0 ) |
+ ( $bot ? EDIT_FORCE_BOT : 0 ) |
+ ( $autoSummary ? EDIT_AUTOSUMMARY : 0 ) |
+ ( $noRC ? EDIT_SUPPRESS_RC : 0 ) );
+if ( $success ) {
+ print "done\n";
+} else {
+ print "failed\n";
+ exit( 1 );
+}
+?>
diff --git a/maintenance/fuzz-tester.php b/maintenance/fuzz-tester.php
index 23c3cd7c..0ee052b2 100644
--- a/maintenance/fuzz-tester.php
+++ b/maintenance/fuzz-tester.php
@@ -694,7 +694,7 @@ class wikiFuzz {
);
/**
- ** @desc: Randomly returns one element of the input array.
+ ** Randomly returns one element of the input array.
*/
static public function chooseInput(array $input) {
$randindex = wikiFuzz::randnum(count($input) - 1);
@@ -705,14 +705,14 @@ class wikiFuzz {
static private $maxparams = 10;
/**
- ** @desc: Returns random number between finish and start.
+ ** Returns random number between finish and start.
*/
static public function randnum($finish,$start=0) {
return mt_rand($start,$finish);
}
/**
- ** @desc: Returns a mix of random text and random wiki syntax.
+ ** Returns a mix of random text and random wiki syntax.
*/
static private function randstring() {
$thestring = "";
@@ -740,7 +740,7 @@ class wikiFuzz {
}
/**
- ** @desc: Returns either random text, or random wiki syntax, or random data from "ints",
+ ** Returns either random text, or random wiki syntax, or random data from "ints",
** or random data from "other".
*/
static private function makestring() {
@@ -758,7 +758,7 @@ class wikiFuzz {
/**
- ** @desc: Strips out the stuff that Mediawiki balks at in a page's title.
+ ** Strips out the stuff that Mediawiki balks at in a page's title.
** Implementation copied/pasted from cleanupTable.inc & cleanupImages.php
*/
static public function makeTitleSafe($str) {
@@ -775,7 +775,7 @@ class wikiFuzz {
}
/**
- ** @desc: Returns a string of fuzz text.
+ ** Returns a string of fuzz text.
*/
static private function loop() {
switch ( wikiFuzz::randnum(3) ) {
@@ -803,7 +803,7 @@ class wikiFuzz {
}
/**
- ** @desc: Returns one of the three styles of random quote: ', ", and nothing.
+ ** Returns one of the three styles of random quote: ', ", and nothing.
*/
static private function getRandQuote() {
switch ( wikiFuzz::randnum(3) ) {
@@ -814,7 +814,7 @@ class wikiFuzz {
}
/**
- ** @desc: Returns fuzz text, with the parameter indicating approximately how many lines of text you want.
+ ** Returns fuzz text, with the parameter indicating approximately how many lines of text you want.
*/
static public function makeFuzz($maxtypes = 2) {
$page = "";
@@ -829,7 +829,7 @@ class wikiFuzz {
//////// MEDIAWIKI PAGES TO TEST, AND HOW TO TEST THEM ///////
/**
- ** @desc: A page test has just these things:
+ ** 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.
@@ -856,7 +856,7 @@ abstract class pageTest {
/**
- ** @desc: a page test for the "Edit" page. Tests Parser.php and Sanitizer.php.
+ ** a page test for the "Edit" page. Tests Parser.php and Sanitizer.php.
*/
class editPageTest extends pageTest {
function __construct() {
@@ -888,7 +888,7 @@ class editPageTest extends pageTest {
/**
- ** @desc: a page test for "Special:Listusers".
+ ** a page test for "Special:Listusers".
*/
class listusersTest extends pageTest {
function __construct() {
@@ -907,7 +907,7 @@ class listusersTest extends pageTest {
/**
- ** @desc: a page test for "Special:Search".
+ ** a page test for "Special:Search".
*/
class searchTest extends pageTest {
function __construct() {
@@ -942,7 +942,7 @@ class searchTest extends pageTest {
/**
- ** @desc: a page test for "Special:Recentchanges".
+ ** a page test for "Special:Recentchanges".
*/
class recentchangesTest extends pageTest {
function __construct() {
@@ -971,7 +971,7 @@ class recentchangesTest extends pageTest {
/**
- ** @desc: a page test for "Special:Prefixindex".
+ ** a page test for "Special:Prefixindex".
*/
class prefixindexTest extends pageTest {
function __construct() {
@@ -997,7 +997,7 @@ class prefixindexTest extends pageTest {
/**
- ** @desc: a page test for "Special:MIMEsearch".
+ ** a page test for "Special:MIMEsearch".
*/
class mimeSearchTest extends pageTest {
function __construct() {
@@ -1014,7 +1014,7 @@ class mimeSearchTest extends pageTest {
/**
- ** @desc: a page test for "Special:Log".
+ ** a page test for "Special:Log".
*/
class specialLogTest extends pageTest {
function __construct() {
@@ -1034,7 +1034,7 @@ class specialLogTest extends pageTest {
/**
- ** @desc: a page test for "Special:Userlogin", with a successful login.
+ ** a page test for "Special:Userlogin", with a successful login.
*/
class successfulUserLoginTest extends pageTest {
function __construct() {
@@ -1053,7 +1053,7 @@ class successfulUserLoginTest extends pageTest {
/**
- ** @desc: a page test for "Special:Userlogin".
+ ** a page test for "Special:Userlogin".
*/
class userLoginTest extends pageTest {
function __construct() {
@@ -1084,7 +1084,7 @@ class userLoginTest extends pageTest {
/**
- ** @desc: a page test for "Special:Ipblocklist" (also includes unblocking)
+ ** a page test for "Special:Ipblocklist" (also includes unblocking)
*/
class ipblocklistTest extends pageTest {
function __construct() {
@@ -1117,7 +1117,7 @@ class ipblocklistTest extends pageTest {
/**
- ** @desc: a page test for "Special:Newimages".
+ ** a page test for "Special:Newimages".
*/
class newImagesTest extends pageTest {
function __construct() {
@@ -1138,7 +1138,7 @@ class newImagesTest extends pageTest {
/**
- ** @desc: a page test for the "Special:Imagelist" page.
+ ** a page test for the "Special:Imagelist" page.
*/
class imagelistTest extends pageTest {
function __construct() {
@@ -1155,7 +1155,7 @@ class imagelistTest extends pageTest {
/**
- ** @desc: a page test for "Special:Export".
+ ** a page test for "Special:Export".
*/
class specialExportTest extends pageTest {
function __construct() {
@@ -1180,7 +1180,7 @@ class specialExportTest extends pageTest {
/**
- ** @desc: a page test for "Special:Booksources".
+ ** a page test for "Special:Booksources".
*/
class specialBooksourcesTest extends pageTest {
function __construct() {
@@ -1196,7 +1196,7 @@ class specialBooksourcesTest extends pageTest {
/**
- ** @desc: a page test for "Special:Allpages".
+ ** a page test for "Special:Allpages".
*/
class specialAllpagesTest extends pageTest {
function __construct() {
@@ -1212,7 +1212,7 @@ class specialAllpagesTest extends pageTest {
/**
- ** @desc: a page test for the page History.
+ ** a page test for the page History.
*/
class pageHistoryTest extends pageTest {
function __construct() {
@@ -1232,7 +1232,7 @@ class pageHistoryTest extends pageTest {
/**
- ** @desc: a page test for the Special:Contributions".
+ ** a page test for the Special:Contributions".
*/
class contributionsTest extends pageTest {
function __construct() {
@@ -1250,7 +1250,7 @@ class contributionsTest extends pageTest {
/**
- ** @desc: a page test for viewing a normal page, whilst posting various params.
+ ** a page test for viewing a normal page, whilst posting various params.
*/
class viewPageTest extends pageTest {
function __construct() {
@@ -1317,7 +1317,7 @@ class viewPageTest extends pageTest {
/**
- ** @desc: a page test for "Special:Allmessages".
+ ** a page test for "Special:Allmessages".
*/
class specialAllmessagesTest extends pageTest {
function __construct() {
@@ -1331,7 +1331,7 @@ class specialAllmessagesTest extends pageTest {
}
/**
- ** @desc: a page test for "Special:Newpages".
+ ** a page test for "Special:Newpages".
*/
class specialNewpages extends pageTest {
function __construct() {
@@ -1351,7 +1351,7 @@ class specialNewpages extends pageTest {
}
/**
- ** @desc: a page test for "redirect.php"
+ ** a page test for "redirect.php"
*/
class redirectTest extends pageTest {
function __construct() {
@@ -1368,7 +1368,7 @@ class redirectTest extends pageTest {
/**
- ** @desc: a page test for "Special:Confirmemail"
+ ** a page test for "Special:Confirmemail"
*/
class confirmEmail extends pageTest {
function __construct() {
@@ -1383,7 +1383,7 @@ class confirmEmail extends pageTest {
/**
- ** @desc: a page test for "Special:Watchlist"
+ ** a page test for "Special:Watchlist"
** Note: this test would be better if we were logged in.
*/
class watchlistTest extends pageTest {
@@ -1409,7 +1409,7 @@ class watchlistTest extends pageTest {
/**
- ** @desc: a page test for "Special:Blockme"
+ ** a page test for "Special:Blockme"
*/
class specialBlockmeTest extends pageTest {
function __construct() {
@@ -1426,7 +1426,7 @@ class specialBlockmeTest extends pageTest {
/**
- ** @desc: a page test for "Special:Movepage"
+ ** a page test for "Special:Movepage"
*/
class specialMovePage extends pageTest {
function __construct() {
@@ -1459,7 +1459,7 @@ class specialMovePage extends pageTest {
/**
- ** @desc: a page test for "Special:Undelete"
+ ** a page test for "Special:Undelete"
*/
class specialUndelete extends pageTest {
function __construct() {
@@ -1486,7 +1486,7 @@ class specialUndelete extends pageTest {
/**
- ** @desc: a page test for "Special:Unlockdb"
+ ** a page test for "Special:Unlockdb"
*/
class specialUnlockdb extends pageTest {
function __construct() {
@@ -1507,7 +1507,7 @@ class specialUnlockdb extends pageTest {
/**
- ** @desc: a page test for "Special:Lockdb"
+ ** a page test for "Special:Lockdb"
*/
class specialLockdb extends pageTest {
function __construct() {
@@ -1529,7 +1529,7 @@ class specialLockdb extends pageTest {
/**
- ** @desc: a page test for "Special:Userrights"
+ ** a page test for "Special:Userrights"
*/
class specialUserrights extends pageTest {
function __construct() {
@@ -1552,7 +1552,7 @@ class specialUserrights extends pageTest {
/**
- ** @desc: a test for page protection and unprotection.
+ ** a test for page protection and unprotection.
*/
class pageProtectionForm extends pageTest {
function __construct() {
@@ -1576,7 +1576,7 @@ class pageProtectionForm extends pageTest {
/**
- ** @desc: a page test for "Special:Blockip".
+ ** a page test for "Special:Blockip".
*/
class specialBlockip extends pageTest {
function __construct() {
@@ -1615,7 +1615,7 @@ class specialBlockip extends pageTest {
/**
- ** @desc: a test for the imagepage.
+ ** a test for the imagepage.
*/
class imagepageTest extends pageTest {
function __construct() {
@@ -1638,7 +1638,7 @@ class imagepageTest extends pageTest {
/**
- ** @desc: a test for page deletion form.
+ ** a test for page deletion form.
*/
class pageDeletion extends pageTest {
function __construct() {
@@ -1660,7 +1660,7 @@ class pageDeletion extends pageTest {
/**
- ** @desc: a test for Revision Deletion.
+ ** a test for Revision Deletion.
*/
class specialRevisionDelete extends pageTest {
function __construct() {
@@ -1691,7 +1691,7 @@ class specialRevisionDelete extends pageTest {
/**
- ** @desc: a test for Special:Import.
+ ** a test for Special:Import.
*/
class specialImport extends pageTest {
function __construct() {
@@ -1724,7 +1724,7 @@ class specialImport extends pageTest {
/**
- ** @desc: a test for thumb.php
+ ** a test for thumb.php
*/
class thumbTest extends pageTest {
function __construct() {
@@ -1745,7 +1745,7 @@ class thumbTest extends pageTest {
/**
- ** @desc: a test for trackback.php
+ ** a test for trackback.php
*/
class trackbackTest extends pageTest {
function __construct() {
@@ -1767,7 +1767,7 @@ class trackbackTest extends pageTest {
/**
- ** @desc: a test for profileinfo.php
+ ** a test for profileinfo.php
*/
class profileInfo extends pageTest {
function __construct() {
@@ -1787,7 +1787,7 @@ class profileInfo extends pageTest {
/**
- ** @desc: a test for Special:Cite (extension Special page).
+ ** a test for Special:Cite (extension Special page).
*/
class specialCite extends pageTest {
function __construct() {
@@ -1806,7 +1806,7 @@ class specialCite extends pageTest {
/**
- ** @desc: a test for Special:Filepath (extension Special page).
+ ** a test for Special:Filepath (extension Special page).
*/
class specialFilepath extends pageTest {
function __construct() {
@@ -1820,7 +1820,7 @@ class specialFilepath extends pageTest {
/**
- ** @desc: a test for Special:Makebot (extension Special page).
+ ** a test for Special:Makebot (extension Special page).
*/
class specialMakebot extends pageTest {
function __construct() {
@@ -1843,7 +1843,7 @@ class specialMakebot extends pageTest {
/**
- ** @desc: a test for Special:Makesysop (extension Special page).
+ ** a test for Special:Makesysop (extension Special page).
*/
class specialMakesysop extends pageTest {
function __construct() {
@@ -1866,7 +1866,7 @@ class specialMakesysop extends pageTest {
/**
- ** @desc: a test for Special:Renameuser (extension Special page).
+ ** a test for Special:Renameuser (extension Special page).
*/
class specialRenameuser extends pageTest {
function __construct() {
@@ -1882,7 +1882,7 @@ class specialRenameuser extends pageTest {
/**
- ** @desc: a test for Special:Linksearch (extension Special page).
+ ** a test for Special:Linksearch (extension Special page).
*/
class specialLinksearch extends pageTest {
function __construct() {
@@ -1899,7 +1899,7 @@ class specialLinksearch extends pageTest {
/**
- ** @desc: a test for Special:CategoryTree (extension Special page).
+ ** a test for Special:CategoryTree (extension Special page).
*/
class specialCategoryTree extends pageTest {
function __construct() {
@@ -1921,7 +1921,7 @@ class specialCategoryTree extends pageTest {
/**
- ** @desc: selects a page test to run.
+ ** selects a page test to run.
*/
function selectPageTest($count) {
@@ -1987,7 +1987,7 @@ function selectPageTest($count) {
/////////////////////// SAVING OUTPUT /////////////////////////
/**
- ** @desc: Utility function for saving a file. Currently has no error checking.
+ ** Utility function for saving a file. Currently has no error checking.
*/
function saveFile($data, $name) {
file_put_contents($name, $data);
@@ -1995,7 +1995,7 @@ function saveFile($data, $name) {
/**
- ** @desc: Returns a test as an experimental GET-to-POST URL.
+ ** 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.
*/
@@ -2017,7 +2017,7 @@ function getAsURL(pageTest $test) {
/**
- ** @desc: Saves a plain-text human-readable version of a test.
+ ** Saves a plain-text human-readable version of a test.
*/
function saveTestAsText(pageTest $test, $filename) {
$str = "Test: " . $test->getPagePath();
@@ -2030,7 +2030,7 @@ function saveTestAsText(pageTest $test, $filename) {
/**
- ** @desc: Saves a test as a standalone basic PHP script that shows this one problem.
+ ** 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) {
@@ -2051,7 +2051,7 @@ function saveTestAsPHP(pageTest $test, $filename) {
/**
- ** @desc: Escapes a value so that it can be used on the command line by Curl.
+ ** 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.
*/
@@ -2068,7 +2068,7 @@ function escapeForCurl(array $input_params) {
/**
- ** @desc: Saves a test as a standalone CURL shell script that shows this one problem.
+ ** 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) {
@@ -2086,7 +2086,7 @@ function saveTestAsCurl(pageTest $test, $filename) {
/**
- ** @desc: Saves the internal data structure to file.
+ ** Saves the internal data structure to file.
*/
function saveTestData (pageTest $test, $filename) {
saveFile(serialize($test), $filename);
@@ -2094,7 +2094,7 @@ function saveTestData (pageTest $test, $filename) {
/**
- ** @desc: saves a test in the various formats.
+ ** saves a test in the various formats.
*/
function saveTest(pageTest $test, $testname) {
$base_name = DIRECTORY . "/" . $testname;
@@ -2108,7 +2108,7 @@ function saveTest(pageTest $test, $testname) {
//////////////////// MEDIAWIKI OUTPUT /////////////////////////
/**
- ** @desc: Asks MediaWiki for the HTML output of a test.
+ ** Asks MediaWiki for the HTML output of a test.
*/
function wikiTestOutput(pageTest $test) {
@@ -2141,7 +2141,7 @@ function wikiTestOutput(pageTest $test) {
//////////////////// HTML VALIDATION /////////////////////////
/*
- ** @desc: Asks the validator whether this is valid HTML, or not.
+ ** Asks the validator whether this is valid HTML, or not.
*/
function validateHTML($text) {
@@ -2172,7 +2172,7 @@ function validateHTML($text) {
/**
- ** @desc: Get tidy to check for no HTML errors in the output file (e.g. unescaped strings).
+ ** Get tidy to check for no HTML errors in the output file (e.g. unescaped strings).
*/
function tidyCheckFile($name) {
$file = DIRECTORY . "/" . $name;
@@ -2193,7 +2193,7 @@ function tidyCheckFile($name) {
/**
- ** @desc: Returns whether or not an database error log file has changed in size since
+ ** 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.
*/
function dbErrorLogged() {
@@ -2222,7 +2222,7 @@ function dbErrorLogged() {
////////////////// TOP-LEVEL PROBLEM-FINDING FUNCTION ////////////////////////
/**
- ** @desc: takes a page test, and runs it and tests it for problems in the output.
+ ** 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.
*/
function runWikiTest(pageTest $test, &$testname, $can_overwrite = false) {
@@ -2315,7 +2315,7 @@ function runWikiTest(pageTest $test, &$testname, $can_overwrite = false) {
/////////////////// RERUNNING OLD TESTS ///////////////////
/**
- ** @desc: We keep our failed tests so that they can be rerun.
+ ** We keep our failed tests so that they can be rerun.
** This function does that retesting.
*/
function rerunPreviousTests() {
diff --git a/maintenance/generateSitemap.php b/maintenance/generateSitemap.php
index a0b6979d..b8d6a5d6 100644
--- a/maintenance/generateSitemap.php
+++ b/maintenance/generateSitemap.php
@@ -264,6 +264,16 @@ class GenerateSitemap {
$entry = $this->fileEntry( $title->getFullURL(), $date, $this->priority( $namespace ) );
$length += strlen( $entry );
$this->write( $this->file, $entry );
+ // generate pages for language variants
+ if($wgContLang->hasVariants()){
+ $variants = $wgContLang->getVariants();
+ foreach($variants as $vCode){
+ if($vCode==$wgContLang->getCode()) continue; // we don't want default variant
+ $entry = $this->fileEntry( $title->getFullURL('',$vCode), $date, $this->priority( $namespace ) );
+ $length += strlen( $entry );
+ $this->write( $this->file, $entry );
+ }
+ }
}
if ( $this->file ) {
$this->write( $this->file, $this->closeFile() );
diff --git a/maintenance/getLagTimes.php b/maintenance/getLagTimes.php
new file mode 100644
index 00000000..f2c06f6a
--- /dev/null
+++ b/maintenance/getLagTimes.php
@@ -0,0 +1,23 @@
+<?php
+
+require 'commandLine.inc';
+
+if( empty( $wgDBservers ) ) {
+ echo "This script dumps replication lag times, but you don't seem to have\n";
+ echo "a multi-host db server configuration.\n";
+} else {
+ $lags = $wgLoadBalancer->getLagTimes();
+ foreach( $lags as $n => $lag ) {
+ $host = $wgDBservers[$n]["host"];
+ if( IP::isValid( $host ) ) {
+ $ip = $host;
+ $host = gethostbyaddr( $host );
+ } else {
+ $ip = gethostbyname( $host );
+ }
+ $stars = str_repeat( '*', intval( $lag ) );
+ printf( "%10s %20s %3d %s\n", $ip, $host, $lag, $stars );
+ }
+}
+
+?> \ No newline at end of file
diff --git a/maintenance/getSlaveServer.php b/maintenance/getSlaveServer.php
new file mode 100644
index 00000000..ebeddc4c
--- /dev/null
+++ b/maintenance/getSlaveServer.php
@@ -0,0 +1,7 @@
+<?php
+
+require_once( dirname(__FILE__).'/commandLine.inc' );
+$i = $wgLoadBalancer->getReaderIndex();
+print $wgDBservers[$i]['host'] . "\n";
+
+?>
diff --git a/maintenance/importDump.php b/maintenance/importDump.php
index 1bca3296..22709f64 100644
--- a/maintenance/importDump.php
+++ b/maintenance/importDump.php
@@ -136,6 +136,8 @@ if( WikiError::isError( $result ) ) {
echo $result->getMessage() . "\n";
} else {
echo "Done!\n";
+ echo "You might want to run rebuildrecentchanges.php to regenerate\n";
+ echo "the recentchanges page.";
}
?>
diff --git a/maintenance/importImages.php b/maintenance/importImages.php
index 2cf8bd19..abf0ec09 100644
--- a/maintenance/importImages.php
+++ b/maintenance/importImages.php
@@ -30,7 +30,9 @@ if( count( $args ) > 1 ) {
$wgUser = User::newFromName( $options['user'] );
} else {
$wgUser = User::newFromName( 'Image import script' );
- $wgUser->setLoaded( true );
+ }
+ if ( $wgUser->isAnon() ) {
+ $wgUser->addToDatabase();
}
# Get the upload comment
@@ -119,4 +121,4 @@ END;
exit();
}
-?> \ No newline at end of file
+?>
diff --git a/maintenance/importTextFile.php b/maintenance/importTextFile.php
index 625763be..92c31fd0 100644
--- a/maintenance/importTextFile.php
+++ b/maintenance/importTextFile.php
@@ -1,111 +1,84 @@
<?php
/**
- * Maintenance script to insert an article, importing text from a file
+ * Maintenance script allows creating or editing pages using
+ * the contents of a text file
*
* @package MediaWiki
* @subpackage Maintenance
* @author Rob Church <robchur@gmail.com>
*/
-
-$options = array( 'help', 'norc' );
+
+$options = array( 'help', 'nooverwrite' );
$optionsWithArgs = array( 'title', 'user', 'comment' );
require_once( 'commandLine.inc' );
-require_once( 'importTextFile.inc' );
echo( "Import Text File\n\n" );
-if( !isset( $options['help'] ) || !$options['help'] ) {
+if( isset( $options['help'] ) ) {
+ showHelp();
+} else {
- # Check file existence
$filename = $args[0];
- echo( "Using file '{$filename}'..." );
- if( file_exists( $filename ) ) {
- echo( "found.\n" );
-
- # Work out the title for the page
- if( isset( $option['title'] ) || trim( $options['title'] ) != '' ) {
- $titleText = $options['title'];
- # Use the supplied title
- echo( "Using title '{$titleText}'..." );
- $title = Title::newFromText( $options['title'] );
- } else {
- # Attempt to make a title out of the filename
- echo( "Using title from filename..." );
- $title = titleFromFilename( $filename );
- }
+ echo( "Using {$filename}..." );
+ if( is_file( $filename ) ) {
- # Check the title's valid
- if( !is_null( $title ) && is_object( $title ) ) {
- echo( "ok.\n" );
+ $title = isset( $options['title'] ) ? $options['title'] : titleFromFilename( $filename );
+ $title = Title::newFromUrl( $title );
+ echo( "\nUsing title '" . $title->getPrefixedText() . "'..." );
- # Read in the text
- $text = file_get_contents( $filename );
-
- # Check the supplied user and fall back to a default if needed
- if( isset( $options['user'] ) && trim( $options['user'] ) != '' ) {
- $username = $options['user'];
- } else {
- $username = 'MediaWiki default';
- }
- echo( "Using user '{$username}'..." );
- $user = User::newFromName( $username );
-
- # Check the user's valid
- if( !is_null( $user ) && is_object( $user ) ) {
- echo( "ok.\n" );
- $wgUser =& $user;
+ if( is_object( $title ) ) {
- # If a comment was supplied, use it (replace _ with spaces ) else use a default
- if( isset( $options['comment'] ) || trim( $options['comment'] != '' ) ) {
- $comment = str_replace( '_', ' ', $options['comment'] );
- } else {
- $comment = 'Importing text file';
- }
- echo( "Using edit summary '{$comment}'.\n" );
+ if( !$title->exists() || !isset( $options['nooverwrite'] ) ) {
- # Do we need to update recent changes?
- if( isset( $options['norc'] ) && $options['norc'] ) {
- $rc = false;
- } else {
- $rc = true;
- }
-
- # Attempt the insertion
- echo( "Attempting to insert page..." );
- $success = insertNewArticle( $title, $text, $user, $comment, $rc );
- if( $success ) {
+ $text = file_get_contents( $filename );
+ $user = isset( $options['user'] ) ? $options['user'] : 'MediaWiki default';
+ $user = User::newFromName( $user );
+ echo( "\nUsing username '" . $user->getName() . "'..." );
+
+ if( is_object( $user ) ) {
+
+ $wgUser =& $user;
+ $comment = isset( $options['comment'] ) ? $options['comment'] : 'Importing text file';
+ $comment = str_replace( '_', ' ', $comment );
+
+ echo( "\nPerforming edit..." );
+ $article = new Article( $title );
+ $article->doEdit( $text, $comment );
echo( "done.\n" );
+
} else {
- echo( "failed. Title exists.\n" );
+ echo( "invalid username.\n" );
}
} else {
- # Dud user
- echo( "invalid username.\n" );
+ echo( "page exists.\n" );
}
} else {
- # Dud title
echo( "invalid title.\n" );
}
} else {
- # File not found
- echo( "not found.\n" );
+ echo( "does not exist.\n" );
}
-} else {
- # Show help
- echo( "Imports the contents of a text file into a wiki page.\n\n" );
- echo( "USAGE: php importTextFile.php [--help|--title <title>|--user <user>|--comment <comment>|--norc] <filename>\n\n" );
+}
+
+function titleFromFilename( $filename ) {
+ $parts = explode( '/', $filename );
+ $parts = explode( '.', $parts[ count( $parts ) - 1 ] );
+ return $parts[0];
+}
+
+function showHelp() {
+ echo( "Import the contents of a text file into a wiki page.\n\n" );
+ echo( "USAGE: php importTextFile.php [--help|--title <title>|--user <user>|--comment <comment>|--nooverwrite] <filename>\n\n" );
echo( " --help: Show this help information\n" );
echo( " --title <title> : Title for the new page; if not supplied, the filename is used as a base for the title\n" );
echo( " --user <user> : User to be associated with the edit; if not supplied, a default is used\n" );
echo( "--comment <comment> : Edit summary to be associated with the edit; underscores are transformed into spaces; if not supplied, a default is used\n" );
- echo( " <filename> : Path to the file containing the wikitext to import\n" );
- echo( " --norc : Do not add a page creation event to recent changes\n" );
-
+ echo( " --nooverwrite : Don't overwrite existing page content\n" );
+ echo( " <filename> : Path to the file containing the wikitext to import\n\n" );
}
-echo( "\n" );
?> \ No newline at end of file
diff --git a/maintenance/initEditCount.php b/maintenance/initEditCount.php
new file mode 100644
index 00000000..9d165cfb
--- /dev/null
+++ b/maintenance/initEditCount.php
@@ -0,0 +1,85 @@
+<?php
+
+require_once "commandLine.inc";
+
+if( isset( $options['help'] ) ) {
+ die( "Batch-recalculate user_editcount fields from the revision table.
+Options:
+ --quick Force the update to be done in a single query.
+ --background Force replication-friendly mode; may be inefficient but
+ avoids locking tables or lagging slaves with large updates;
+ calculates counts on a slave if possible.
+
+Background mode will be automatically used if the server is MySQL 4.0
+(which does not support subqueries) or if multiple servers are listed
+in \$wgDBservers, usually indicating a replication environment.
+
+");
+}
+$dbw = wfGetDB( DB_MASTER );
+$user = $dbw->tableName( 'user' );
+$revision = $dbw->tableName( 'revision' );
+
+$dbver = $dbw->getServerVersion();
+
+// Autodetect mode...
+$backgroundMode = count( $wgDBservers ) > 1 ||
+ ($dbw instanceof DatabaseMySql && version_compare( $dbver, '4.1' ) < 0);
+
+if( isset( $options['background'] ) ) {
+ $backgroundMode = true;
+} elseif( isset( $options['quick'] ) ) {
+ $backgroundMode = false;
+}
+
+if( $backgroundMode ) {
+ echo "Using replication-friendly background mode...\n";
+
+ $dbr = wfGetDB( DB_SLAVE );
+ $chunkSize = 100;
+ $lastUser = $dbr->selectField( 'user', 'MAX(user_id)', '', __FUNCTION__ );
+
+ $start = microtime( true );
+ $migrated = 0;
+ for( $min = 0; $min <= $lastUser; $min += $chunkSize ) {
+ $max = $min + $chunkSize;
+ $result = $dbr->query(
+ "SELECT
+ user_id,
+ COUNT(rev_user) AS user_editcount
+ FROM $user
+ LEFT OUTER JOIN $revision ON user_id=rev_user
+ WHERE user_id > $min AND user_id <= $max
+ GROUP BY user_id",
+ __FUNCTION__ );
+
+ while( $row = $dbr->fetchObject( $result ) ) {
+ $dbw->update( 'user',
+ array( 'user_editcount' => $row->user_editcount ),
+ array( 'user_id' => $row->user_id ),
+ __FUNCTION__ );
+ ++$migrated;
+ }
+ $dbr->freeResult( $result );
+
+ $delta = microtime( true ) - $start;
+ $rate = ($delta == 0.0) ? 0.0 : $migrated / $delta;
+ printf( "%s %d (%0.1f%%) done in %0.1f secs (%0.3f accounts/sec).\n",
+ $wgDBname,
+ $migrated,
+ min( $max, $lastUser ) / $lastUser * 100.0,
+ $delta,
+ $rate );
+
+ wfWaitForSlaves( 10 );
+ }
+} else {
+ // Subselect should work on modern MySQLs etc
+ echo "Using single-query mode...\n";
+ $sql = "UPDATE $user SET user_editcount=(SELECT COUNT(*) FROM $revision WHERE rev_user=user_id)";
+ $dbw->query( $sql );
+}
+
+echo "Done!\n";
+
+?>
diff --git a/maintenance/initStats.php b/maintenance/initStats.php
index b622c3f0..291de1ee 100644
--- a/maintenance/initStats.php
+++ b/maintenance/initStats.php
@@ -23,6 +23,7 @@ if( isset( $options['help'] ) ) {
echo( "Counting total edits..." );
$edits = $dbr->selectField( 'revision', 'COUNT(*)', '', $fname );
+$edits += $dbr->selectField( 'archive', 'COUNT(*)', '', $fname );
echo( "{$edits}\nCounting number of articles..." );
global $wgContentNamespaces;
diff --git a/maintenance/interwiki.sql b/maintenance/interwiki.sql
index ca656e46..b0df5557 100644
--- a/maintenance/interwiki.sql
+++ b/maintenance/interwiki.sql
@@ -147,7 +147,7 @@ REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES
('twistedwiki','http://purl.net/wiki/twisted/$1',0),
('uea','http://www.tejo.org/uea/$1',0),
('unreal','http://wiki.beyondunreal.com/wiki/$1',0),
-('ursine','http://ursine.ca/$1',0),
+('ursine','http://wiki.ursine.ca/$1',0),
('usej','http://www.tejo.org/usej/$1',0),
('usemod','http://www.usemod.com/cgi-bin/wiki.pl?$1',0),
('visualworks','http://wiki.cs.uiuc.edu/VisualWorks/$1',0),
@@ -157,10 +157,11 @@ REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES
('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/index.php/$1',0),
+('wikia','http://www.wikia.com/wiki/$1',0),
('wikibooks','http://en.wikibooks.org/wiki/$1',1),
('wikicities','http://www.wikicities.com/index.php/$1',0),
('wikif1','http://www.wikif1.org/$1',0),
+('wikihow','http://www.wikihow.com/$1',0),
('wikinfo','http://www.wikinfo.org/wiki.php?title=$1',0),
('wikimedia','http://wikimediafoundation.org/wiki/$1',0),
('wikiquote','http://en.wikiquote.org/wiki/$1',1),
diff --git a/maintenance/language/langmemusage.php b/maintenance/language/langmemusage.php
index 974bb0d8..54b6a58c 100644
--- a/maintenance/language/langmemusage.php
+++ b/maintenance/language/langmemusage.php
@@ -18,7 +18,7 @@ $memlast = $memstart = memory_get_usage();
print 'Base memory usage: '.$memstart."\n";
foreach ( $langtool->getLanguages() as $langcode ) {
- require_once( Language::getClassFileName( $langcode ) );
+ Language::factory( $langcode );
$memstep = memory_get_usage();
printf( "%12s: %d\n", $langcode, ($memstep- $memlast) );
$memlast = $memstep;
diff --git a/maintenance/language/languages.inc b/maintenance/language/languages.inc
index 86cd0869..946c6cb2 100644
--- a/maintenance/language/languages.inc
+++ b/maintenance/language/languages.inc
@@ -6,328 +6,15 @@
* @subpackage Maintenance
*/
+require_once( 'messageTypes.inc' );
+
class languages {
private $mLanguages; # List of languages
private $mRawMessages; # Raw list of the messages in each language
private $mMessages; # Messages in each language (except for English), divided to groups
private $mGeneralMessages; # General messages in English, divided to groups
- private $mIgnoredMessages = array(
- 'sidebar',
- 'addsection',
- 'anonnotice',
- 'catseparator',
- 'googlesearch',
- 'exif-make-value',
- 'exif-model-value',
- 'exif-software-value',
- 'history_copyright',
- 'licenses',
- 'loginend',
- 'loginlanguagelinks',
- 'markaspatrolledlink',
- 'newarticletextanon',
- 'noarticletextanon',
- 'number_of_watching_users_RCview',
- 'pubmedurl',
- 'randompage-url',
- 'recentchanges-url',
- 'rfcurl',
- 'shareddescriptionfollows',
- 'signupend',
- 'sitenotice',
- 'sitesubtitle',
- 'sitetitle',
- 'talkpagetext',
- 'trackback',
- 'trackbackexcerpt',
- 'widthheight',
- ); # All the messages which should be exist only in the English file
- private $mOptionalMessages = array(
- 'imgmultigotopost',
- 'linkprefix',
- 'allpages-summary',
- 'booksources-summary',
- 'ipblocklist-summary',
- 'listusers-summary',
- 'longpages-summary',
- 'preferences-summary',
- 'specialpages-summary',
- 'whatlinkshere-summary',
- 'whatlinkshere-barrow',
- 'imagelist-summary',
- 'mimesearch-summary',
- 'listredirects-summary',
- 'uncategorizedpages-summary',
- 'uncategorizedcategories-summary',
- 'uncategorizedimages-summary',
- 'popularpages-summary',
- 'wantedcategories-summary',
- 'wantedpages-summary',
- 'mostlinked-summary',
- 'mostlinkedcategories-summary',
- 'mostcategories-summary',
- 'mostimages-summary',
- 'mostrevisions-summary',
- 'prefixindex-summary',
- 'shortpages-summary',
- 'newpages-summary',
- 'ancientpages-summary',
- 'newimages-summary',
- 'unwatchedpages-summary',
- 'userrights-summary',
- 'variantname-zh-cn',
- 'variantname-zh-tw',
- 'variantname-zh-hk',
- 'variantname-zh-sg',
- 'variantname-zh',
- 'variantname-sr-ec',
- 'variantname-sr-el',
- 'variantname-sr-jc',
- 'variantname-sr-jl',
- 'variantname-sr',
- 'variantname-kk-tr',
- 'variantname-kk-kz',
- 'variantname-kk-cn',
- 'variantname-kk',
- ); # All the messages which may be translated or not, depending on the language
- private $mEXIFMessages = 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-resolutionunit',
- 'exif-stripoffsets',
- 'exif-rowsperstrip',
- 'exif-stripbytecounts',
- 'exif-jpeginterchangeformat',
- 'exif-jpeginterchangeformatlength',
- 'exif-transferfunction',
- '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-makernote',
- '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-oecf',
- '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-spatialfrequencyresponse',
- 'exif-focalplanexresolution',
- 'exif-focalplaneyresolution',
- 'exif-focalplaneresolutionunit',
- 'exif-subjectlocation',
- 'exif-exposureindex',
- 'exif-sensingmethod',
- 'exif-filesource',
- 'exif-scenetype',
- 'exif-cfapattern',
- '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-compression-1',
- 'exif-compression-6',
- 'exif-photometricinterpretation-2',
- 'exif-photometricinterpretation-6',
- '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-ffff.h',
- '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-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-gpsstatus-a',
- 'exif-gpsstatus-v',
- 'exif-gpsmeasuremode-2',
- 'exif-gpsmeasuremode-3',
- 'exif-gpsspeed-k',
- 'exif-gpsspeed-m',
- 'exif-gpsspeed-n',
- 'exif-gpsdirection-t',
- 'exif-gpsdirection-m',
- ); # All the EXIF messages, may be set as optional if defined as such
+ private $mIgnoredMessages; # All the messages which should be exist only in the English file
+ private $mOptionalMessages; # All the messages which may be translated or not, depending on the language
/**
* Load the list of languages: all the Messages*.php
@@ -336,11 +23,16 @@ class languages {
* @param $exif Treat the EXIF messages?
*/
function __construct( $exif = true ) {
+ global $wgIgnoredMessages, $wgOptionalMessages, $wgEXIFMessages;
+ $this->mIgnoredMessages = $wgIgnoredMessages;
+ if ( $exif ) {
+ $this->mOptionalMessages = array_merge( $wgOptionalMessages );
+ } else {
+ $this->mOptionalMessages = array_merge( $wgOptionalMessages, $wgEXIFMessages );
+ }
+
$this->mLanguages = array_keys( Language::getLanguageNames( true ) );
sort( $this->mLanguages );
- if ( !$exif ) {
- $this->mOptionalMessages = array_merge( $this->mOptionalMessages, $this->mEXIFMessages );
- }
}
/**
@@ -353,6 +45,24 @@ class languages {
}
/**
+ * Get the ignored messages list.
+ *
+ * @return The ignored messages list.
+ */
+ public function getIgnoredMessages() {
+ return $this->mIgnoredMessages;
+ }
+
+ /**
+ * Get the optional messages list.
+ *
+ * @return The optional messages list.
+ */
+ public function getOptionalMessages() {
+ return $this->mOptionalMessages;
+ }
+
+ /**
* Load the raw messages for a specific langauge from the messages file.
*
* @param $code The langauge code.
diff --git a/maintenance/language/messageTypes.inc b/maintenance/language/messageTypes.inc
new file mode 100644
index 00000000..f7f1ffeb
--- /dev/null
+++ b/maintenance/language/messageTypes.inc
@@ -0,0 +1,346 @@
+<?php
+/**
+ * Several types of messages.
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** Ignored messages, which should be exist only in the English messages file. */
+$wgIgnoredMessages = array(
+ 'sidebar',
+ 'addsection',
+ 'anonnotice',
+ 'autoblock_whitelist',
+ 'catseparator',
+ 'googlesearch',
+ 'exif-make-value',
+ 'exif-model-value',
+ 'exif-software-value',
+ 'history_copyright',
+ 'licenses',
+ 'loginend',
+ 'loginlanguagelinks',
+ 'markaspatrolledlink',
+ 'newarticletextanon',
+ 'newtalkseperator',
+ 'noarticletextanon',
+ 'number_of_watching_users_RCview',
+ 'pagecategorieslink',
+ 'pubmedurl',
+ 'randompage-url',
+ 'rc-change-size',
+ 'recentchanges-url',
+ 'revision-nav',
+ 'rfcurl',
+ 'shareddescriptionfollows',
+ 'signupend',
+ 'sitenotice',
+ 'sitesubtitle',
+ 'sitetitle',
+ 'talkpagetext',
+ 'trackback',
+ 'trackbackexcerpt',
+ 'widthheight',
+);
+
+/** Optional messages, which may be translated only if changed in the other language. */
+$wgOptionalMessages = array(
+ 'imgmultigotopost',
+ 'linkprefix',
+ 'feed-atom',
+ 'feed-rss',
+ 'allpages-summary',
+ 'booksources-summary',
+ 'ipblocklist-summary',
+ 'listusers-summary',
+ 'longpages-summary',
+ 'preferences-summary',
+ 'specialpages-summary',
+ 'whatlinkshere-summary',
+ 'whatlinkshere-barrow',
+ 'imagelist-summary',
+ 'mimesearch-summary',
+ 'listredirects-summary',
+ 'uncategorizedpages-summary',
+ 'uncategorizedcategories-summary',
+ 'uncategorizedimages-summary',
+ 'popularpages-summary',
+ 'wantedcategories-summary',
+ 'wantedpages-summary',
+ 'mostlinked-summary',
+ 'mostlinkedcategories-summary',
+ 'mostcategories-summary',
+ 'mostimages-summary',
+ 'mostrevisions-summary',
+ 'prefixindex-summary',
+ 'shortpages-summary',
+ 'newpages-summary',
+ 'ancientpages-summary',
+ 'newimages-summary',
+ 'unwatchedpages-summary',
+ 'userrights-summary',
+ 'brokenredirects-summary',
+ 'deadendpages-summary',
+ 'disambiguations-summary',
+ 'doubleredirects-summary',
+ 'lonelypages-summary',
+ 'unusedtemplates-summary',
+ 'variantname-zh-cn',
+ 'variantname-zh-tw',
+ 'variantname-zh-hk',
+ 'variantname-zh-sg',
+ 'variantname-zh',
+ 'variantname-sr-ec',
+ 'variantname-sr-el',
+ 'variantname-sr-jc',
+ 'variantname-sr-jl',
+ 'variantname-sr',
+ 'variantname-kk-tr',
+ 'variantname-kk-kz',
+ 'variantname-kk-cn',
+ 'variantname-kk',
+);
+
+/** 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-resolutionunit',
+ 'exif-stripoffsets',
+ 'exif-rowsperstrip',
+ 'exif-stripbytecounts',
+ 'exif-jpeginterchangeformat',
+ 'exif-jpeginterchangeformatlength',
+ 'exif-transferfunction',
+ '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-makernote',
+ '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-oecf',
+ '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-spatialfrequencyresponse',
+ 'exif-focalplanexresolution',
+ 'exif-focalplaneyresolution',
+ 'exif-focalplaneresolutionunit',
+ 'exif-subjectlocation',
+ 'exif-exposureindex',
+ 'exif-sensingmethod',
+ 'exif-filesource',
+ 'exif-scenetype',
+ 'exif-cfapattern',
+ '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-compression-1',
+ 'exif-compression-6',
+ 'exif-unknowndate',
+ 'exif-photometricinterpretation-2',
+ 'exif-photometricinterpretation-6',
+ '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-ffff.h',
+ '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-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-gpsstatus-a',
+ 'exif-gpsstatus-v',
+ 'exif-gpsmeasuremode-2',
+ 'exif-gpsmeasuremode-3',
+ 'exif-gpsspeed-k',
+ 'exif-gpsspeed-m',
+ 'exif-gpsspeed-n',
+ 'exif-gpsdirection-t',
+ 'exif-gpsdirection-m',
+);
+
+?>
diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc
new file mode 100644
index 00000000..4fbe2ed1
--- /dev/null
+++ b/maintenance/language/messages.inc
@@ -0,0 +1,2081 @@
+<?php
+/**
+ * Define the messages structure in the messages file, for a future automated rewriting.
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** The structure of the messages, divided to blocks */
+$wgMessageStrucutre = array(
+ 'sidebar' => array(
+ 'sidebar',
+ ),
+ 'toggles' => array(
+ 'tog-underline',
+ 'tog-highlightbroken',
+ 'tog-justify',
+ 'tog-hideminor',
+ 'tog-extendwatchlist',
+ 'tog-usenewrc',
+ 'tog-numberheadings',
+ 'tog-showtoolbar',
+ 'tog-editondblclick',
+ 'tog-editsection',
+ 'tog-editsectiononrightclick',
+ 'tog-showtoc',
+ 'tog-rememberpassword',
+ 'tog-editwidth',
+ '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-fancysig',
+ 'tog-externaleditor',
+ 'tog-externaldiff',
+ 'tog-showjumplinks',
+ 'tog-uselivepreview',
+ 'tog-forceeditsummary',
+ 'tog-watchlisthideown',
+ 'tog-watchlisthidebots',
+ 'tog-watchlisthideminor',
+ 'tog-nolangconversion',
+ 'tog-ccmeonemails',
+ ),
+ 'underline' => array(
+ 'underline-always',
+ 'underline-never',
+ 'underline-default',
+ ),
+ 'skinpreview' => array(
+ 'skinpreview',
+ ),
+ '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',
+ ),
+ 'categories' => array(
+ 'categories',
+ 'pagecategories',
+ 'pagecategorieslink',
+ 'category_header',
+ 'subcategories',
+ 'category-media-header',
+ ),
+ 'mainpage' => array(
+ 'linkprefix',
+ 'mainpage',
+ 'mainpagetext',
+ 'mainpagedocfooter',
+ ),
+ 'miscellaneous1' => array(
+ 'portal',
+ 'portal-url',
+ 'about',
+ 'aboutsite',
+ 'aboutpage',
+ 'article',
+ 'help',
+ 'helppage',
+ 'bugreports',
+ 'bugreportspage',
+ 'sitesupport',
+ 'sitesupport-url',
+ 'faq',
+ 'faqpage',
+ 'edithelp',
+ 'newwindow',
+ 'edithelppage',
+ 'cancel',
+ 'qbfind',
+ 'qbbrowse',
+ 'qbedit',
+ 'qbpageoptions',
+ 'qbpageinfo',
+ 'qbmyoptions',
+ 'qbspecialpages',
+ 'moredotdotdot',
+ 'mypage',
+ 'mytalk',
+ 'anontalk',
+ 'navigation',
+ ),
+ 'metadata_help' => array(
+ 'metadata_help',
+ ),
+ 'currentevents' => array(
+ 'currentevents',
+ 'currentevents-url',
+ ),
+ 'miscellaneous2' => array(
+ 'disclaimers',
+ 'disclaimerpage',
+ 'privacy',
+ 'privacypage',
+ 'errorpagetitle',
+ 'returnto',
+ 'tagline',
+ 'help',
+ 'search',
+ 'searchbutton',
+ 'go',
+ 'searcharticle',
+ 'history',
+ 'history_short',
+ 'updatedmarker',
+ 'info_short',
+ 'printableversion',
+ 'permalink',
+ 'print',
+ 'edit',
+ 'editthispage',
+ 'delete',
+ 'deletethispage',
+ 'undelete_short',
+ 'protect',
+ 'protectthispage',
+ 'unprotect',
+ 'unprotectthispage',
+ 'newpage',
+ 'talkpage',
+ 'specialpage',
+ 'personaltools',
+ 'postcomment',
+ 'addsection',
+ 'articlepage',
+ 'talk',
+ 'views',
+ 'toolbox',
+ 'userpage',
+ 'projectpage',
+ 'imagepage',
+ 'mediawikipage',
+ 'templatepage',
+ 'viewhelppage',
+ 'categorypage',
+ 'viewtalkpage',
+ 'otherlanguages',
+ 'redirectedfrom',
+ 'redirectpagesub',
+ 'lastmodifiedat',
+ 'viewcount',
+ 'copyright',
+ 'protectedpage',
+ 'jumpto',
+ 'jumptonavigation',
+ 'jumptosearch',
+ ),
+ 'badaccess' => array(
+ 'badaccess',
+ 'badaccess-group0',
+ 'badaccess-group1',
+ 'badaccess-group2',
+ 'badaccess-groups',
+ ),
+ 'versionrequired' => array(
+ 'versionrequired',
+ 'versionrequiredtext',
+ ),
+ 'miscellaneous3' => array(
+ 'widthheight',
+ 'ok',
+ 'sitetitle',
+ 'pagetitle',
+ 'sitesubtitle',
+ 'retrievedfrom',
+ 'youhavenewmessages',
+ 'newmessageslink',
+ 'newmessagesdifflink',
+ 'editsection',
+ 'editold',
+ 'editsectionhint',
+ 'toc',
+ 'showtoc',
+ 'hidetoc',
+ 'thisisdeleted',
+ 'viewdeleted',
+ 'restorelink',
+ 'feedlinks',
+ 'feed-invalid',
+ 'feed-atom',
+ 'feed-rss',
+ 'sitenotice',
+ 'anonnotice',
+ ),
+ 'nstab' => array(
+ 'nstab-main',
+ 'nstab-user',
+ 'nstab-media',
+ 'nstab-special',
+ 'nstab-project',
+ 'nstab-image',
+ 'nstab-mediawiki',
+ 'nstab-template',
+ 'nstab-help',
+ 'nstab-category',
+ ),
+ 'main' => array(
+ 'nosuchaction',
+ 'nosuchactiontext',
+ 'nosuchspecialpage',
+ 'nospecialpagetext',
+ ),
+ 'errors' => array(
+ 'error',
+ 'databaseerror',
+ 'dberrortext',
+ 'dberrortextcl',
+ 'noconnect',
+ 'nodb',
+ 'cachederror',
+ 'laggedslavemode',
+ 'readonly',
+ 'enterlockreason',
+ 'readonlytext',
+ 'missingarticle',
+ 'readonly_lag',
+ 'internalerror',
+ 'filecopyerror',
+ 'filerenameerror',
+ 'filedeleteerror',
+ 'filenotfound',
+ 'unexpected',
+ 'formerror',
+ 'badarticleerror',
+ 'cannotdelete',
+ 'badtitle',
+ 'badtitletext',
+ 'perfdisabled',
+ 'perfdisabledsub',
+ 'perfcached',
+ 'perfcachedts',
+ 'querypage-no-updates',
+ 'wrong_wfQuery_params',
+ 'viewsource',
+ 'viewsourcefor',
+ 'protectedpagetext',
+ 'viewsourcetext',
+ 'protectedinterface',
+ 'editinginterface',
+ 'sqlhidden',
+ ),
+ 'login' => array(
+ 'logouttitle',
+ 'logouttext',
+ 'welcomecreation',
+ 'loginpagetitle',
+ 'yourname',
+ 'yourpassword',
+ 'yourpasswordagain',
+ 'remembermypassword',
+ 'yourdomainname',
+ 'externaldberror',
+ 'loginproblem',
+ 'alreadyloggedin',
+ 'login',
+ 'loginprompt',
+ 'userlogin',
+ 'logout',
+ 'userlogout',
+ 'notloggedin',
+ 'nologin',
+ 'nologinlink',
+ 'createaccount',
+ 'gotaccount',
+ 'gotaccountlink',
+ 'createaccountmail',
+ 'badretype',
+ 'userexists',
+ 'youremail',
+ 'username',
+ 'uid',
+ 'yourrealname',
+ 'yourlanguage',
+ 'yourvariant',
+ 'yournick',
+ 'badsig',
+ 'email',
+ 'prefs-help-email-enotif',
+ 'prefs-help-realname',
+ 'loginerror',
+ 'prefs-help-email',
+ 'nocookiesnew',
+ 'nocookieslogin',
+ 'noname',
+ 'loginsuccesstitle',
+ 'loginsuccess',
+ 'nosuchuser',
+ 'nosuchusershort',
+ 'nouserspecified',
+ 'wrongpassword',
+ 'wrongpasswordempty',
+ 'mailmypassword',
+ 'passwordremindertitle',
+ 'passwordremindertext',
+ 'noemail',
+ 'passwordsent',
+ 'blocked-mailpassword',
+ 'eauthentsent',
+ 'throttled-mailpassword',
+ 'loginend',
+ 'signupend',
+ 'mailerror',
+ 'acct_creation_throttle_hit',
+ 'emailauthenticated',
+ 'emailnotauthenticated',
+ 'noemailprefs',
+ 'emailconfirmlink',
+ 'invalidemailaddress',
+ 'accountcreated',
+ 'accountcreatedtext',
+ ),
+ 'resetpass' => array(
+ 'resetpass',
+ 'resetpass_announce',
+ 'resetpass_text',
+ 'resetpass_header',
+ 'resetpass_submit',
+ 'resetpass_success',
+ 'resetpass_bad_temporary',
+ 'resetpass_forbidden',
+ 'resetpass_missing',
+ ),
+ 'toolbar' => array(
+ 'bold_sample',
+ 'bold_tip',
+ 'italic_sample',
+ 'italic_tip',
+ 'link_sample',
+ 'link_tip',
+ 'extlink_sample',
+ 'extlink_tip',
+ 'headline_sample',
+ 'headline_tip',
+ 'math_sample',
+ 'math_tip',
+ 'nowiki_sample',
+ 'nowiki_tip',
+ 'image_sample',
+ 'image_tip',
+ 'media_sample',
+ 'media_tip',
+ 'sig_tip',
+ 'hr_tip',
+ ),
+ 'edit' => array(
+ 'summary',
+ 'subject',
+ 'minoredit',
+ 'watchthis',
+ 'savearticle',
+ 'preview',
+ 'showpreview',
+ 'showlivepreview',
+ 'showdiff',
+ 'anoneditwarning',
+ 'missingsummary',
+ 'missingcommenttext',
+ 'missingcommentheader',
+ 'summary-preview',
+ 'subject-preview',
+ 'blockedtitle',
+ 'blockedtext',
+ 'blockedoriginalsource',
+ 'blockededitsource',
+ 'whitelistedittitle',
+ 'whitelistedittext',
+ 'whitelistreadtitle',
+ 'whitelistreadtext',
+ 'whitelistacctitle',
+ 'whitelistacctext',
+ 'confirmedittitle',
+ 'confirmedittext',
+ 'loginreqtitle',
+ 'loginreqlink',
+ 'loginreqpagetext',
+ 'accmailtitle',
+ 'accmailtext',
+ 'newarticle',
+ 'newarticletext',
+ 'newarticletextanon',
+ 'talkpagetext',
+ 'anontalkpagetext',
+ 'noarticletext',
+ 'noarticletextanon',
+ 'clearyourcache',
+ 'usercssjsyoucanpreview',
+ 'usercsspreview',
+ 'userjspreview',
+ 'userinvalidcssjstitle',
+ 'updated',
+ 'note',
+ 'previewnote',
+ 'previewconflict',
+ 'session_fail_preview',
+ 'session_fail_preview_html',
+ 'importing',
+ 'editing',
+ 'editinguser',
+ 'editingsection',
+ 'editingcomment',
+ 'editconflict',
+ 'explainconflict',
+ 'yourtext',
+ 'storedversion',
+ 'nonunicodebrowser',
+ 'editingold',
+ 'yourdiff',
+ 'copyrightwarning',
+ 'copyrightwarning2',
+ 'longpagewarning',
+ 'longpageerror',
+ 'readonlywarning',
+ 'protectedpagewarning',
+ 'semiprotectedpagewarning',
+ 'templatesused',
+ 'templatesusedpreview',
+ 'templatesusedsection',
+ 'template-protected',
+ 'template-semiprotected',
+ 'edittools',
+ 'nocreatetitle',
+ 'nocreatetext',
+ ),
+ 'undo' => array(
+ 'undo-success',
+ 'undo-failure',
+ 'undo-summary',
+ ),
+ 'cantcreateaccount' => array(
+ 'cantcreateaccounttitle',
+ 'cantcreateaccounttext',
+ ),
+ 'history' => array(
+ 'revhistory',
+ 'viewpagelogs',
+ 'nohistory',
+ 'revnotfound',
+ 'revnotfoundtext',
+ 'loadhist',
+ 'currentrev',
+ 'revisionasof',
+ 'revision-info',
+ 'revision-nav',
+ 'previousrevision',
+ 'nextrevision',
+ 'currentrevisionlink',
+ 'cur',
+ 'next',
+ 'last',
+ 'orig',
+ 'histlegend',
+ 'history_copyright',
+ 'deletedrev',
+ 'histfirst',
+ 'histlast',
+ 'rev-deleted-comment',
+ 'rev-deleted-user',
+ 'rev-deleted-text-permission',
+ 'rev-deleted-text-view',
+ 'rev-delundel',
+ ),
+ 'history-feed' => array(
+ 'history-feed-title',
+ 'history-feed-description',
+ 'history-feed-item-nocomment',
+ 'history-feed-empty',
+ ),
+ 'revdelete' => array(
+ 'revisiondelete',
+ 'revdelete-nooldid-title',
+ 'revdelete-nooldid-text',
+ 'revdelete-selected',
+ 'revdelete-text',
+ 'revdelete-legend',
+ 'revdelete-hide-text',
+ 'revdelete-hide-comment',
+ 'revdelete-hide-user',
+ 'revdelete-hide-restricted',
+ 'revdelete-log',
+ 'revdelete-submit',
+ 'revdelete-logentry',
+ ),
+ 'diffs' => array(
+ 'difference',
+ 'loadingrev',
+ 'lineno',
+ 'editcurrent',
+ 'selectnewerversionfordiff',
+ 'selectolderversionfordiff',
+ 'compareselectedversions',
+ 'editundo',
+ 'diff-multi',
+ ),
+ 'search' => array(
+ 'searchresults',
+ 'searchresulttext',
+ 'searchsubtitle',
+ 'searchsubtitleinvalid',
+ 'badquery',
+ 'badquerytext',
+ 'matchtotals',
+ 'noexactmatch',
+ 'titlematches',
+ 'notitlematches',
+ 'textmatches',
+ 'notextmatches',
+ 'prevn',
+ 'nextn',
+ 'viewprevnext',
+ 'showingresults',
+ 'showingresultsnum',
+ 'nonefound',
+ 'powersearch',
+ 'powersearchtext',
+ 'searchdisabled',
+ 'googlesearch',
+ 'blanknamespace',
+ ),
+ 'preferences' => array(
+ 'preferences',
+ 'preferences-summary',
+ 'mypreferences',
+ 'prefsnologin',
+ 'prefsnologintext',
+ 'prefsreset',
+ 'qbsettings',
+ 'changepassword',
+ 'skin',
+ 'math',
+ 'dateformat',
+ 'datedefault',
+ 'datetime',
+ 'math_failure',
+ 'math_unknown_error',
+ 'math_unknown_function',
+ 'math_lexing_error',
+ 'math_syntax_error',
+ 'math_image_error',
+ 'math_bad_tmpdir',
+ 'math_bad_output',
+ 'math_notexvc',
+ 'prefs-personal',
+ 'prefs-rc',
+ 'prefs-watchlist',
+ 'prefs-watchlist-days',
+ 'prefs-watchlist-edits',
+ 'prefs-misc',
+ 'saveprefs',
+ 'resetprefs',
+ 'oldpassword',
+ 'newpassword',
+ 'retypenew',
+ 'textboxsize',
+ 'rows',
+ 'columns',
+ 'searchresultshead',
+ 'resultsperpage',
+ 'contextlines',
+ 'contextchars',
+ 'stubthreshold',
+ 'recentchangescount',
+ 'savedprefs',
+ 'timezonelegend',
+ 'timezonetext',
+ 'localtime',
+ 'timezoneoffset',
+ 'servertime',
+ 'guesstimezone',
+ 'allowemail',
+ 'defaultns',
+ 'default',
+ 'files',
+ ),
+ 'userrights' => array(
+ 'userrights-lookup-user',
+ 'userrights-user-editname',
+ 'editusergroup',
+ 'userrights-editusergroup',
+ 'saveusergroups',
+ 'userrights-groupsmember',
+ 'userrights-groupsavailable',
+ 'userrights-groupshelp',
+ ),
+ 'group' => array(
+ 'group',
+ 'group-bot',
+ 'group-sysop',
+ 'group-bureaucrat',
+ 'group-all',
+ ),
+ 'group-member' => array(
+ 'group-bot-member',
+ 'group-sysop-member',
+ 'group-bureaucrat-member',
+ ),
+ 'grouppage' => array(
+ 'grouppage-bot',
+ 'grouppage-sysop',
+ 'grouppage-bureaucrat',
+ ),
+ 'recentchanges' => array(
+ 'changes',
+ 'recentchanges',
+ 'recentchanges-url',
+ 'recentchangestext',
+ 'recentchanges-feed-description',
+ 'rcnote',
+ 'rcnotefrom',
+ 'rclistfrom',
+ 'rcshowhideminor',
+ 'rcshowhidebots',
+ 'rcshowhideliu',
+ 'rcshowhideanons',
+ 'rcshowhidepatr',
+ 'rcshowhidemine',
+ 'rclinks',
+ 'diff',
+ 'hist',
+ 'hide',
+ 'show',
+ 'minoreditletter',
+ 'newpageletter',
+ 'boteditletter',
+ 'sectionlink',
+ 'number_of_watching_users_RCview',
+ 'number_of_watching_users_pageview',
+ 'rc_categories',
+ 'rc_categories_any',
+ 'rc-change-size',
+ ),
+ 'upload' => array(
+ 'upload',
+ 'uploadbtn',
+ 'reupload',
+ 'reuploaddesc',
+ 'uploadnologin',
+ 'uploadnologintext',
+ 'upload_directory_read_only',
+ 'uploaderror',
+ 'uploadtext',
+ 'uploadlog',
+ 'uploadlogpage',
+ 'uploadlogpagetext',
+ 'filename',
+ 'filedesc',
+ 'fileuploadsummary',
+ 'filestatus',
+ 'filesource',
+ 'copyrightpage',
+ 'copyrightpagename',
+ 'uploadedfiles',
+ 'ignorewarning',
+ 'ignorewarnings',
+ 'minlength',
+ 'illegalfilename',
+ 'badfilename',
+ 'badfiletype',
+ 'large-file',
+ 'largefileserver',
+ 'emptyfile',
+ 'fileexists',
+ 'fileexists-forbidden',
+ 'fileexists-shared-forbidden',
+ 'successfulupload',
+ 'fileuploaded',
+ 'uploadwarning',
+ 'savefile',
+ 'uploadedimage',
+ 'uploaddisabled',
+ 'uploaddisabledtext',
+ 'uploadscripted',
+ 'uploadcorrupt',
+ 'uploadvirus',
+ 'sourcefilename',
+ 'destfilename',
+ 'watchthisupload',
+ 'filewasdeleted',
+ ),
+ 'upload-errors' => array(
+ 'upload-proto-error',
+ 'upload-proto-error-text',
+ 'upload-file-error',
+ 'upload-file-error-text',
+ 'upload-misc-error',
+ 'upload-misc-error-text',
+ ),
+ 'upload-curl-errors' => array(
+ 'upload-curl-error6',
+ 'upload-curl-error6-text',
+ 'upload-curl-error28',
+ 'upload-curl-error28-text',
+ ),
+ 'licenses' => array(
+ 'license',
+ 'nolicense',
+ 'licenses',
+ 'upload_source_url',
+ 'upload_source_file',
+ ),
+ 'imagelist' => array(
+ 'imagelist',
+ 'imagelist-summary',
+ 'imagelisttext',
+ 'imagelistforuser',
+ 'getimagelist',
+ 'ilsubmit',
+ 'showlast',
+ 'byname',
+ 'bydate',
+ 'bysize',
+ 'imgdelete',
+ 'imgdesc',
+ 'imgfile',
+ 'imglegend',
+ 'imghistory',
+ 'revertimg',
+ 'deleteimg',
+ 'deleteimgcompletely',
+ 'imghistlegend',
+ 'imagelinks',
+ 'linkstoimage',
+ 'nolinkstoimage',
+ 'sharedupload',
+ 'shareduploadwiki',
+ 'shareduploadwiki-linktext',
+ 'shareddescriptionfollows',
+ 'noimage',
+ 'noimage-linktext',
+ 'uploadnewversion-linktext',
+ 'imagelist_date',
+ 'imagelist_name',
+ 'imagelist_user',
+ 'imagelist_size',
+ 'imagelist_description',
+ 'imagelist_search_for',
+ ),
+ 'mimesearch' => array(
+ 'mimesearch',
+ 'mimesearch-summary',
+ 'mimetype',
+ 'download',
+ ),
+ 'unwatchedpages' => array(
+ 'unwatchedpages',
+ 'unwatchedpages-summary',
+ ),
+ 'listredirects' => array(
+ 'listredirects',
+ 'listredirects-summary',
+ ),
+ 'unusedtemplates' => array(
+ 'unusedtemplates',
+ 'unusedtemplates-summary',
+ 'unusedtemplatestext',
+ 'unusedtemplateswlh',
+ ),
+ 'randomredirect' => array(
+ 'randomredirect',
+ ),
+ 'statistics' => array(
+ 'statistics',
+ 'sitestats',
+ 'userstats',
+ 'sitestatstext',
+ 'userstatstext',
+ 'statistics-mostpopular',
+ ),
+ 'disambiguations' => array(
+ 'disambiguations',
+ 'disambiguations-summary',
+ 'disambiguationspage',
+ 'disambiguationstext',
+ ),
+ 'doubleredirects' => array(
+ 'doubleredirects',
+ 'doubleredirects-summary',
+ 'doubleredirectstext',
+ ),
+ 'brokenredirects' => array(
+ 'brokenredirects',
+ 'brokenredirects-summary',
+ 'brokenredirectstext',
+ ),
+ 'specialpages' => array(
+ 'nbytes',
+ 'ncategories',
+ 'nlinks',
+ 'nmembers',
+ 'nrevisions',
+ 'nviews',
+ 'lonelypages',
+ 'lonelypages-summary',
+ 'lonelypagestext',
+ 'uncategorizedpages',
+ 'uncategorizedpages-summary',
+ 'uncategorizedcategories',
+ 'uncategorizedcategories-summary',
+ 'uncategorizedimages',
+ 'uncategorizedimages-summary',
+ 'unusedcategories',
+ 'unusedimages',
+ 'popularpages',
+ 'popularpages-summary',
+ 'wantedcategories',
+ 'wantedcategories-summary',
+ 'wantedpages',
+ 'wantedpages-summary',
+ 'mostlinked',
+ 'mostlinked-summary',
+ 'mostlinkedcategories',
+ 'mostlinkedcategories-summary',
+ 'mostcategories',
+ 'mostcategories-summary',
+ 'mostimages',
+ 'mostimages-summary',
+ 'mostrevisions',
+ 'mostrevisions-summary',
+ 'allpages',
+ 'allpages-summary',
+ 'prefixindex',
+ 'prefixindex-summary',
+ 'randompage',
+ 'randompage-url',
+ 'shortpages',
+ 'shortpages-summary',
+ 'longpages',
+ 'longpages-summary',
+ 'deadendpages',
+ 'deadendpages-summary',
+ 'deadendpagestext',
+ 'listusers',
+ 'listusers-summary',
+ 'specialpages',
+ 'specialpages-summary',
+ 'spheading',
+ 'restrictedpheading',
+ 'recentchangeslinked',
+ 'rclsub',
+ 'newpages',
+ 'newpages-summary',
+ 'newpages-username',
+ 'ancientpages',
+ 'ancientpages-summary',
+ 'intl',
+ 'move',
+ 'movethispage',
+ 'unusedimagestext',
+ 'unusedcategoriestext',
+ ),
+ 'booksources' => array(
+ 'booksources',
+ 'booksources-summary',
+ 'booksources-search-legend',
+ 'booksources-isbn',
+ 'booksources-go',
+ 'booksources-text',
+ ),
+ 'specialpages2' => array(
+ 'categoriespagetext',
+ 'data',
+ 'userrights',
+ 'userrights-summary',
+ 'groups',
+ 'isbn',
+ 'rfcurl',
+ 'pubmedurl',
+ 'alphaindexline',
+ 'version',
+ 'log',
+ 'alllogstext',
+ 'logempty',
+ ),
+ 'allpages' => array(
+ 'nextpage',
+ 'prevpage',
+ 'allpagesfrom',
+ 'allarticles',
+ 'allinnamespace',
+ 'allnotinnamespace',
+ 'allpagesprev',
+ 'allpagesnext',
+ 'allpagessubmit',
+ 'allpagesprefix',
+ 'allpagesbadtitle',
+ ),
+ 'listusers' => array(
+ 'listusersfrom',
+ ),
+ 'emailuser' => array(
+ 'mailnologin',
+ 'mailnologintext',
+ 'emailuser',
+ 'emailpage',
+ 'emailpagetext',
+ 'usermailererror',
+ 'defemailsubject',
+ 'noemailtitle',
+ 'noemailtext',
+ 'emailfrom',
+ 'emailto',
+ 'emailsubject',
+ 'emailmessage',
+ 'emailsend',
+ 'emailccme',
+ 'emailccsubject',
+ 'emailsent',
+ 'emailsenttext',
+ ),
+ 'watchlist' => array(
+ 'watchlist',
+ 'watchlistfor',
+ 'nowatchlist',
+ 'watchlistanontext',
+ 'watchlistcount',
+ 'clearwatchlist',
+ 'watchlistcleartext',
+ 'watchlistclearbutton',
+ 'watchlistcleardone',
+ 'watchnologin',
+ 'watchnologintext',
+ 'addedwatch',
+ 'addedwatchtext',
+ 'removedwatch',
+ 'removedwatchtext',
+ 'watch',
+ 'watchthispage',
+ 'unwatch',
+ 'unwatchthispage',
+ 'notanarticle',
+ 'watchnochange',
+ 'watchdetails',
+ 'wlheader-enotif',
+ 'wlheader-showupdated',
+ 'watchmethod-recent',
+ 'watchmethod-list',
+ 'removechecked',
+ 'watchlistcontains',
+ 'watcheditlist',
+ 'removingchecked',
+ 'couldntremove',
+ 'iteminvalidname',
+ 'wlnote',
+ 'wlshowlast',
+ 'wlsaved',
+ 'watchlist-show-bots',
+ 'watchlist-hide-bots',
+ 'watchlist-show-own',
+ 'watchlist-hide-own',
+ 'watchlist-show-minor',
+ 'watchlist-hide-minor',
+ 'wldone',
+ ),
+ 'watching' => array(
+ 'watching',
+ 'unwatching',
+ ),
+ 'enotif' => array(
+ 'enotif_mailer',
+ 'enotif_reset',
+ 'enotif_newpagetext',
+ 'changed',
+ 'created',
+ 'enotif_subject',
+ 'enotif_lastvisited',
+ 'enotif_body',
+ ),
+ 'deleteprotectrev' => array(
+ 'deletepage',
+ 'confirm',
+ 'excontent',
+ 'excontentauthor',
+ 'exbeforeblank',
+ 'exblank',
+ 'confirmdelete',
+ 'deletesub',
+ 'historywarning',
+ 'confirmdeletetext',
+ 'actioncomplete',
+ 'deletedtext',
+ 'deletedarticle',
+ 'dellogpage',
+ 'dellogpagetext',
+ 'deletionlog',
+ 'reverted',
+ 'deletecomment',
+ 'imagereverted',
+ 'rollback',
+ 'rollback_short',
+ 'rollbacklink',
+ 'rollbackfailed',
+ 'cantrollback',
+ 'alreadyrolled',
+ 'editcomment',
+ 'revertpage',
+ 'sessionfailure',
+ 'protectlogpage',
+ 'protectlogtext',
+ 'protectedarticle',
+ 'unprotectedarticle',
+ 'protectsub',
+ 'confirmprotecttext',
+ 'confirmprotect',
+ 'protectmoveonly',
+ 'protectcomment',
+ 'unprotectsub',
+ 'confirmunprotecttext',
+ 'confirmunprotect',
+ 'unprotectcomment',
+ 'protect-unchain',
+ 'protect-text',
+ 'protect-viewtext',
+ 'protect-default',
+ 'protect-level-autoconfirmed',
+ 'protect-level-sysop',
+ ),
+ 'restrictions' => array(
+ 'restriction-edit',
+ 'restriction-move',
+ ),
+ 'undelete' => array(
+ 'undelete',
+ 'undeletepage',
+ 'viewdeletedpage',
+ 'undeletepagetext',
+ 'undeleteextrahelp',
+ 'undeletearticle',
+ 'undeleterevisions',
+ 'undeletehistory',
+ 'undeletehistorynoadmin',
+ 'undeleterevision',
+ 'undeleterevision-missing',
+ 'undeletebtn',
+ 'undeletereset',
+ 'undeletecomment',
+ 'undeletedarticle',
+ 'undeletedrevisions',
+ 'undeletedrevisions-files',
+ 'undeletedfiles',
+ 'cannotundelete',
+ 'undeletedpage',
+ ),
+ 'nsform' => array(
+ 'namespace',
+ 'invert',
+ ),
+ 'contributions' => array(
+ 'contributions',
+ 'mycontris',
+ 'contribsub',
+ 'nocontribs',
+ 'ucnote',
+ 'uclinks',
+ 'uctop',
+ 'newbies',
+ ),
+ 'sp-contributions' => array(
+ 'sp-contributions-newest',
+ 'sp-contributions-oldest',
+ 'sp-contributions-newer',
+ 'sp-contributions-older',
+ 'sp-contributions-newbies-sub',
+ 'sp-contributions-blocklog',
+ ),
+ 'newimages-showfrom' => array(
+ 'sp-newimages-showfrom',
+ ),
+ 'whatlinkshere' => array(
+ 'whatlinkshere',
+ 'whatlinkshere-summary',
+ 'whatlinkshere-barrow',
+ 'notargettitle',
+ 'notargettext',
+ 'linklistsub',
+ 'linkshere',
+ 'nolinkshere',
+ 'isredirect',
+ 'istemplate',
+ ),
+ 'block' => array(
+ 'blockip',
+ 'blockiptext',
+ 'ipaddress',
+ 'ipadressorusername',
+ 'ipbexpiry',
+ 'ipbreason',
+ 'ipbanononly',
+ 'ipbcreateaccount',
+ 'ipbenableautoblock',
+ 'ipbsubmit',
+ 'ipbother',
+ 'ipboptions',
+ 'ipbotheroption',
+ 'badipaddress',
+ 'blockipsuccesssub',
+ 'blockipsuccesstext',
+ 'unblockip',
+ 'unblockiptext',
+ 'ipusubmit',
+ 'unblocked',
+ 'ipblocklist',
+ 'ipblocklist-summary',
+ 'blocklistline',
+ 'infiniteblock',
+ 'expiringblock',
+ 'anononlyblock',
+ 'noautoblockblock',
+ 'createaccountblock',
+ 'ipblocklistempty',
+ 'blocklink',
+ 'unblocklink',
+ 'contribslink',
+ 'autoblocker',
+ 'blocklogpage',
+ 'blocklogentry',
+ 'blocklogtext',
+ 'unblocklogentry',
+ 'range_block_disabled',
+ 'ipb_expiry_invalid',
+ 'ipb_already_blocked',
+ 'ip_range_invalid',
+ 'proxyblocker',
+ 'ipb_cant_unblock',
+ 'proxyblockreason',
+ 'proxyblocksuccess',
+ 'sorbs',
+ 'sorbsreason',
+ 'sorbs_create_account_reason',
+ ),
+ 'developertools' => array(
+ 'lockdb',
+ 'unlockdb',
+ 'lockdbtext',
+ 'unlockdbtext',
+ 'lockconfirm',
+ 'unlockconfirm',
+ 'lockbtn',
+ 'unlockbtn',
+ 'locknoconfirm',
+ 'lockdbsuccesssub',
+ 'unlockdbsuccesssub',
+ 'lockdbsuccesstext',
+ 'unlockdbsuccesstext',
+ 'lockfilenotwritable',
+ 'databasenotlocked',
+ ),
+ 'makesysop' => array(
+ 'makesysoptitle',
+ 'makesysoptext',
+ 'makesysopname',
+ 'makesysopsubmit',
+ 'makesysopok',
+ 'makesysopfail',
+ 'setbureaucratflag',
+ 'rightslog',
+ 'rightslogtext',
+ 'rightslogentry',
+ 'rights',
+ 'set_user_rights',
+ 'user_rights_set',
+ 'set_rights_fail',
+ 'makesysop',
+ 'already_sysop',
+ 'already_bureaucrat',
+ 'rightsnone',
+ ),
+ 'movepage' => array(
+ 'movepage',
+ 'movepagetext',
+ 'movepagetalktext',
+ 'movearticle',
+ 'movenologin',
+ 'movenologintext',
+ 'newtitle',
+ 'move-watch',
+ 'movepagebtn',
+ 'pagemovedsub',
+ 'pagemovedtext',
+ 'articleexists',
+ 'talkexists',
+ 'movedto',
+ 'movetalk',
+ 'talkpagemoved',
+ 'talkpagenotmoved',
+ '1movedto2',
+ '1movedto2_redir',
+ 'movelogpage',
+ 'movelogpagetext',
+ 'movereason',
+ 'revertmove',
+ 'delete_and_move',
+ 'delete_and_move_text',
+ 'delete_and_move_confirm',
+ 'delete_and_move_reason',
+ 'selfmove',
+ 'immobile_namespace',
+ ),
+ 'export' => array(
+ 'export',
+ 'exporttext',
+ 'exportcuronly',
+ 'exportnohistory',
+ 'export-submit',
+ ),
+ 'allmessages' => array(
+ 'allmessages',
+ 'allmessagesname',
+ 'allmessagesdefault',
+ 'allmessagescurrent',
+ 'allmessagestext',
+ 'allmessagesnotsupportedUI',
+ 'allmessagesnotsupportedDB',
+ 'allmessagesfilter',
+ 'allmessagesmodified',
+ ),
+ 'thumbnails' => array(
+ 'thumbnail-more',
+ 'missingimage',
+ 'filemissing',
+ 'thumbnail_error',
+ ),
+ 'import' => array(
+ 'import',
+ 'importinterwiki',
+ 'import-interwiki-text',
+ 'import-interwiki-history',
+ 'import-interwiki-submit',
+ 'import-interwiki-namespace',
+ 'importtext',
+ 'importstart',
+ 'import-revision-count',
+ 'importnopages',
+ 'importfailed',
+ 'importunknownsource',
+ 'importcantopen',
+ 'importbadinterwiki',
+ 'importnotext',
+ 'importsuccess',
+ 'importhistoryconflict',
+ 'importnosources',
+ 'importnofile',
+ 'importuploaderror',
+ ),
+ 'importlog' => array(
+ 'importlogpage',
+ 'importlogpagetext',
+ 'import-logentry-upload',
+ 'import-logentry-upload-detail',
+ 'import-logentry-interwiki',
+ 'import-logentry-interwiki-detail',
+ ),
+ 'accesskeys' => array(
+ 'accesskey-search',
+ 'accesskey-minoredit',
+ 'accesskey-save',
+ 'accesskey-preview',
+ 'accesskey-diff',
+ 'accesskey-compareselectedversions',
+ 'accesskey-watch',
+ ),
+ 'tooltips' => array(
+ 'tooltip-search',
+ 'tooltip-minoredit',
+ 'tooltip-save',
+ 'tooltip-preview',
+ 'tooltip-diff',
+ 'tooltip-compareselectedversions',
+ 'tooltip-watch',
+ ),
+ 'stylesheets' => array(
+ 'common.css',
+ 'monobook.css',
+ ),
+ 'metadata_cc' => array(
+ 'nodublincore',
+ 'nocreativecommons',
+ 'notacceptable',
+ ),
+ 'attribution' => array(
+ 'anonymous',
+ 'siteuser',
+ 'lastmodifiedatby',
+ 'and',
+ 'othercontribs',
+ 'others',
+ 'siteusers',
+ 'creditspage',
+ 'nocredits',
+ ),
+ 'spamprotection' => array(
+ 'spamprotectiontitle',
+ 'spamprotectiontext',
+ 'spamprotectionmatch',
+ 'subcategorycount',
+ 'categoryarticlecount',
+ 'category-media-count',
+ 'listingcontinuesabbrev',
+ 'spambot_username',
+ 'spam_reverting',
+ 'spam_blanking',
+ ),
+ 'info' => array(
+ 'infosubtitle',
+ 'numedits',
+ 'numtalkedits',
+ 'numwatchers',
+ 'numauthors',
+ 'numtalkauthors',
+ ),
+ 'math' => array(
+ 'mw_math_png',
+ 'mw_math_simple',
+ 'mw_math_html',
+ 'mw_math_source',
+ 'mw_math_modern',
+ 'mw_math_mathml',
+ ),
+ 'patrolling' => array(
+ 'markaspatrolleddiff',
+ 'markaspatrolledlink',
+ 'markaspatrolledtext',
+ 'markedaspatrolled',
+ 'markedaspatrolledtext',
+ 'rcpatroldisabled',
+ 'rcpatroldisabledtext',
+ 'markedaspatrollederror',
+ 'markedaspatrollederrortext',
+ 'markedaspatrollederror-noautopatrol',
+ ),
+ 'monobook.js' => array(
+ 'monobook.js',
+ ),
+ 'common.js' => array(
+ 'common.js',
+ ),
+ 'imagedeletion' => array(
+ 'deletedrevision',
+ ),
+ 'browsediffs' => array(
+ 'previousdiff',
+ 'nextdiff',
+ ),
+ 'imagesize' => array(
+ 'imagemaxsize',
+ 'thumbsize',
+ 'showbigimage',
+ ),
+ 'newimages' => array(
+ 'newimages',
+ 'newimages-summary',
+ 'showhidebots',
+ 'noimages',
+ ),
+ 'variantname-zh' => array(
+ 'variantname-zh-cn',
+ 'variantname-zh-tw',
+ 'variantname-zh-hk',
+ 'variantname-zh-sg',
+ 'variantname-zh',
+ ),
+ 'variantname-sr' => array(
+ 'variantname-sr-ec',
+ 'variantname-sr-el',
+ 'variantname-sr-jc',
+ 'variantname-sr-jl',
+ 'variantname-sr',
+ ),
+ 'variantname-kk' => array(
+ 'variantname-kk-tr',
+ 'variantname-kk-kz',
+ 'variantname-kk-cn',
+ 'variantname-kk',
+ ),
+ 'specialloglabels' => array(
+ 'specialloguserlabel',
+ 'speciallogtitlelabel',
+ ),
+ 'passwordtooshort' => array(
+ 'passwordtooshort',
+ ),
+ 'mediawarning' => array(
+ 'mediawarning',
+ ),
+ 'fileinfo' => array(
+ 'fileinfo',
+ ),
+ 'metadata' => array(
+ 'metadata',
+ 'metadata-help',
+ 'metadata-expand',
+ 'metadata-collapse',
+ 'metadata-fields',
+ ),
+ 'exif' => 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-resolutionunit',
+ 'exif-stripoffsets',
+ 'exif-rowsperstrip',
+ 'exif-stripbytecounts',
+ 'exif-jpeginterchangeformat',
+ 'exif-jpeginterchangeformatlength',
+ 'exif-transferfunction',
+ '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-makernote',
+ '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-oecf',
+ '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-spatialfrequencyresponse',
+ 'exif-focalplanexresolution',
+ 'exif-focalplaneyresolution',
+ 'exif-focalplaneresolutionunit',
+ 'exif-subjectlocation',
+ 'exif-exposureindex',
+ 'exif-sensingmethod',
+ 'exif-filesource',
+ 'exif-scenetype',
+ 'exif-cfapattern',
+ '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-values' => array(
+ 'exif-make-value',
+ 'exif-model-value',
+ 'exif-software-value',
+ ),
+ 'exif-compression' => array(
+ 'exif-compression-1',
+ 'exif-compression-6',
+ ),
+ 'exif-photometricinterpretation' => array(
+ 'exif-photometricinterpretation-2',
+ 'exif-photometricinterpretation-6',
+ ),
+ 'exif-unknowndate' => array(
+ 'exif-unknowndate',
+ ),
+ 'exif-orientation' => array(
+ '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' => array(
+ 'exif-planarconfiguration-1',
+ 'exif-planarconfiguration-2',
+ ),
+ 'exif-xyresolution' => array(
+ 'exif-xyresolution-i',
+ 'exif-xyresolution-c',
+ ),
+ 'exif-colorspace' => array(
+ 'exif-colorspace-1',
+ 'exif-colorspace-ffff.h',
+ ),
+ 'exif-componentsconfiguration' => array(
+ 'exif-componentsconfiguration-0',
+ 'exif-componentsconfiguration-1',
+ 'exif-componentsconfiguration-2',
+ 'exif-componentsconfiguration-3',
+ 'exif-componentsconfiguration-4',
+ 'exif-componentsconfiguration-5',
+ 'exif-componentsconfiguration-6',
+ ),
+ 'exif-exposureprogram' => array(
+ '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' => array(
+ 'exif-subjectdistance-value',
+ ),
+ 'exif-meteringmode' => array(
+ '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' => array(
+ '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-focalplaneresolutionunit' => array(
+ 'exif-focalplaneresolutionunit-2',
+ ),
+ 'exif-sensingmethod' => array(
+ 'exif-sensingmethod-1',
+ 'exif-sensingmethod-2',
+ 'exif-sensingmethod-3',
+ 'exif-sensingmethod-4',
+ 'exif-sensingmethod-5',
+ 'exif-sensingmethod-7',
+ 'exif-sensingmethod-8',
+ ),
+ 'exif-filesource' => array(
+ 'exif-filesource-3',
+ ),
+ 'exif-scenetype' => array(
+ 'exif-scenetype-1',
+ ),
+ 'exif-customrendered' => array(
+ 'exif-customrendered-0',
+ 'exif-customrendered-1',
+ ),
+ 'exif-exposuremode' => array(
+ 'exif-exposuremode-0',
+ 'exif-exposuremode-1',
+ 'exif-exposuremode-2',
+ ),
+ 'exif-whitebalance' => array(
+ 'exif-whitebalance-0',
+ 'exif-whitebalance-1',
+ ),
+ 'exif-scenecapturetype' => array(
+ 'exif-scenecapturetype-0',
+ 'exif-scenecapturetype-1',
+ 'exif-scenecapturetype-2',
+ 'exif-scenecapturetype-3',
+ ),
+ 'exif-gaincontrol' => array(
+ 'exif-gaincontrol-0',
+ 'exif-gaincontrol-1',
+ 'exif-gaincontrol-2',
+ 'exif-gaincontrol-3',
+ 'exif-gaincontrol-4',
+ ),
+ 'exif-contrast' => array(
+ 'exif-contrast-0',
+ 'exif-contrast-1',
+ 'exif-contrast-2',
+ ),
+ 'exif-saturation' => array(
+ 'exif-saturation-0',
+ 'exif-saturation-1',
+ 'exif-saturation-2',
+ ),
+ 'exif-sharpness' => array(
+ 'exif-sharpness-0',
+ 'exif-sharpness-1',
+ 'exif-sharpness-2',
+ ),
+ 'exif-subjectdistancerange' => array(
+ 'exif-subjectdistancerange-0',
+ 'exif-subjectdistancerange-1',
+ 'exif-subjectdistancerange-2',
+ 'exif-subjectdistancerange-3',
+ ),
+ 'exif-gpslatitude' => array(
+ 'exif-gpslatitude-n',
+ 'exif-gpslatitude-s',
+ ),
+ 'exif-gpslongitude' => array(
+ 'exif-gpslongitude-e',
+ 'exif-gpslongitude-w',
+ ),
+ 'exif-gpsstatus' => array(
+ 'exif-gpsstatus-a',
+ 'exif-gpsstatus-v',
+ ),
+ 'exif-gpsmeasuremode' => array(
+ 'exif-gpsmeasuremode-2',
+ 'exif-gpsmeasuremode-3',
+ ),
+ 'exif-gpsspeed' => array(
+ 'exif-gpsspeed-k',
+ 'exif-gpsspeed-m',
+ 'exif-gpsspeed-n',
+ ),
+ 'exif-gpsdirection' => array(
+ 'exif-gpsdirection-t',
+ 'exif-gpsdirection-m',
+ ),
+ 'edit-externally' => array(
+ 'edit-externally',
+ 'edit-externally-help',
+ ),
+ 'all' => array(
+ 'recentchangesall',
+ 'imagelistall',
+ 'watchlistall1',
+ 'watchlistall2',
+ 'namespacesall',
+ ),
+ 'confirmemail' => array(
+ 'confirmemail',
+ 'confirmemail_noemail',
+ 'confirmemail_text',
+ 'confirmemail_pending',
+ 'confirmemail_send',
+ 'confirmemail_sent',
+ 'confirmemail_oncreate',
+ 'confirmemail_sendfailed',
+ 'confirmemail_invalid',
+ 'confirmemail_needlogin',
+ 'confirmemail_success',
+ 'confirmemail_loggedin',
+ 'confirmemail_error',
+ 'confirmemail_subject',
+ 'confirmemail_body',
+ ),
+ 'inputbox' => array(
+ 'tryexact',
+ 'searchfulltext',
+ 'createarticle',
+ ),
+ 'scarytransclusion' => array(
+ 'scarytranscludedisabled',
+ 'scarytranscludefailed',
+ 'scarytranscludetoolong',
+ ),
+ 'trackbacks' => array(
+ 'trackbackbox',
+ 'trackback',
+ 'trackbackexcerpt',
+ 'trackbackremove',
+ 'trackbacklink',
+ 'trackbackdeleteok',
+ ),
+ 'deleteconflict' => array(
+ 'deletedwhileediting',
+ 'confirmrecreate',
+ 'recreate',
+ 'tooltip-recreate',
+ ),
+ 'unit-pixel' => array(
+ 'unit-pixel',
+ ),
+ 'htmldump' => array(
+ 'redirectingto',
+ ),
+ 'purge' => array(
+ 'confirm_purge',
+ 'confirm_purge_button',
+ ),
+ 'newmessagesmulti' => array(
+ 'youhavenewmessagesmulti',
+ 'newtalkseperator',
+ ),
+ 'search2' => array(
+ 'searchcontaining',
+ 'searchnamed',
+ 'articletitles',
+ 'hideresults',
+ ),
+ 'displaytitle' => array(
+ 'displaytitle',
+ ),
+ 'catseparator' => array(
+ 'catseparator',
+ ),
+ 'loginlanguage' => array(
+ 'loginlanguagelabel',
+ 'loginlanguagelinks',
+ ),
+ 'imgmulti' => array(
+ 'imgmultipageprev',
+ 'imgmultipagenext',
+ 'imgmultigo',
+ 'imgmultigotopre',
+ 'imgmultigotopost',
+ ),
+ 'tablepager' => array(
+ 'ascending_abbrev',
+ 'descending_abbrev',
+ 'table_pager_next',
+ 'table_pager_prev',
+ 'table_pager_first',
+ 'table_pager_last',
+ 'table_pager_limit',
+ 'table_pager_limit_submit',
+ 'table_pager_empty',
+ ),
+ 'autosumm' => array(
+ 'autosumm-blank',
+ 'autosumm-replace',
+ 'autoredircomment',
+ 'autosumm-new',
+ ),
+ 'autoblock_whitelist' => array(
+ 'autoblock_whitelist',
+ ),
+ 'sizeunits' => array(
+ 'size-bytes',
+ 'size-kilobytes',
+ 'size-megabytes',
+ 'size-gigabytes',
+ ),
+);
+/** Comments for each block */
+$wgBlockComments = array(
+ 'sidebar' => "The sidebar for MonoBook is generated from this message, lines that do not
+begin with * or ** are discarded, furthermore lines that do begin with ** and
+do not contain | are also discarded, but don't depend on this behaviour for
+future releases. Also note that since each list value is wrapped in a unique
+XHTML id it should only appear once and include characters that are legal
+XHTML id names.",
+ 'toggles' => 'User preference toggles',
+ 'underline' => '',
+ 'skinpreview' => '',
+ 'dates' => 'Dates',
+ 'categories' => 'Bits of text used by many pages',
+ 'mainpage' => '',
+ 'miscellaneous1' => '',
+ 'metadata_help' => 'Metadata in edit box',
+ 'currentevents' => '',
+ 'miscellaneous2' => '',
+ 'badaccess' => '',
+ 'versionrequired' => '',
+ 'miscellaneous3' => '',
+ 'nstab' => "Short words for each namespace, by default used in the 'article' tab in monobook",
+ 'main' => 'Main script and global functions',
+ 'errors' => 'General errors',
+ 'login' => 'Login and logout pages',
+ 'resetpass' => 'Password reset dialog',
+ 'toolbar' => 'Edit page toolbar',
+ 'edit' => 'Edit pages',
+ 'undo' => '"Undo" feature',
+ 'cantcreateaccount' => 'Account creation failure',
+ 'history' => 'History pages',
+ 'history-feed' => '',
+ 'revdelete' => 'Revision deletion',
+ 'diffs' => 'Diffs',
+ 'search' => 'Search results',
+ 'preferences' => 'Preferences page',
+ 'userrights' => 'User rights',
+ 'group' => 'Groups',
+ 'group-member' => '',
+ 'grouppage' => '',
+ 'recentchanges' => 'Recent changes',
+ 'upload' => 'Upload',
+ 'upload-errors' => '',
+ 'upload-curl-errors' => 'Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html>',
+ 'licenses' => '',
+ 'imagelist' => 'Image list',
+ 'mimesearch' => 'MIME search',
+ 'unwatchedpages' => 'Unwatched pages',
+ 'listredirects' => 'List redirects',
+ 'unusedtemplates' => 'Unused templates',
+ 'randomredirect' => 'Random redirect',
+ 'statistics' => 'Statistics',
+ 'disambiguations' => '',
+ 'doubleredirects' => '',
+ 'brokenredirects' => '',
+ 'specialpages' => 'Miscellaneous special pages',
+ 'booksources' => 'Book sources',
+ 'specialpages2' => '',
+ 'allpages' => 'Special:Allpages',
+ 'listusers' => 'Special:Listusers',
+ 'emailuser' => 'E-mail user',
+ 'watchlist' => 'Watchlist',
+ 'watching' => 'Displayed when you click the "watch" button and it\'s in the process of watching',
+ 'enotif' => '',
+ 'deleteprotectrev' => 'Delete/protect/revert',
+ 'restrictions' => 'Restrictions (nouns)',
+ 'undelete' => 'Undelete',
+ 'nsform' => 'Namespace form on various pages',
+ 'contributions' => 'Contributions',
+ 'sp-contributions' => '',
+ 'newimages-showfrom' => '',
+ 'whatlinkshere' => 'What links here',
+ 'block' => 'Block/unblock',
+ 'developertools' => 'Developer tools',
+ 'makesysop' => 'Make sysop',
+ 'movepage' => 'Move page',
+ 'export' => 'Export',
+ 'allmessages' => 'Namespace 8 related',
+ 'thumbnails' => 'Thumbnails',
+ 'import' => 'Special:Import',
+ 'importlog' => 'Import log',
+ 'accesskeys' => 'Keyboard access keys for power users',
+ 'tooltips' => 'Tooltip help for some actions, most are in Monobook.js',
+ 'stylesheets' => 'Stylesheets',
+ 'metadata_cc' => 'Metadata',
+ 'attribution' => 'Attribution',
+ 'spamprotection' => 'Spam protection',
+ 'info' => 'Info page',
+ 'math' => 'Math options',
+ 'patrolling' => 'Patrolling',
+ 'monobook.js' => 'Monobook.js: tooltips and access keys for monobook',
+ 'common.js' => 'Common.js: contains nothing but a placeholder comment',
+ 'imagedeletion' => 'Image deletion',
+ 'browsediffs' => 'Browsing diffs',
+ 'imagesize' => '',
+ 'newimages' => '',
+ 'variantname-zh' => "Short names for language variants used for language conversion links.
+To disable showing a particular link, set it to 'disable', e.g.
+'variantname-zh-sg' => 'disable',
+Variants for Chinese language",
+ 'variantname-sr' => 'Variants for Serbian language',
+ 'variantname-kk' => 'Variants for Kazakh language',
+ 'specialloglabels' => 'Labels for User: and Title: on Special:Log pages',
+ 'passwordtooshort' => '',
+ 'mediawarning' => 'Media Warning',
+ 'fileinfo' => '',
+ 'metadata' => 'Metadata',
+ 'exif' => 'EXIF tags',
+ 'exif-values' => 'Make & model, can be wikified in order to link to the camera and model name',
+ 'exif-compression' => 'EXIF attributes',
+ 'exif-unknowndate' => '',
+ 'exif-photometricinterpretation' => '',
+ 'exif-orientation' => '',
+ 'exif-planarconfiguration' => '',
+ 'exif-xyresolution' => '',
+ 'exif-colorspace' => '',
+ 'exif-componentsconfiguration' => '',
+ 'exif-exposureprogram' => '',
+ 'exif-subjectdistance-value' => '',
+ 'exif-meteringmode' => '',
+ 'exif-lightsource' => '',
+ 'exif-focalplaneresolutionunit' => '',
+ 'exif-sensingmethod' => '',
+ 'exif-filesource' => '',
+ 'exif-scenetype' => '',
+ 'exif-customrendered' => '',
+ 'exif-exposuremode' => '',
+ 'exif-whitebalance' => '',
+ 'exif-scenecapturetype' => '',
+ 'exif-gaincontrol' => '',
+ 'exif-contrast' => '',
+ 'exif-saturation' => '',
+ 'exif-sharpness' => '',
+ 'exif-subjectdistancerange' => '',
+ 'exif-gpslatitude' => 'Pseudotags used for GPSLatitudeRef and GPSDestLatitudeRef',
+ 'exif-gpslongitude' => 'Pseudotags used for GPSLongitudeRef and GPSDestLongitudeRef',
+ 'exif-gpsstatus' => '',
+ 'exif-gpsmeasuremode' => '',
+ 'exif-gpsspeed' => 'Pseudotags used for GPSSpeedRef and GPSDestDistanceRef',
+ 'exif-gpsdirection' => 'Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef',
+ 'edit-externally' => 'External editor support',
+ 'all' => "'all' in various places, this might be different for inflected languages",
+ 'confirmemail' => 'E-mail address confirmation',
+ 'inputbox' => 'Inputbox extension, may be useful in other contexts as well',
+ 'scarytransclusion' => 'Scary transclusion',
+ 'trackbacks' => 'Trackbacks',
+ 'deleteconflict' => 'Delete conflict',
+ 'unit-pixel' => '',
+ 'htmldump' => 'HTML dump',
+ 'purge' => 'action=purge',
+ 'newmessagesmulti' => '',
+ 'search2' => '',
+ 'displaytitle' => 'DISPLAYTITLE',
+ 'catseparator' => 'Separator for categories in page lists',
+ 'loginlanguage' => '',
+ 'imgmulti' => 'Multipage image navigation',
+ 'tablepager' => 'Table pager',
+ 'autosumm' => 'Auto-summaries',
+ 'autoblock_whitelist' => 'Autoblock whitelist',
+ 'sizeunits' => 'Size units',
+);
+
+/** Short comments for standalone messages */
+$wgMessageComments = array(
+ 'lastmodifiedat' => '$1 date, $2 time',
+ 'sitenotice' => 'the equivalent to wgSiteNotice',
+ 'perfdisabledsub' => 'obsolete?',
+ 'history-feed-item-nocomment' => 'user at time',
+ 'editcomment' => 'only shown if there is an edit comment',
+ 'lastmodifiedatby' => '$1 date, $2 time, $3 user',
+ 'exif-orientation-1' => '0th row: top; 0th column: left',
+ 'exif-orientation-2' => '0th row: top; 0th column: right',
+ 'exif-orientation-3' => '0th row: bottom; 0th column: right',
+ 'exif-orientation-4' => '0th row: bottom; 0th column: left',
+ 'exif-orientation-5' => '0th row: left; 0th column: top',
+ 'exif-orientation-6' => '0th row: right; 0th column: top',
+ 'exif-orientation-7' => '0th row: right; 0th column: bottom',
+ 'exif-orientation-8' => '0th row: left; 0th column: bottom',
+ 'autoredircomment' => 'This should be changed to the new naming convention, but existed beforehand',
+);
+
+/** Messages which contain dollar signs (which are not followed by numbers), and therefore should use a single apostrophe */
+$wgMessagseWithDollarSigns = array(
+ 'linkprefix',
+ 'enotif_subject',
+ 'enotif_body',
+ 'allmessagesnotsupportedDB',
+);
+
+?>
diff --git a/maintenance/language/rebuildLanguage.php b/maintenance/language/rebuildLanguage.php
new file mode 100644
index 00000000..1643d30b
--- /dev/null
+++ b/maintenance/language/rebuildLanguage.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Rewrite the messages array in the files languages/messages/MessagesXX.php.
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+require_once( dirname(__FILE__).'/../commandLine.inc' );
+require_once( 'languages.inc' );
+require_once( 'writeMessagesArray.inc' );
+
+/**
+ * Rewrite a messages array.
+ *
+ * @param $code The language code.
+ * @param $write Write to the messages file?
+ */
+function rebuildLanguage( $code, $write ) {
+ global $wgLanguages, $wg;
+
+ # Get messages
+ $messages = $wgLanguages->getMessages( $code );
+ $messages = $messages['all'];
+
+ # Rewrite messages array
+ $messagesText = writeMessagesArray( $messages, $code == 'en' );
+
+ # Write to the file
+ if ( $write ) {
+ $filename = Language::getMessagesFileName( $code );
+ $contents = file_get_contents( $filename );
+ if ( strpos( $contents, '$messages' ) !== false ) {
+ $new = explode( '$messages', $contents );
+ $new = $new[0];
+ $new .= $messagesText;
+ $new .= "\n?>\n";
+ file_put_contents( $filename, $new );
+ echo "Generated and wrote messages in language $code.\n";
+ }
+ } else {
+ echo "Generated messages in language $code.\n";
+ }
+}
+
+# Show help
+if ( isset( $options['help'] ) ) {
+ echo <<<END
+Run this script to rewrite the messages array in the files languages/messages/MessagesXX.php.
+Parameters:
+ * lang: Language code (default: the installation default language). You can also specify "all" to check all the languages.
+ * help: Show this help.
+Options:
+ * dry-run: Don't write the array to the file.
+
+END;
+ exit();
+}
+
+# Get the language code
+if ( isset( $options['lang'] ) ) {
+ $wgCode = $options['lang'];
+} else {
+ $wgCode = $wgContLang->getCode();
+}
+
+# Get the write options
+$wgWriteToFile = !isset( $options['dry-run'] );
+
+# Get language objects
+$wgLanguages = new languages();
+
+# Write all the language
+if ( $wgCode == 'all' ) {
+ foreach ( $wgLanguages->getLanguages() as $language ) {
+ rebuildLanguage( $language, $wgWriteToFile );
+ }
+} else {
+ rebuildLanguage( $wgCode, $wgWriteToFile );
+}
+
+?>
diff --git a/maintenance/language/splitLanguageFiles.inc b/maintenance/language/splitLanguageFiles.inc
index c2500778..500d2cdc 100644
--- a/maintenance/language/splitLanguageFiles.inc
+++ b/maintenance/language/splitLanguageFiles.inc
@@ -1124,7 +1124,7 @@ $commonMsg = array (
'thumbnail-more',
'missingimage',
'filemissing',
-'Monobook.css',
+'monobook.css',
'nodublincore',
'nocreativecommons',
'notacceptable',
@@ -1154,7 +1154,7 @@ $commonMsg = array (
'rcpatroldisabled', // not used ?
'rcpatroldisabledtext', // not used ?
-'Monobook.js',
+'monobook.js',
'newimages',
'noimages',
'variantname-zh-cn',
diff --git a/maintenance/language/transstat.php b/maintenance/language/transstat.php
index 590da121..e1b67274 100644
--- a/maintenance/language/transstat.php
+++ b/maintenance/language/transstat.php
@@ -12,7 +12,7 @@
* http://meta.wikimedia.org/wiki/Localization_statistics
*/
-require_once( 'maintenance/commandLine.inc' );
+require_once( dirname(__FILE__).'/../commandLine.inc' );
require_once( 'languages.inc' );
if ( isset( $options['help'] ) ) {
@@ -67,7 +67,7 @@ class wikiStatsOutput extends statsOutput {
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 '{| border="2" cellpadding="4" cellspacing="0" style="background-color: #F9F9F9; border: 1px #AAAAAA solid; border-collapse: collapse;" width="100%"'."\n";
+ echo '{| class="sortable wikitable" border="2" cellpadding="4" cellspacing="0" style="background-color: #F9F9F9; border: 1px #AAAAAA solid; border-collapse: collapse;" width="100%"'."\n";
}
function footer() {
echo "|}\n";
@@ -160,6 +160,7 @@ $wgLanguages = new languages();
$wgOut->heading();
$wgOut->blockstart();
$wgOut->element( 'Language', true );
+$wgOut->element( 'Code', true );
$wgOut->element( 'Translated', true );
$wgOut->element( '%', true );
$wgOut->element( 'Obsolete', true );
@@ -195,7 +196,8 @@ foreach ( $wgLanguages->getLanguages() as $code ) {
# Output them
$wgOut->blockstart();
- $wgOut->element( "$language ($code)" );
+ $wgOut->element( "$language" );
+ $wgOut->element( "$code" );
$wgOut->element( "$requiredMessagesNumber/$wgRequiredMessagesNumber" );
$wgOut->element( $requiredMessagesPercent );
$wgOut->element( "$obsoleteMessagesNumber/$messagesNumber" );
diff --git a/maintenance/language/writeMessagesArray.inc b/maintenance/language/writeMessagesArray.inc
new file mode 100644
index 00000000..b0d17c59
--- /dev/null
+++ b/maintenance/language/writeMessagesArray.inc
@@ -0,0 +1,145 @@
+<?php
+/**
+ * Write a messages array as a PHP text.
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+require_once( 'messages.inc' );
+require_once( 'messageTypes.inc' );
+
+/**
+ * Write a messages array as a PHP text.
+ *
+ * @param $messages The messages array.
+ * @param $ignoredComments Show comments about ignored and optional messages? (For English.)
+ *
+ * @return The PHP text.
+ */
+function writeMessagesArray( $messages, $ignoredComments = false ) {
+ global $wgMessageStrucutre, $wgBlockComments, $wgMessageComments;
+
+ # Sort messages to blocks
+ $sortedMessages['unknown'] = $messages;
+ foreach ( $wgMessageStrucutre as $blockName => $block ) {
+ foreach ( $block as $key ) {
+ if ( array_key_exists( $key, $sortedMessages['unknown'] ) ) {
+ $sortedMessages[$blockName][$key] = $sortedMessages['unknown'][$key];
+ unset( $sortedMessages['unknown'][$key] );
+ }
+ }
+ }
+
+ # Write all the messages
+ $messagesText = "\$messages = array(\n";
+ foreach( $sortedMessages as $block => $messages ) {
+ # Skip if it's the block of unknown messages - handle that in the end of file
+ if ( $block == 'unknown' ) {
+ continue;
+ }
+
+ # Write the block
+ $messagesText .= writeMessagesBlock( $block, $wgBlockComments[$block], $messages, $ignoredComments );
+ }
+ ksort( $sortedMessages['unknown'] );
+ $messagesText .= writeMessagesBlock( 'unknown', 'Unknown messages', $sortedMessages['unknown'], $ignoredComments ); # Write the unknown messages, alphabetically sorted
+ $messagesText .= ");\n";
+
+ return $messagesText;
+}
+
+/**
+ * Write a block of messages to PHP.
+ *
+ * @param $name The block name.
+ * @param $comment The block comment.
+ * @param $messages The block messages.
+ * @param $ignoredComments Show comments about ignored and optional messages? (For English.)
+ *
+ * @return The block, formatted in PHP.
+ */
+function writeMessagesBlock( $name, $comment, $messages, $ignoredComments ) {
+ global $wgMessageComments, $wgMessagseWithDollarSigns;
+ global $wgIgnoredMessages, $wgOptionalMessages;
+ $blockText = '';
+
+ # Skip the block if it includes no messages
+ if ( empty( $messages ) ) {
+ return '';
+ }
+
+ # Format the block comment (if exists); check for multiple lines comments
+ if ( !empty( $comment ) ) {
+ if ( strpos( $comment, "\n" ) === false ) {
+ $blockText .= "# $comment\n";
+ } else {
+ $blockText .= "/*\n$comment\n*/\n";
+ }
+ }
+
+ # Get max key length
+ $maxKeyLength = 0;
+ foreach( array_keys( $messages ) as $key ) {
+ if ( strlen( $key ) > $maxKeyLength ) {
+ $maxKeyLength = strlen( $key );
+ }
+ }
+
+ # Format the messages
+ foreach( $messages as $key => $value ) {
+ # Add the key name
+ $blockText .= "'$key'";
+
+ # Add the appropriate block whitespace
+ for ( $i = 1; $i <= ( $maxKeyLength - strlen( $key ) ); $i++ ) {
+ $blockText .= ' ';
+ }
+
+ # Refer to the value
+ $blockText .= ' => ';
+
+ # Check for the appropriate apostrophe and add the value
+ if ( strpos( $value, "'" ) === false ) {
+ $blockText .= "'$value'";
+ } elseif ( strpos( $value, '"' ) === false && !in_array( $key, $wgMessagseWithDollarSigns ) ) {
+ $blockText .= "\"$value\"";
+ } else {
+ $blockText .= "'" . str_replace( "'", "\'", $value ) . "'";
+ }
+
+ # Comma
+ $blockText .= ',';
+
+ $ignoredComment = "don't translate or duplicate this message to other languages";
+ $optionalComment = "only translate this message to other languages if you have to change it";
+ $showIgnoredOrOptionalComment = in_array( $key, $wgIgnoredMessages ) || in_array( $key, $wgOptionalMessages );
+ if ( $ignoredComments ) {
+ if ( array_key_exists( $key, $wgMessageComments ) ) {
+ $blockText .= ' # ' . $wgMessageComments[$key];
+ if ( $showIgnoredOrOptionalComment ) {
+ $blockText .= '; ';
+ }
+ } elseif ( $showIgnoredOrOptionalComment ) {
+ $blockText .= ' # ';
+ }
+ if ( in_array( $key, $wgIgnoredMessages ) ) {
+ $blockText .= $ignoredComment;
+ } elseif ( in_array( $key, $wgOptionalMessages ) ) {
+ $blockText .= $optionalComment;
+ }
+ } elseif ( array_key_exists( $key, $wgMessageComments ) ) {
+ $blockText .= ' # ' . $wgMessageComments[$key];
+ }
+
+ # Newline
+ $blockText .= "\n";
+ }
+
+ # Newline to end the block
+ $blockText .= "\n";
+
+ return $blockText;
+}
+
+?>
diff --git a/maintenance/moveBatch.php b/maintenance/moveBatch.php
index 8d7141cd..4b0abf7f 100644
--- a/maintenance/moveBatch.php
+++ b/maintenance/moveBatch.php
@@ -1,13 +1,23 @@
<?php
-# Move a batch of pages
-# Usage: php moveBatch.php [-u <user>] [-r <reason>] [-i <interval>] <listfile>
-# where
-# <listfile> is a file where each line has two titles separated by a pipe
-# character. The first title is the source, the second is the destination.
-# <user> is the username
-# <reason> is the move reason
-# <interval> is the number of seconds to sleep for after each move
+/**
+ * Maintenance script to move a batch of pages
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * @author Tim Starling
+ *
+ * USAGE: php moveBatch.php [-u <user>] [-r <reason>] [-i <interval>] <listfile>
+ *
+ * <listfile> - file with two titles per line, separated with pipe characters;
+ * the first title is the source, the second is the destination
+ * <user> - username to perform moves as
+ * <reason> - reason to be given for moves
+ * <interval> - number of seconds to sleep after each move
+ *
+ * This will print out error codes from Title::moveTo() if something goes wrong,
+ * e.g. immobile_namespace for namespaces which can't be moved
+ */
$oldCwd = getcwd();
$optionsWithArgs = array( 'u', 'r', 'i' );
@@ -66,7 +76,7 @@ for ( $linenum = 1; !feof( $file ); $linenum++ ) {
}
- print $source->getPrefixedText();
+ print $source->getPrefixedText() . ' --> ' . $dest->getPrefixedText();
$dbw->begin();
$err = $source->moveTo( $dest, false, $reason );
if( $err !== true ) {
diff --git a/maintenance/mysql5/tables-binary.sql b/maintenance/mysql5/tables-binary.sql
new file mode 100644
index 00000000..2ab36546
--- /dev/null
+++ b/maintenance/mysql5/tables-binary.sql
@@ -0,0 +1,1095 @@
+-- Experimental table definitions for MySQL 4.1 and 5.0 with
+-- content-holding fields switched to explicit binary charset.
+--
+-- Binary is used instead of UTF-8 or UCS-2 so that all of
+-- Unicode may be used as UTF-8 (MySQL still does not allow
+-- use of characters outside the BMP in UTF-8 and has no UTF-16
+-- support).
+--
+-- This should provide compatibility with our current MySQL 4.0
+-- behavior (safe for full UTF-8, but ugly sorting) on newer
+-- versions of MySQL server, without the conversion surprises
+-- you get from piggybacking on "Latin-1" fields.
+--
+-- UTF-8 is used for the searchindex fields, as the fulltext index
+-- doesn't seem to like the binary encoding.
+--
+-- Not fully tested, may have surprises!
+--
+-- TODO: Test various fields
+
+-- ------------------------------------------------------------
+
+-- SQL to create the initial tables for the MediaWiki database.
+-- This is read and executed by the install script; you should
+-- not have to run it by itself unless doing a manual install.
+
+--
+-- General notes:
+--
+-- If possible, create tables as InnoDB to benefit from the
+-- superior resiliency against crashes and ability to read
+-- during writes (and write during reads!)
+--
+-- Only the 'searchindex' table requires MyISAM due to the
+-- requirement for fulltext index support, which is missing
+-- from InnoDB.
+--
+--
+-- The MySQL table backend for MediaWiki currently uses
+-- 14-character CHAR or VARCHAR fields to store timestamps.
+-- The format is YYYYMMDDHHMMSS, which is derived from the
+-- text format of MySQL's TIMESTAMP fields.
+--
+-- Historically TIMESTAMP fields were used, but abandoned
+-- in early 2002 after a lot of trouble with the fields
+-- auto-updating.
+--
+-- The Postgres backend uses DATETIME fields for timestamps,
+-- and we will migrate the MySQL definitions at some point as
+-- well.
+--
+--
+-- The /*$wgDBprefix*/ comments in this and other files are
+-- replaced with the defined table prefix by the installer
+-- and updater scripts. If you are installing or running
+-- updates manually, you will need to manually insert the
+-- table prefix if any when running these scripts.
+--
+
+
+--
+-- The user table contains basic account information,
+-- authentication keys, etc.
+--
+-- Some multi-wiki sites may share a single central user table
+-- between separate wikis using the $wgSharedDB setting.
+--
+-- Note that when a external authentication plugin is used,
+-- user table entries still need to be created to store
+-- preferences and to key tracking information in the other
+-- tables.
+--
+CREATE TABLE /*$wgDBprefix*/user (
+ user_id int(5) unsigned NOT NULL auto_increment,
+
+ -- Usernames must be unique, must not be in the form of
+ -- an IP address. _Shouldn't_ allow slashes or case
+ -- conflicts. Spaces are allowed, and are _not_ converted
+ -- to underscores like titles. See the User::newFromName() for
+ -- the specific tests that usernames have to pass.
+ user_name varchar(255) binary NOT NULL default '',
+
+ -- Optional 'real name' to be displayed in credit listings
+ user_real_name varchar(255) binary NOT NULL default '',
+
+ -- Password hashes, normally hashed like so:
+ -- MD5(CONCAT(user_id,'-',MD5(plaintext_password))), see
+ -- wfEncryptPassword() in GlobalFunctions.php
+ user_password tinyblob NOT NULL,
+
+ -- When using 'mail me a new password', a random
+ -- password is generated and the hash stored here.
+ -- The previous password is left in place until
+ -- someone actually logs in with the new password,
+ -- at which point the hash is moved to user_password
+ -- and the old password is invalidated.
+ user_newpassword tinyblob NOT NULL,
+
+ -- Timestamp of the last time when a new password was
+ -- sent, for throttling purposes
+ user_newpass_time char(14) binary,
+
+ -- Note: email should be restricted, not public info.
+ -- Same with passwords.
+ user_email tinytext NOT NULL,
+
+ -- Newline-separated list of name=value defining the user
+ -- preferences
+ user_options blob NOT NULL,
+
+ -- This is a timestamp which is updated when a user
+ -- logs in, logs out, changes preferences, or performs
+ -- some other action requiring HTML cache invalidation
+ -- to ensure that the UI is updated.
+ user_touched char(14) binary NOT NULL default '',
+
+ -- A pseudorandomly generated value that is stored in
+ -- a cookie when the "remember password" feature is
+ -- used (previously, a hash of the password was used, but
+ -- this was vulnerable to cookie-stealing attacks)
+ user_token char(32) binary NOT NULL default '',
+
+ -- Initially NULL; when a user's e-mail address has been
+ -- validated by returning with a mailed token, this is
+ -- set to the current timestamp.
+ user_email_authenticated char(14) binary,
+
+ -- Randomly generated token created when the e-mail address
+ -- is set and a confirmation test mail sent.
+ user_email_token char(32) binary,
+
+ -- Expiration date for the user_email_token
+ user_email_token_expires char(14) binary,
+
+ -- Timestamp of account registration.
+ -- Accounts predating this schema addition may contain NULL.
+ user_registration char(14) binary,
+
+ -- Count of edits and edit-like actions.
+ --
+ -- *NOT* intended to be an accurate copy of COUNT(*) WHERE rev_user=user_id
+ -- May contain NULL for old accounts if batch-update scripts haven't been
+ -- run, as well as listing deleted edits and other myriad ways it could be
+ -- out of sync.
+ --
+ -- Meant primarily for heuristic checks to give an impression of whether
+ -- the account has been used much.
+ --
+ user_editcount int,
+
+ PRIMARY KEY user_id (user_id),
+ UNIQUE INDEX user_name (user_name),
+ INDEX (user_email_token)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- User permissions have been broken out to a separate table;
+-- this allows sites with a shared user table to have different
+-- permissions assigned to a user in each project.
+--
+-- This table replaces the old user_rights field which used a
+-- comma-separated blob.
+--
+CREATE TABLE /*$wgDBprefix*/user_groups (
+ -- Key to user_id
+ ug_user int(5) unsigned NOT NULL default '0',
+
+ -- Group names are short symbolic string keys.
+ -- The set of group names is open-ended, though in practice
+ -- only some predefined ones are likely to be used.
+ --
+ -- At runtime $wgGroupPermissions will associate group keys
+ -- with particular permissions. A user will have the combined
+ -- permissions of any group they're explicitly in, plus
+ -- the implicit '*' and 'user' groups.
+ ug_group char(16) NOT NULL default '',
+
+ PRIMARY KEY (ug_user,ug_group),
+ KEY (ug_group)
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+-- Stores notifications of user talk page changes, for the display
+-- of the "you have new messages" box
+CREATE TABLE /*$wgDBprefix*/user_newtalk (
+ -- Key to user.user_id
+ user_id int(5) NOT NULL default '0',
+ -- If the user is an anonymous user hir IP address is stored here
+ -- since the user_id of 0 is ambiguous
+ user_ip varchar(40) NOT NULL default '',
+ INDEX user_id (user_id),
+ INDEX user_ip (user_ip)
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+
+--
+-- Core of the wiki: each page has an entry here which identifies
+-- it by title and contains some essential metadata.
+--
+CREATE TABLE /*$wgDBprefix*/page (
+ -- Unique identifier number. The page_id will be preserved across
+ -- edits and rename operations, but not deletions and recreations.
+ page_id int(8) unsigned NOT NULL auto_increment,
+
+ -- A page name is broken into a namespace and a title.
+ -- The namespace keys are UI-language-independent constants,
+ -- defined in includes/Defines.php
+ page_namespace int NOT NULL,
+
+ -- The rest of the title, as text.
+ -- Spaces are transformed into underscores in title storage.
+ page_title varchar(255) binary NOT NULL,
+
+ -- Comma-separated set of permission keys indicating who
+ -- can move or edit the page.
+ page_restrictions tinyblob NOT NULL,
+
+ -- Number of times this page has been viewed.
+ page_counter bigint(20) unsigned NOT NULL default '0',
+
+ -- 1 indicates the article is a redirect.
+ page_is_redirect tinyint(1) unsigned NOT NULL default '0',
+
+ -- 1 indicates this is a new entry, with only one edit.
+ -- Not all pages with one edit are new pages.
+ page_is_new tinyint(1) unsigned NOT NULL default '0',
+
+ -- Random value between 0 and 1, used for Special:Randompage
+ page_random real unsigned NOT NULL,
+
+ -- This timestamp is updated whenever the page changes in
+ -- a way requiring it to be re-rendered, invalidating caches.
+ -- Aside from editing this includes permission changes,
+ -- creation or deletion of linked pages, and alteration
+ -- of contained templates.
+ page_touched char(14) binary NOT NULL default '',
+
+ -- Handy key to revision.rev_id of the current revision.
+ -- This may be 0 during page creation, but that shouldn't
+ -- happen outside of a transaction... hopefully.
+ page_latest int(8) unsigned NOT NULL,
+
+ -- Uncompressed length in bytes of the page's current source text.
+ page_len int(8) unsigned NOT NULL,
+
+ PRIMARY KEY page_id (page_id),
+ UNIQUE INDEX name_title (page_namespace,page_title),
+
+ -- Special-purpose indexes
+ INDEX (page_random),
+ INDEX (page_len)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- Every edit of a page creates also a revision row.
+-- This stores metadata about the revision, and a reference
+-- to the text storage backend.
+--
+CREATE TABLE /*$wgDBprefix*/revision (
+ rev_id int(8) unsigned NOT NULL auto_increment,
+
+ -- Key to page_id. This should _never_ be invalid.
+ rev_page int(8) unsigned NOT NULL,
+
+ -- Key to text.old_id, where the actual bulk text is stored.
+ -- It's possible for multiple revisions to use the same text,
+ -- for instance revisions where only metadata is altered
+ -- or a rollback to a previous version.
+ rev_text_id int(8) unsigned NOT NULL,
+
+ -- Text comment summarizing the change.
+ -- This text is shown in the history and other changes lists,
+ -- rendered in a subset of wiki markup by Linker::formatComment()
+ rev_comment tinyblob NOT NULL,
+
+ -- Key to user.user_id of the user who made this edit.
+ -- Stores 0 for anonymous edits and for some mass imports.
+ rev_user int(5) unsigned NOT NULL default '0',
+
+ -- Text username or IP address of the editor.
+ rev_user_text varchar(255) binary NOT NULL default '',
+
+ -- Timestamp
+ rev_timestamp char(14) binary NOT NULL default '',
+
+ -- Records whether the user marked the 'minor edit' checkbox.
+ -- Many automated edits are marked as minor.
+ rev_minor_edit tinyint(1) unsigned NOT NULL default '0',
+
+ -- Not yet used; reserved for future changes to the deletion system.
+ rev_deleted tinyint(1) 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)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+
+--
+-- Holds text of individual page revisions.
+--
+-- Field names are a holdover from the 'old' revisions table in
+-- MediaWiki 1.4 and earlier: an upgrade will transform that
+-- table into the 'text' table to minimize unnecessary churning
+-- and downtime. If upgrading, the other fields will be left unused.
+--
+CREATE TABLE /*$wgDBprefix*/text (
+ -- Unique text storage key number.
+ -- Note that the 'oldid' parameter used in URLs does *not*
+ -- refer to this number anymore, but to rev_id.
+ --
+ -- revision.rev_text_id is a key to this column
+ old_id int(8) unsigned NOT NULL auto_increment,
+
+ -- Depending on the contents of the old_flags field, the text
+ -- may be convenient plain text, or it may be funkily encoded.
+ old_text mediumblob NOT NULL,
+
+ -- Comma-separated list of flags:
+ -- gzip: text is compressed with PHP's gzdeflate() function.
+ -- utf8: text was stored as UTF-8.
+ -- If $wgLegacyEncoding option is on, rows *without* this flag
+ -- will be converted to UTF-8 transparently at load time.
+ -- object: text field contained a serialized PHP object.
+ -- The object either contains multiple versions compressed
+ -- together to achieve a better compression ratio, or it refers
+ -- to another row where the text can be found.
+ old_flags tinyblob NOT NULL,
+
+ PRIMARY KEY old_id (old_id)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- Holding area for deleted articles, which may be viewed
+-- or restored by admins through the Special:Undelete interface.
+-- The fields generally correspond to the page, revision, and text
+-- fields, with several caveats.
+--
+CREATE TABLE /*$wgDBprefix*/archive (
+ ar_namespace int NOT NULL default '0',
+ ar_title varchar(255) binary NOT NULL default '',
+
+ -- Newly deleted pages will not store text in this table,
+ -- but will reference the separately existing text rows.
+ -- This field is retained for backwards compatibility,
+ -- so old archived pages will remain accessible after
+ -- upgrading from 1.4 to 1.5.
+ -- Text may be gzipped or otherwise funky.
+ ar_text mediumblob NOT NULL,
+
+ -- Basic revision stuff...
+ ar_comment tinyblob NOT NULL,
+ ar_user int(5) unsigned NOT NULL default '0',
+ ar_user_text varchar(255) binary NOT NULL,
+ ar_timestamp char(14) binary NOT NULL default '',
+ ar_minor_edit tinyint(1) NOT NULL default '0',
+
+ -- See ar_text note.
+ ar_flags tinyblob NOT NULL,
+
+ -- When revisions are deleted, their unique rev_id is stored
+ -- here so it can be retained after undeletion. This is necessary
+ -- to retain permalinks to given revisions after accidental delete
+ -- cycles or messy operations like history merges.
+ --
+ -- Old entries from 1.4 will be NULL here, and a new rev_id will
+ -- be created on undeletion for those revisions.
+ ar_rev_id int(8) unsigned,
+
+ -- For newly deleted revisions, this is the text.old_id key to the
+ -- actual stored text. To avoid breaking the block-compression scheme
+ -- and otherwise making storage changes harder, the actual text is
+ -- *not* deleted from the text table, merely hidden by removal of the
+ -- page and revision entries.
+ --
+ -- Old entries deleted under 1.2-1.4 will have NULL here, and their
+ -- ar_text and ar_flags fields will be used to create a new text
+ -- row upon undeletion.
+ ar_text_id int(8) unsigned,
+
+ KEY name_title_timestamp (ar_namespace,ar_title,ar_timestamp)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+
+--
+-- Track page-to-page hyperlinks within the wiki.
+--
+CREATE TABLE /*$wgDBprefix*/pagelinks (
+ -- Key to the page_id of the page containing the link.
+ pl_from int(8) unsigned NOT NULL default '0',
+
+ -- Key to page_namespace/page_title of the target page.
+ -- The target page may or may not exist, and due to renames
+ -- and deletions may refer to different page records as time
+ -- goes by.
+ pl_namespace int NOT NULL default '0',
+ pl_title varchar(255) binary NOT NULL default '',
+
+ UNIQUE KEY pl_from (pl_from,pl_namespace,pl_title),
+ KEY (pl_namespace,pl_title,pl_from)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+
+--
+-- Track template inclusions.
+--
+CREATE TABLE /*$wgDBprefix*/templatelinks (
+ -- Key to the page_id of the page containing the link.
+ tl_from int(8) unsigned NOT NULL default '0',
+
+ -- Key to page_namespace/page_title of the target page.
+ -- The target page may or may not exist, and due to renames
+ -- and deletions may refer to different page records as time
+ -- goes by.
+ tl_namespace int NOT NULL default '0',
+ tl_title varchar(255) binary NOT NULL default '',
+
+ UNIQUE KEY tl_from (tl_from,tl_namespace,tl_title),
+ KEY (tl_namespace,tl_title,tl_from)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+
+--
+-- Track links to images *used inline*
+-- We don't distinguish live from broken links here, so
+-- they do not need to be changed on upload/removal.
+--
+CREATE TABLE /*$wgDBprefix*/imagelinks (
+ -- Key to page_id of the page containing the image / media link.
+ il_from int(8) unsigned NOT NULL default '0',
+
+ -- Filename of target image.
+ -- This is also the page_title of the file's description page;
+ -- all such pages are in namespace 6 (NS_IMAGE).
+ il_to varchar(255) binary NOT NULL default '',
+
+ UNIQUE KEY il_from (il_from,il_to),
+ KEY (il_to,il_from)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- Track category inclusions *used inline*
+-- This tracks a single level of category membership
+-- (folksonomic tagging, really).
+--
+CREATE TABLE /*$wgDBprefix*/categorylinks (
+ -- Key to page_id of the page defined as a category member.
+ cl_from int(8) unsigned NOT NULL default '0',
+
+ -- Name of the category.
+ -- This is also the page_title of the category's description page;
+ -- all such pages are in namespace 14 (NS_CATEGORY).
+ cl_to varchar(255) binary NOT NULL default '',
+
+ -- The title of the linking page, or an optional override
+ -- to determine sort order. Sorting is by binary order, which
+ -- isn't always ideal, but collations seem to be an exciting
+ -- and dangerous new world in MySQL...
+ --
+ -- For MySQL 4.1+ with charset set to utf8, the sort key *index*
+ -- needs cut to be smaller than 1024 bytes (at 3 bytes per char).
+ -- To sort properly on the shorter key, this field needs to be
+ -- the same shortness.
+ cl_sortkey varchar(86) binary NOT NULL default '',
+
+ -- This isn't really used at present. Provided for an optional
+ -- sorting method by approximate addition time.
+ cl_timestamp timestamp NOT NULL,
+
+ UNIQUE KEY cl_from (cl_from,cl_to),
+
+ -- We always sort within a given category...
+ KEY cl_sortkey (cl_to,cl_sortkey),
+
+ -- Not really used?
+ KEY cl_timestamp (cl_to,cl_timestamp)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- Track links to external URLs
+--
+CREATE TABLE /*$wgDBprefix*/externallinks (
+ -- page_id of the referring page
+ el_from int(8) unsigned NOT NULL default '0',
+
+ -- The URL
+ el_to blob NOT NULL,
+
+ -- In the case of HTTP URLs, this is the URL with any username or password
+ -- removed, and with the labels in the hostname reversed and converted to
+ -- lower case. An extra dot is added to allow for matching of either
+ -- example.com or *.example.com in a single scan.
+ -- Example:
+ -- http://user:password@sub.example.com/page.html
+ -- becomes
+ -- http://com.example.sub./page.html
+ -- which allows for fast searching for all pages under example.com with the
+ -- clause:
+ -- WHERE el_index LIKE 'http://com.example.%'
+ el_index blob NOT NULL,
+
+ KEY (el_from, el_to(40)),
+ KEY (el_to(60), el_from),
+ KEY (el_index(60))
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- Track interlanguage links
+--
+CREATE TABLE /*$wgDBprefix*/langlinks (
+ -- page_id of the referring page
+ ll_from int(8) unsigned NOT NULL default '0',
+
+ -- Language code of the target
+ ll_lang varchar(10) binary NOT NULL default '',
+
+ -- Title of the target, including namespace
+ ll_title varchar(255) binary NOT NULL default '',
+
+ UNIQUE KEY (ll_from, ll_lang),
+ KEY (ll_lang, ll_title)
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- Contains a single row with some aggregate info
+-- on the state of the site.
+--
+CREATE TABLE /*$wgDBprefix*/site_stats (
+ -- The single row should contain 1 here.
+ ss_row_id int(8) unsigned NOT NULL,
+
+ -- Total number of page views, if hit counters are enabled.
+ ss_total_views bigint(20) unsigned default '0',
+
+ -- Total number of edits performed.
+ ss_total_edits bigint(20) unsigned default '0',
+
+ -- An approximate count of pages matching the following criteria:
+ -- * in namespace 0
+ -- * not a redirect
+ -- * contains the text '[['
+ -- See Article::isCountable() in includes/Article.php
+ ss_good_articles bigint(20) unsigned default '0',
+
+ -- Total pages, theoretically equal to SELECT COUNT(*) FROM page; except faster
+ ss_total_pages bigint(20) default '-1',
+
+ -- Number of users, theoretically equal to SELECT COUNT(*) FROM user;
+ ss_users bigint(20) default '-1',
+
+ -- Deprecated, no longer updated as of 1.5
+ ss_admins int(10) default '-1',
+
+ -- Number of images, equivalent to SELECT COUNT(*) FROM image
+ ss_images int(10) default '0',
+
+ UNIQUE KEY ss_row_id (ss_row_id)
+
+) ENGINE=InnoDB;
+
+--
+-- Stores an ID for every time any article is visited;
+-- depending on $wgHitcounterUpdateFreq, it is
+-- periodically cleared and the page_counter column
+-- in the page table updated for the all articles
+-- that have been visited.)
+--
+CREATE TABLE /*$wgDBprefix*/hitcounter (
+ hc_id int unsigned NOT NULL
+) ENGINE=HEAP MAX_ROWS=25000;
+
+
+--
+-- The internet is full of jerks, alas. Sometimes it's handy
+-- to block a vandal or troll account.
+--
+CREATE TABLE /*$wgDBprefix*/ipblocks (
+ -- Primary key, introduced for privacy.
+ ipb_id int(8) NOT NULL auto_increment,
+
+ -- Blocked IP address in dotted-quad form or user name.
+ ipb_address tinyblob NOT NULL,
+
+ -- Blocked user ID or 0 for IP blocks.
+ ipb_user int(8) unsigned NOT NULL default '0',
+
+ -- User ID who made the block.
+ ipb_by int(8) unsigned NOT NULL default '0',
+
+ -- Text comment made by blocker.
+ ipb_reason tinyblob NOT NULL,
+
+ -- Creation (or refresh) date in standard YMDHMS form.
+ -- IP blocks expire automatically.
+ ipb_timestamp char(14) binary NOT NULL default '',
+
+ -- Indicates that the IP address was banned because a banned
+ -- user accessed a page through it. If this is 1, ipb_address
+ -- will be hidden, and the block identified by block ID number.
+ ipb_auto bool NOT NULL default '0',
+
+ -- If set to 1, block applies only to logged-out users
+ ipb_anon_only bool NOT NULL default 0,
+
+ -- Block prevents account creation from matching IP addresses
+ ipb_create_account bool NOT NULL default 1,
+
+ -- Block triggers autoblocks
+ ipb_enable_autoblock bool NOT NULL default '1',
+
+ -- Time at which the block will expire.
+ ipb_expiry char(14) binary NOT NULL default '',
+
+ -- Start and end of an address range, in hexadecimal
+ -- Size chosen to allow IPv6
+ ipb_range_start varchar(32) NOT NULL default '',
+ ipb_range_end varchar(32) NOT NULL default '',
+
+ PRIMARY KEY ipb_id (ipb_id),
+
+ -- Unique index to support "user already blocked" messages
+ -- Any new options which prevent collisions should be included
+ UNIQUE INDEX ipb_address (ipb_address(255), ipb_user, ipb_auto, ipb_anon_only),
+
+ INDEX ipb_user (ipb_user),
+ INDEX ipb_range (ipb_range_start(8), ipb_range_end(8)),
+ INDEX ipb_timestamp (ipb_timestamp),
+ INDEX ipb_expiry (ipb_expiry)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+
+--
+-- Uploaded images and other files.
+--
+CREATE TABLE /*$wgDBprefix*/image (
+ -- Filename.
+ -- This is also the title of the associated description page,
+ -- which will be in namespace 6 (NS_IMAGE).
+ img_name varchar(255) binary NOT NULL default '',
+
+ -- File size in bytes.
+ img_size int(8) unsigned NOT NULL default '0',
+
+ -- For images, size in pixels.
+ img_width int(5) NOT NULL default '0',
+ img_height int(5) NOT NULL default '0',
+
+ -- Extracted EXIF metadata stored as a serialized PHP array.
+ img_metadata mediumblob NOT NULL,
+
+ -- For images, bits per pixel if known.
+ img_bits int(3) NOT NULL default '0',
+
+ -- Media type as defined by the MEDIATYPE_xxx constants
+ img_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
+
+ -- major part of a MIME media type as defined by IANA
+ -- see http://www.iana.org/assignments/media-types/
+ img_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") NOT NULL default "unknown",
+
+ -- minor part of a MIME media type as defined by IANA
+ -- the minor parts are not required to adher to any standard
+ -- but should be consistent throughout the database
+ -- see http://www.iana.org/assignments/media-types/
+ img_minor_mime varchar(32) NOT NULL default "unknown",
+
+ -- Description field as entered by the uploader.
+ -- This is displayed in image upload history and logs.
+ img_description tinyblob NOT NULL,
+
+ -- user_id and user_name of uploader.
+ img_user int(5) unsigned NOT NULL default '0',
+ img_user_text varchar(255) binary NOT NULL default '',
+
+ -- Time of the upload.
+ img_timestamp char(14) binary NOT NULL default '',
+
+ PRIMARY KEY img_name (img_name),
+
+ -- Used by Special:Imagelist for sort-by-size
+ INDEX img_size (img_size),
+
+ -- Used by Special:Newimages and Special:Imagelist
+ INDEX img_timestamp (img_timestamp)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- Previous revisions of uploaded files.
+-- Awkwardly, image rows have to be moved into
+-- this table at re-upload time.
+--
+CREATE TABLE /*$wgDBprefix*/oldimage (
+ -- Base filename: key to image.img_name
+ oi_name varchar(255) binary NOT NULL default '',
+
+ -- Filename of the archived file.
+ -- This is generally a timestamp and '!' prepended to the base name.
+ oi_archive_name varchar(255) binary NOT NULL default '',
+
+ -- Other fields as in image...
+ oi_size int(8) unsigned NOT NULL default 0,
+ oi_width int(5) NOT NULL default 0,
+ oi_height int(5) NOT NULL default 0,
+ oi_bits int(3) NOT NULL default 0,
+ oi_description tinyblob NOT NULL,
+ oi_user int(5) unsigned NOT NULL default '0',
+ oi_user_text varchar(255) binary NOT NULL default '',
+ oi_timestamp char(14) binary NOT NULL default '',
+
+ INDEX oi_name (oi_name(10))
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+
+--
+-- Record of deleted file data
+--
+CREATE TABLE /*$wgDBprefix*/filearchive (
+ -- Unique row id
+ fa_id int NOT NULL auto_increment,
+
+ -- Original base filename; key to image.img_name, page.page_title, etc
+ fa_name varchar(255) binary NOT NULL default '',
+
+ -- Filename of archived file, if an old revision
+ fa_archive_name varchar(255) binary default '',
+
+ -- Which storage bin (directory tree or object store) the file data
+ -- is stored in. Should be 'deleted' for files that have been deleted;
+ -- any other bin is not yet in use.
+ fa_storage_group varchar(16),
+
+ -- SHA-1 of the file contents plus extension, used as a key for storage.
+ -- eg 8f8a562add37052a1848ff7771a2c515db94baa9.jpg
+ --
+ -- If NULL, the file was missing at deletion time or has been purged
+ -- from the archival storage.
+ fa_storage_key varchar(64) binary default '',
+
+ -- Deletion information, if this file is deleted.
+ fa_deleted_user int,
+ fa_deleted_timestamp char(14) binary default '',
+ fa_deleted_reason text,
+
+ -- Duped fields from image
+ fa_size int(8) unsigned default '0',
+ fa_width int(5) default '0',
+ fa_height int(5) default '0',
+ fa_metadata mediumblob,
+ fa_bits int(3) default '0',
+ fa_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
+ fa_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") default "unknown",
+ fa_minor_mime varchar(32) default "unknown",
+ fa_description tinyblob,
+ fa_user int(5) unsigned default '0',
+ fa_user_text varchar(255) binary default '',
+ fa_timestamp char(14) binary default '',
+
+ PRIMARY KEY (fa_id),
+ INDEX (fa_name, fa_timestamp), -- pick out by image name
+ INDEX (fa_storage_group, fa_storage_key), -- pick out dupe files
+ INDEX (fa_deleted_timestamp), -- sort by deletion time
+ INDEX (fa_deleted_user) -- sort by deleter
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- Primarily a summary table for Special:Recentchanges,
+-- this table contains some additional info on edits from
+-- the last few days, see Article::editUpdates()
+--
+CREATE TABLE /*$wgDBprefix*/recentchanges (
+ rc_id int(8) NOT NULL auto_increment,
+ rc_timestamp varchar(14) binary NOT NULL default '',
+ rc_cur_time varchar(14) binary NOT NULL default '',
+
+ -- As in revision
+ rc_user int(10) unsigned NOT NULL default '0',
+ rc_user_text varchar(255) binary NOT NULL default '',
+
+ -- When pages are renamed, their RC entries do _not_ change.
+ rc_namespace int NOT NULL default '0',
+ rc_title varchar(255) binary NOT NULL default '',
+
+ -- as in revision...
+ rc_comment varchar(255) binary NOT NULL default '',
+ rc_minor tinyint(3) unsigned NOT NULL default '0',
+
+ -- Edits by user accounts with the 'bot' rights key are
+ -- marked with a 1 here, and will be hidden from the
+ -- default view.
+ rc_bot tinyint(3) unsigned NOT NULL default '0',
+
+ rc_new tinyint(3) unsigned NOT NULL default '0',
+
+ -- Key to page_id (was cur_id prior to 1.5).
+ -- This will keep links working after moves while
+ -- retaining the at-the-time name in the changes list.
+ rc_cur_id int(10) unsigned NOT NULL default '0',
+
+ -- rev_id of the given revision
+ rc_this_oldid int(10) unsigned NOT NULL default '0',
+
+ -- rev_id of the prior revision, for generating diff links.
+ rc_last_oldid int(10) unsigned NOT NULL default '0',
+
+ -- These may no longer be used, with the new move log.
+ rc_type tinyint(3) unsigned NOT NULL default '0',
+ rc_moved_to_ns tinyint(3) unsigned NOT NULL default '0',
+ rc_moved_to_title varchar(255) binary NOT NULL default '',
+
+ -- If the Recent Changes Patrol option is enabled,
+ -- users may mark edits as having been reviewed to
+ -- remove a warning flag on the RC list.
+ -- A value of 1 indicates the page has been reviewed.
+ rc_patrolled tinyint(3) unsigned NOT NULL default '0',
+
+ -- Recorded IP address the edit was made from, if the
+ -- $wgPutIPinRC option is enabled.
+ rc_ip char(15) NOT NULL default '',
+
+ -- Text length in characters before
+ -- and after the edit
+ rc_old_len int(10) default '0',
+ rc_new_len int(10) default '0',
+
+ PRIMARY KEY rc_id (rc_id),
+ INDEX rc_timestamp (rc_timestamp),
+ INDEX rc_namespace_title (rc_namespace, rc_title),
+ INDEX rc_cur_id (rc_cur_id),
+ INDEX new_name_timestamp (rc_new,rc_namespace,rc_timestamp),
+ INDEX rc_ip (rc_ip),
+ INDEX rc_ns_usertext ( rc_namespace, rc_user_text )
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+CREATE TABLE /*$wgDBprefix*/watchlist (
+ -- Key to user.user_id
+ wl_user int(5) unsigned NOT NULL,
+
+ -- Key to page_namespace/page_title
+ -- Note that users may watch pages which do not exist yet,
+ -- or existed in the past but have been deleted.
+ wl_namespace int NOT NULL default '0',
+ wl_title varchar(255) binary NOT NULL default '',
+
+ -- Timestamp when user was last sent a notification e-mail;
+ -- cleared when the user visits the page.
+ wl_notificationtimestamp varchar(14) binary,
+
+ UNIQUE KEY (wl_user, wl_namespace, wl_title),
+ KEY namespace_title (wl_namespace,wl_title)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+
+--
+-- Used by the math module to keep track
+-- of previously-rendered items.
+--
+CREATE TABLE /*$wgDBprefix*/math (
+ -- Binary MD5 hash of the latex fragment, used as an identifier key.
+ math_inputhash varbinary(16) NOT NULL,
+
+ -- Not sure what this is, exactly...
+ math_outputhash varbinary(16) NOT NULL,
+
+ -- texvc reports how well it thinks the HTML conversion worked;
+ -- if it's a low level the PNG rendering may be preferred.
+ math_html_conservativeness tinyint(1) NOT NULL,
+
+ -- HTML output from texvc, if any
+ math_html text,
+
+ -- MathML output from texvc, if any
+ math_mathml text,
+
+ UNIQUE KEY math_inputhash (math_inputhash)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- When using the default MySQL search backend, page titles
+-- and text are munged to strip markup, do Unicode case folding,
+-- and prepare the result for MySQL's fulltext index.
+--
+-- This table must be MyISAM; InnoDB does not support the needed
+-- fulltext index.
+--
+CREATE TABLE /*$wgDBprefix*/searchindex (
+ -- Key to page_id
+ si_page int(8) unsigned NOT NULL,
+
+ -- Munged version of title
+ si_title varchar(255) NOT NULL default '',
+
+ -- Munged version of body text
+ si_text mediumtext NOT NULL,
+
+ UNIQUE KEY (si_page),
+ FULLTEXT si_title (si_title),
+ FULLTEXT si_text (si_text)
+
+) ENGINE=MyISAM, DEFAULT CHARSET=utf8;
+
+--
+-- Recognized interwiki link prefixes
+--
+CREATE TABLE /*$wgDBprefix*/interwiki (
+ -- The interwiki prefix, (e.g. "Meatball", or the language prefix "de")
+ iw_prefix char(32) NOT NULL,
+
+ -- The URL of the wiki, with "$1" as a placeholder for an article name.
+ -- Any spaces in the name will be transformed to underscores before
+ -- insertion.
+ iw_url char(127) NOT NULL,
+
+ -- A boolean value indicating whether the wiki is in this project
+ -- (used, for example, to detect redirect loops)
+ iw_local bool NOT NULL,
+
+ -- Boolean value indicating whether interwiki transclusions are allowed.
+ iw_trans tinyint(1) NOT NULL default 0,
+
+ UNIQUE KEY iw_prefix (iw_prefix)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- Used for caching expensive grouped queries
+--
+CREATE TABLE /*$wgDBprefix*/querycache (
+ -- A key name, generally the base name of of the special page.
+ qc_type char(32) NOT NULL,
+
+ -- Some sort of stored value. Sizes, counts...
+ qc_value int(5) unsigned NOT NULL default '0',
+
+ -- Target namespace+title
+ qc_namespace int NOT NULL default '0',
+ qc_title char(255) binary NOT NULL default '',
+
+ KEY (qc_type,qc_value)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- For a few generic cache operations if not using Memcached
+--
+CREATE TABLE /*$wgDBprefix*/objectcache (
+ keyname char(255) binary NOT NULL default '',
+ value mediumblob,
+ exptime datetime,
+ UNIQUE KEY (keyname),
+ KEY (exptime)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+--
+-- Cache of interwiki transclusion
+--
+CREATE TABLE /*$wgDBprefix*/transcache (
+ tc_url varchar(255) NOT NULL,
+ tc_contents text,
+ tc_time int NOT NULL,
+ UNIQUE INDEX tc_url_idx (tc_url)
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+CREATE TABLE /*$wgDBprefix*/logging (
+ -- Symbolic keys for the general log type and the action type
+ -- within the log. The output format will be controlled by the
+ -- action field, but only the type controls categorization.
+ log_type char(10) NOT NULL default '',
+ log_action char(10) NOT NULL default '',
+
+ -- Timestamp. Duh.
+ log_timestamp char(14) NOT NULL default '19700101000000',
+
+ -- The user who performed this action; key to user_id
+ log_user int unsigned NOT NULL default 0,
+
+ -- Key to the page affected. Where a user is the target,
+ -- this will point to the user page.
+ log_namespace int NOT NULL default 0,
+ log_title varchar(255) binary NOT NULL default '',
+
+ -- Freeform text. Interpreted as edit history comments.
+ log_comment varchar(255) NOT NULL default '',
+
+ -- LF separated list of miscellaneous parameters
+ log_params blob NOT NULL,
+
+ KEY type_time (log_type, log_timestamp),
+ KEY user_time (log_user, log_timestamp),
+ KEY page_time (log_namespace, log_title, log_timestamp)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+CREATE TABLE /*$wgDBprefix*/trackbacks (
+ tb_id int auto_increment,
+ tb_page int REFERENCES page(page_id) ON DELETE CASCADE,
+ tb_title varchar(255) NOT NULL,
+ tb_url varchar(255) NOT NULL,
+ tb_ex text,
+ tb_name varchar(255),
+
+ PRIMARY KEY (tb_id),
+ INDEX (tb_page)
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+-- Jobs performed by parallel apache threads or a command-line daemon
+CREATE TABLE /*$wgDBprefix*/job (
+ job_id int(9) unsigned NOT NULL auto_increment,
+
+ -- Command name, currently only refreshLinks is defined
+ job_cmd varchar(255) NOT NULL default '',
+
+ -- Namespace and title to act on
+ -- Should be 0 and '' if the command does not operate on a title
+ job_namespace int NOT NULL,
+ job_title varchar(255) binary NOT NULL,
+
+ -- Any other parameters to the command
+ -- Presently unused, format undefined
+ job_params blob NOT NULL,
+
+ PRIMARY KEY job_id (job_id),
+ KEY (job_cmd, job_namespace, job_title)
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+-- Details of updates to cached special pages
+CREATE TABLE /*$wgDBprefix*/querycache_info (
+
+ -- Special page name
+ -- Corresponds to a qc_type value
+ qci_type varchar(32) NOT NULL default '',
+
+ -- Timestamp of last update
+ qci_timestamp char(14) NOT NULL default '19700101000000',
+
+ UNIQUE KEY ( qci_type )
+
+) ENGINE=InnoDB;
+
+-- For each redirect, this table contains exactly one row defining its target
+CREATE TABLE /*$wgDBprefix*/redirect (
+ -- Key to the page_id of the redirect page
+ rd_from int(8) unsigned NOT NULL default '0',
+
+ -- Key to page_namespace/page_title of the target page.
+ -- The target page may or may not exist, and due to renames
+ -- and deletions may refer to different page records as time
+ -- goes by.
+ rd_namespace int NOT NULL default '0',
+ rd_title varchar(255) binary NOT NULL default '',
+
+ PRIMARY KEY rd_from (rd_from),
+ KEY rd_ns_title (rd_namespace,rd_title,rd_from)
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
+
+-- Used for caching expensive grouped queries that need two links (for example double-redirects)
+
+CREATE TABLE /*$wgDBprefix*/querycachetwo (
+ -- A key name, generally the base name of of the special page.
+ qcc_type char(32) NOT NULL,
+
+ -- Some sort of stored value. Sizes, counts...
+ qcc_value int(5) unsigned NOT NULL default '0',
+
+ -- Target namespace+title
+ qcc_namespace int NOT NULL default '0',
+ qcc_title char(255) binary NOT NULL default '',
+
+ -- Target namespace+title2
+ qcc_namespacetwo int NOT NULL default '0',
+ qcc_titletwo char(255) binary NOT NULL default '',
+
+ KEY qcc_type (qcc_type,qcc_value),
+ KEY qcc_title (qcc_type,qcc_namespace,qcc_title),
+ KEY qcc_titletwo (qcc_type,qcc_namespacetwo,qcc_titletwo)
+
+) ENGINE=InnoDB, DEFAULT CHARSET=binary;
diff --git a/maintenance/mysql5/tables.sql b/maintenance/mysql5/tables.sql
index 81a4690a..356f3bbf 100644
--- a/maintenance/mysql5/tables.sql
+++ b/maintenance/mysql5/tables.sql
@@ -36,7 +36,7 @@
-- in early 2002 after a lot of trouble with the fields
-- auto-updating.
--
--- The PostgreSQL backend uses DATETIME fields for timestamps,
+-- The Postgres backend uses DATETIME fields for timestamps,
-- and we will migrate the MySQL definitions at some point as
-- well.
--
@@ -77,7 +77,7 @@ CREATE TABLE /*$wgDBprefix*/user (
-- Password hashes, normally hashed like so:
-- MD5(CONCAT(user_id,'-',MD5(plaintext_password))), see
-- wfEncryptPassword() in GlobalFunctions.php
- user_password tinyblob NOT NULL default '',
+ user_password tinyblob NOT NULL,
-- When using 'mail me a new password', a random
-- password is generated and the hash stored here.
@@ -85,15 +85,19 @@ CREATE TABLE /*$wgDBprefix*/user (
-- someone actually logs in with the new password,
-- at which point the hash is moved to user_password
-- and the old password is invalidated.
- user_newpassword tinyblob NOT NULL default '',
+ user_newpassword tinyblob NOT NULL,
+
+ -- Timestamp of the last time when a new password was
+ -- sent, for throttling purposes
+ user_newpass_time char(14) binary,
-- Note: email should be restricted, not public info.
-- Same with passwords.
- user_email tinytext NOT NULL default '',
+ user_email tinytext NOT NULL,
-- Newline-separated list of name=value defining the user
-- preferences
- user_options blob NOT NULL default '',
+ user_options blob NOT NULL,
-- This is a timestamp which is updated when a user
-- logs in, logs out, changes preferences, or performs
@@ -110,24 +114,36 @@ CREATE TABLE /*$wgDBprefix*/user (
-- Initially NULL; when a user's e-mail address has been
-- validated by returning with a mailed token, this is
-- set to the current timestamp.
- user_email_authenticated CHAR(14) BINARY,
+ user_email_authenticated char(14) binary,
-- Randomly generated token created when the e-mail address
-- is set and a confirmation test mail sent.
- user_email_token CHAR(32) BINARY,
+ user_email_token char(32) binary,
-- Expiration date for the user_email_token
- user_email_token_expires CHAR(14) BINARY,
+ user_email_token_expires char(14) binary,
-- Timestamp of account registration.
-- Accounts predating this schema addition may contain NULL.
- user_registration CHAR(14) BINARY,
+ user_registration char(14) binary,
+
+ -- Count of edits and edit-like actions.
+ --
+ -- *NOT* intended to be an accurate copy of COUNT(*) WHERE rev_user=user_id
+ -- May contain NULL for old accounts if batch-update scripts haven't been
+ -- run, as well as listing deleted edits and other myriad ways it could be
+ -- out of sync.
+ --
+ -- Meant primarily for heuristic checks to give an impression of whether
+ -- the account has been used much.
+ --
+ user_editcount int,
PRIMARY KEY user_id (user_id),
UNIQUE INDEX user_name (user_name),
INDEX (user_email_token)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- User permissions have been broken out to a separate table;
@@ -153,7 +169,7 @@ CREATE TABLE /*$wgDBprefix*/user_groups (
PRIMARY KEY (ug_user,ug_group),
KEY (ug_group)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
-- Stores notifications of user talk page changes, for the display
-- of the "you have new messages" box
@@ -165,7 +181,7 @@ CREATE TABLE /*$wgDBprefix*/user_newtalk (
user_ip varchar(40) NOT NULL default '',
INDEX user_id (user_id),
INDEX user_ip (user_ip)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
@@ -188,7 +204,7 @@ CREATE TABLE /*$wgDBprefix*/page (
-- Comma-separated set of permission keys indicating who
-- can move or edit the page.
- page_restrictions tinyblob NOT NULL default '',
+ page_restrictions tinyblob NOT NULL,
-- Number of times this page has been viewed.
page_counter bigint(20) unsigned NOT NULL default '0',
@@ -225,7 +241,7 @@ CREATE TABLE /*$wgDBprefix*/page (
INDEX (page_random),
INDEX (page_len)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- Every edit of a page creates also a revision row.
@@ -247,7 +263,7 @@ CREATE TABLE /*$wgDBprefix*/revision (
-- Text comment summarizing the change.
-- This text is shown in the history and other changes lists,
-- rendered in a subset of wiki markup by Linker::formatComment()
- rev_comment tinyblob NOT NULL default '',
+ rev_comment tinyblob NOT NULL,
-- Key to user.user_id of the user who made this edit.
-- Stores 0 for anonymous edits and for some mass imports.
@@ -273,7 +289,7 @@ CREATE TABLE /*$wgDBprefix*/revision (
INDEX user_timestamp (rev_user,rev_timestamp),
INDEX usertext_timestamp (rev_user_text,rev_timestamp)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
@@ -294,7 +310,7 @@ CREATE TABLE /*$wgDBprefix*/text (
-- Depending on the contents of the old_flags field, the text
-- may be convenient plain text, or it may be funkily encoded.
- old_text mediumblob NOT NULL default '',
+ old_text mediumblob NOT NULL,
-- Comma-separated list of flags:
-- gzip: text is compressed with PHP's gzdeflate() function.
@@ -305,11 +321,11 @@ CREATE TABLE /*$wgDBprefix*/text (
-- The object either contains multiple versions compressed
-- together to achieve a better compression ratio, or it refers
-- to another row where the text can be found.
- old_flags tinyblob NOT NULL default '',
+ old_flags tinyblob NOT NULL,
PRIMARY KEY old_id (old_id)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- Holding area for deleted articles, which may be viewed
@@ -327,17 +343,17 @@ CREATE TABLE /*$wgDBprefix*/archive (
-- so old archived pages will remain accessible after
-- upgrading from 1.4 to 1.5.
-- Text may be gzipped or otherwise funky.
- ar_text mediumblob NOT NULL default '',
+ ar_text mediumblob NOT NULL,
-- Basic revision stuff...
- ar_comment tinyblob NOT NULL default '',
+ ar_comment tinyblob NOT NULL,
ar_user int(5) unsigned NOT NULL default '0',
ar_user_text varchar(255) binary NOT NULL,
ar_timestamp char(14) binary NOT NULL default '',
ar_minor_edit tinyint(1) NOT NULL default '0',
-- See ar_text note.
- ar_flags tinyblob NOT NULL default '',
+ ar_flags tinyblob NOT NULL,
-- When revisions are deleted, their unique rev_id is stored
-- here so it can be retained after undeletion. This is necessary
@@ -361,7 +377,7 @@ CREATE TABLE /*$wgDBprefix*/archive (
KEY name_title_timestamp (ar_namespace,ar_title,ar_timestamp)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
@@ -378,10 +394,10 @@ CREATE TABLE /*$wgDBprefix*/pagelinks (
pl_namespace int NOT NULL default '0',
pl_title varchar(255) binary NOT NULL default '',
- UNIQUE KEY pl_from(pl_from,pl_namespace,pl_title),
- KEY (pl_namespace,pl_title)
+ UNIQUE KEY pl_from (pl_from,pl_namespace,pl_title),
+ KEY (pl_namespace,pl_title,pl_from)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
@@ -398,10 +414,10 @@ CREATE TABLE /*$wgDBprefix*/templatelinks (
tl_namespace int NOT NULL default '0',
tl_title varchar(255) binary NOT NULL default '',
- UNIQUE KEY tl_from(tl_from,tl_namespace,tl_title),
- KEY (tl_namespace,tl_title)
+ UNIQUE KEY tl_from (tl_from,tl_namespace,tl_title),
+ KEY (tl_namespace,tl_title,tl_from)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
@@ -418,10 +434,10 @@ CREATE TABLE /*$wgDBprefix*/imagelinks (
-- all such pages are in namespace 6 (NS_IMAGE).
il_to varchar(255) binary NOT NULL default '',
- UNIQUE KEY il_from(il_from,il_to),
- KEY (il_to)
+ UNIQUE KEY il_from (il_from,il_to),
+ KEY (il_to,il_from)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- Track category inclusions *used inline*
@@ -452,15 +468,15 @@ CREATE TABLE /*$wgDBprefix*/categorylinks (
-- sorting method by approximate addition time.
cl_timestamp timestamp NOT NULL,
- UNIQUE KEY cl_from(cl_from,cl_to),
+ UNIQUE KEY cl_from (cl_from,cl_to),
-- We always sort within a given category...
- KEY cl_sortkey(cl_to,cl_sortkey),
+ KEY cl_sortkey (cl_to,cl_sortkey),
-- Not really used?
- KEY cl_timestamp(cl_to,cl_timestamp)
+ KEY cl_timestamp (cl_to,cl_timestamp)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- Track links to external URLs
@@ -470,7 +486,7 @@ CREATE TABLE /*$wgDBprefix*/externallinks (
el_from int(8) unsigned NOT NULL default '0',
-- The URL
- el_to blob NOT NULL default '',
+ el_to blob NOT NULL,
-- In the case of HTTP URLs, this is the URL with any username or password
-- removed, and with the labels in the hostname reversed and converted to
@@ -483,12 +499,12 @@ CREATE TABLE /*$wgDBprefix*/externallinks (
-- which allows for fast searching for all pages under example.com with the
-- clause:
-- WHERE el_index LIKE 'http://com.example.%'
- el_index blob NOT NULL default '',
+ el_index blob NOT NULL,
KEY (el_from, el_to(40)),
KEY (el_to(60), el_from),
KEY (el_index(60))
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- Track interlanguage links
@@ -542,7 +558,7 @@ CREATE TABLE /*$wgDBprefix*/site_stats (
UNIQUE KEY ss_row_id (ss_row_id)
-) TYPE=InnoDB;
+) ENGINE=InnoDB;
--
-- Stores an ID for every time any article is visited;
@@ -552,8 +568,8 @@ CREATE TABLE /*$wgDBprefix*/site_stats (
-- that have been visited.)
--
CREATE TABLE /*$wgDBprefix*/hitcounter (
- hc_id INTEGER UNSIGNED NOT NULL
-) TYPE=HEAP MAX_ROWS=25000;
+ hc_id int unsigned NOT NULL
+) ENGINE=HEAP MAX_ROWS=25000;
--
@@ -565,7 +581,7 @@ CREATE TABLE /*$wgDBprefix*/ipblocks (
ipb_id int(8) NOT NULL auto_increment,
-- Blocked IP address in dotted-quad form or user name.
- ipb_address varchar(40) binary NOT NULL default '',
+ ipb_address tinyblob NOT NULL,
-- Blocked user ID or 0 for IP blocks.
ipb_user int(8) unsigned NOT NULL default '0',
@@ -574,7 +590,7 @@ CREATE TABLE /*$wgDBprefix*/ipblocks (
ipb_by int(8) unsigned NOT NULL default '0',
-- Text comment made by blocker.
- ipb_reason tinyblob NOT NULL default '',
+ ipb_reason tinyblob NOT NULL,
-- Creation (or refresh) date in standard YMDHMS form.
-- IP blocks expire automatically.
@@ -590,6 +606,9 @@ CREATE TABLE /*$wgDBprefix*/ipblocks (
-- Block prevents account creation from matching IP addresses
ipb_create_account bool NOT NULL default 1,
+
+ -- Block triggers autoblocks
+ ipb_enable_autoblock bool NOT NULL default '1',
-- Time at which the block will expire.
ipb_expiry char(14) binary NOT NULL default '',
@@ -610,7 +629,7 @@ CREATE TABLE /*$wgDBprefix*/ipblocks (
INDEX ipb_timestamp (ipb_timestamp),
INDEX ipb_expiry (ipb_expiry)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
@@ -626,14 +645,14 @@ CREATE TABLE /*$wgDBprefix*/image (
img_size int(8) unsigned NOT NULL default '0',
-- For images, size in pixels.
- img_width int(5) NOT NULL default '0',
- img_height int(5) NOT NULL default '0',
+ img_width int(5) NOT NULL default '0',
+ img_height int(5) NOT NULL default '0',
-- Extracted EXIF metadata stored as a serialized PHP array.
img_metadata mediumblob NOT NULL,
-- For images, bits per pixel if known.
- img_bits int(3) NOT NULL default '0',
+ img_bits int(3) NOT NULL default '0',
-- Media type as defined by the MEDIATYPE_xxx constants
img_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
@@ -650,7 +669,7 @@ CREATE TABLE /*$wgDBprefix*/image (
-- Description field as entered by the uploader.
-- This is displayed in image upload history and logs.
- img_description tinyblob NOT NULL default '',
+ img_description tinyblob NOT NULL,
-- user_id and user_name of uploader.
img_user int(5) unsigned NOT NULL default '0',
@@ -667,7 +686,7 @@ CREATE TABLE /*$wgDBprefix*/image (
-- Used by Special:Newimages and Special:Imagelist
INDEX img_timestamp (img_timestamp)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- Previous revisions of uploaded files.
@@ -687,14 +706,14 @@ CREATE TABLE /*$wgDBprefix*/oldimage (
oi_width int(5) NOT NULL default 0,
oi_height int(5) NOT NULL default 0,
oi_bits int(3) NOT NULL default 0,
- oi_description tinyblob NOT NULL default '',
+ oi_description tinyblob NOT NULL,
oi_user int(5) unsigned NOT NULL default '0',
oi_user_text varchar(255) binary NOT NULL default '',
oi_timestamp char(14) binary NOT NULL default '',
INDEX oi_name (oi_name(10))
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
@@ -702,7 +721,7 @@ CREATE TABLE /*$wgDBprefix*/oldimage (
--
CREATE TABLE /*$wgDBprefix*/filearchive (
-- Unique row id
- fa_id int not null auto_increment,
+ fa_id int NOT NULL auto_increment,
-- Original base filename; key to image.img_name, page.page_title, etc
fa_name varchar(255) binary NOT NULL default '',
@@ -729,14 +748,14 @@ CREATE TABLE /*$wgDBprefix*/filearchive (
-- Duped fields from image
fa_size int(8) unsigned default '0',
- fa_width int(5) default '0',
- fa_height int(5) default '0',
+ fa_width int(5) default '0',
+ fa_height int(5) default '0',
fa_metadata mediumblob,
- fa_bits int(3) default '0',
+ fa_bits int(3) default '0',
fa_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
fa_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") default "unknown",
fa_minor_mime varchar(32) default "unknown",
- fa_description tinyblob default '',
+ fa_description tinyblob,
fa_user int(5) unsigned default '0',
fa_user_text varchar(255) binary default '',
fa_timestamp char(14) binary default '',
@@ -747,7 +766,7 @@ CREATE TABLE /*$wgDBprefix*/filearchive (
INDEX (fa_deleted_timestamp), -- sort by deletion time
INDEX (fa_deleted_user) -- sort by deleter
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- Primarily a summary table for Special:Recentchanges,
@@ -804,15 +823,20 @@ CREATE TABLE /*$wgDBprefix*/recentchanges (
-- $wgPutIPinRC option is enabled.
rc_ip char(15) NOT NULL default '',
+ -- Text length in characters before
+ -- and after the edit
+ rc_old_len int(10) default '0',
+ rc_new_len int(10) default '0',
+
PRIMARY KEY rc_id (rc_id),
INDEX rc_timestamp (rc_timestamp),
INDEX rc_namespace_title (rc_namespace, rc_title),
INDEX rc_cur_id (rc_cur_id),
- INDEX new_name_timestamp(rc_new,rc_namespace,rc_timestamp),
+ INDEX new_name_timestamp (rc_new,rc_namespace,rc_timestamp),
INDEX rc_ip (rc_ip),
INDEX rc_ns_usertext ( rc_namespace, rc_user_text )
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
CREATE TABLE /*$wgDBprefix*/watchlist (
-- Key to user.user_id
@@ -831,7 +855,7 @@ CREATE TABLE /*$wgDBprefix*/watchlist (
UNIQUE KEY (wl_user, wl_namespace, wl_title),
KEY namespace_title (wl_namespace,wl_title)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
@@ -857,7 +881,7 @@ CREATE TABLE /*$wgDBprefix*/math (
UNIQUE KEY math_inputhash (math_inputhash)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- When using the default MySQL search backend, page titles
@@ -875,13 +899,13 @@ CREATE TABLE /*$wgDBprefix*/searchindex (
si_title varchar(255) NOT NULL default '',
-- Munged version of body text
- si_text mediumtext NOT NULL default '',
+ si_text mediumtext NOT NULL,
UNIQUE KEY (si_page),
FULLTEXT si_title (si_title),
FULLTEXT si_text (si_text)
-) TYPE=MyISAM, DEFAULT CHARSET=utf8;
+) ENGINE=MyISAM, DEFAULT CHARSET=utf8;
--
-- Recognized interwiki link prefixes
@@ -897,14 +921,14 @@ CREATE TABLE /*$wgDBprefix*/interwiki (
-- A boolean value indicating whether the wiki is in this project
-- (used, for example, to detect redirect loops)
- iw_local BOOL NOT NULL,
+ iw_local bool NOT NULL,
-- Boolean value indicating whether interwiki transclusions are allowed.
- iw_trans TINYINT(1) NOT NULL DEFAULT 0,
+ iw_trans tinyint(1) NOT NULL default 0,
UNIQUE KEY iw_prefix (iw_prefix)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- Used for caching expensive grouped queries
@@ -922,29 +946,29 @@ CREATE TABLE /*$wgDBprefix*/querycache (
KEY (qc_type,qc_value)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- For a few generic cache operations if not using Memcached
--
CREATE TABLE /*$wgDBprefix*/objectcache (
- keyname char(255) binary not null default '',
+ keyname char(255) binary NOT NULL default '',
value mediumblob,
exptime datetime,
- unique key (keyname),
- key (exptime)
+ UNIQUE KEY (keyname),
+ KEY (exptime)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
--
-- Cache of interwiki transclusion
--
CREATE TABLE /*$wgDBprefix*/transcache (
- tc_url VARCHAR(255) NOT NULL,
- tc_contents TEXT,
- tc_time INT NOT NULL,
- UNIQUE INDEX tc_url_idx(tc_url)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+ tc_url varchar(255) NOT NULL,
+ tc_contents text,
+ tc_time int NOT NULL,
+ UNIQUE INDEX tc_url_idx (tc_url)
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
CREATE TABLE /*$wgDBprefix*/logging (
-- Symbolic keys for the general log type and the action type
@@ -968,24 +992,25 @@ CREATE TABLE /*$wgDBprefix*/logging (
log_comment varchar(255) NOT NULL default '',
-- LF separated list of miscellaneous parameters
- log_params blob NOT NULL default '',
+ log_params blob NOT NULL,
KEY type_time (log_type, log_timestamp),
KEY user_time (log_user, log_timestamp),
KEY page_time (log_namespace, log_title, log_timestamp)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
CREATE TABLE /*$wgDBprefix*/trackbacks (
- tb_id integer AUTO_INCREMENT PRIMARY KEY,
- tb_page integer REFERENCES page(page_id) ON DELETE CASCADE,
- tb_title varchar(255) NOT NULL,
- tb_url varchar(255) NOT NULL,
- tb_ex text,
- tb_name varchar(255),
-
- INDEX (tb_page)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+ tb_id int auto_increment,
+ tb_page int REFERENCES page(page_id) ON DELETE CASCADE,
+ tb_title varchar(255) NOT NULL,
+ tb_url varchar(255) NOT NULL,
+ tb_ex text,
+ tb_name varchar(255),
+
+ PRIMARY KEY (tb_id),
+ INDEX (tb_page)
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
-- Jobs performed by parallel apache threads or a command-line daemon
CREATE TABLE /*$wgDBprefix*/job (
@@ -1001,22 +1026,61 @@ CREATE TABLE /*$wgDBprefix*/job (
-- Any other parameters to the command
-- Presently unused, format undefined
- job_params blob NOT NULL default '',
+ job_params blob NOT NULL,
PRIMARY KEY job_id (job_id),
KEY (job_cmd, job_namespace, job_title)
-) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
-- Details of updates to cached special pages
CREATE TABLE /*$wgDBprefix*/querycache_info (
- -- Special page name
- -- Corresponds to a qc_type value
- qci_type varchar(32) NOT NULL default '',
+ -- Special page name
+ -- Corresponds to a qc_type value
+ qci_type varchar(32) NOT NULL default '',
+
+ -- Timestamp of last update
+ qci_timestamp char(14) NOT NULL default '19700101000000',
+
+ UNIQUE KEY ( qci_type )
+
+) ENGINE=InnoDB;
+
+-- For each redirect, this table contains exactly one row defining its target
+CREATE TABLE /*$wgDBprefix*/redirect (
+ -- Key to the page_id of the redirect page
+ rd_from int(8) unsigned NOT NULL default '0',
+
+ -- Key to page_namespace/page_title of the target page.
+ -- The target page may or may not exist, and due to renames
+ -- and deletions may refer to different page records as time
+ -- goes by.
+ rd_namespace int NOT NULL default '0',
+ rd_title varchar(255) binary NOT NULL default '',
+
+ PRIMARY KEY rd_from (rd_from),
+ KEY rd_ns_title (rd_namespace,rd_title,rd_from)
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
- -- Timestamp of last update
- qci_timestamp char(14) NOT NULL default '19700101000000',
+-- Used for caching expensive grouped queries that need two links (for example double-redirects)
- UNIQUE KEY ( qci_type )
+CREATE TABLE /*$wgDBprefix*/querycachetwo (
+ -- A key name, generally the base name of of the special page.
+ qcc_type char(32) NOT NULL,
+
+ -- Some sort of stored value. Sizes, counts...
+ qcc_value int(5) unsigned NOT NULL default '0',
+
+ -- Target namespace+title
+ qcc_namespace int NOT NULL default '0',
+ qcc_title char(255) binary NOT NULL default '',
+
+ -- Target namespace+title2
+ qcc_namespacetwo int NOT NULL default '0',
+ qcc_titletwo char(255) binary NOT NULL default '',
+
+ KEY qcc_type (qcc_type,qcc_value),
+ KEY qcc_title (qcc_type,qcc_namespace,qcc_title),
+ KEY qcc_titletwo (qcc_type,qcc_namespacetwo,qcc_titletwo)
-) TYPE=InnoDB;
+) ENGINE=InnoDB, DEFAULT CHARSET=utf8;
diff --git a/maintenance/namespace2sql.php b/maintenance/namespace2sql.php
index 8084bfec..081f6099 100644
--- a/maintenance/namespace2sql.php
+++ b/maintenance/namespace2sql.php
@@ -6,8 +6,8 @@
require_once( "commandLine.inc" );
for ($i = -2; $i < 16; ++$i) {
- $nsname = wfStrencode( $wgLang->getNsText( $i ) );
- $dbname = wfStrencode( $wgDBname );
+ $nsname = mysql_escape_string( $wgLang->getNsText( $i ) );
+ $dbname = mysql_escape_string( $wgDBname );
print "INSERT INTO ns_name(ns_db, ns_num, ns_name) VALUES('$dbname', $i, '$nsname');\n";
}
diff --git a/maintenance/oracle/tables.sql b/maintenance/oracle/tables.sql
index 6733f950..030f427f 100644
--- a/maintenance/oracle/tables.sql
+++ b/maintenance/oracle/tables.sql
@@ -109,14 +109,14 @@ CREATE TABLE pagelinks (
pl_title VARCHAR2(255) NOT NULL
);
CREATE UNIQUE INDEX pl_from ON pagelinks(pl_from, pl_namespace, pl_title);
-CREATE INDEX pl_namespace ON pagelinks(pl_namespace, pl_title);
+CREATE INDEX pl_namespace ON pagelinks(pl_namespace, pl_title, pl_from);
CREATE TABLE imagelinks (
il_from NUMBER(8) NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
il_to VARCHAR2(255) NOT NULL
);
CREATE UNIQUE INDEX il_from ON imagelinks(il_from, il_to);
-CREATE INDEX il_to ON imagelinks(il_to);
+CREATE INDEX il_to ON imagelinks(il_to, il_from);
CREATE TABLE categorylinks (
cl_from NUMBER(8) NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
@@ -229,6 +229,8 @@ CREATE TABLE recentchanges (
rc_moved_to_title VARCHAR2(255),
rc_patrolled NUMBER(3) DEFAULT 0 NOT NULL,
rc_ip VARCHAR2(40),
+ rc_old_len NUMBER(10) DEFAULT 0,
+ rc_new_len NUMBER(10) DEFAULT 0,
CONSTRAINT rc_pk PRIMARY KEY (rc_id)
);
CREATE INDEX rc_timestamp ON recentchanges (rc_timestamp);
diff --git a/maintenance/ourusers.php b/maintenance/ourusers.php
index b50519d2..9b7af605 100644
--- a/maintenance/ourusers.php
+++ b/maintenance/ourusers.php
@@ -59,28 +59,6 @@ foreach( $hosts as $host ) {
print "GRANT SELECT, INSERT, UPDATE, DELETE ON `$db`.* TO 'wikiuser'@'$host' IDENTIFIED BY '$wikiuser_pass';\n";
}
-/*
- print "\n-- wikisql\n\n";
- foreach ( $databases as $db ) {
-print <<<EOS
-GRANT SELECT ON `$db`.`old` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`imagelinks` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`image` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`watchlist` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`site_stats` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`archive` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`links` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`ipblocks` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`cur` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT (user_rights, user_id, user_name, user_options) ON `$db`.`user` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`oldimage` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`recentchanges` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`math` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-GRANT SELECT ON `$db`.`brokenlinks` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
-
-EOS;
- }*/
-
print "\n-- wikiadmin\n\n";
print "GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'wikiadmin'@'$host' IDENTIFIED BY '$wikiadmin_pass';\n";
print "GRANT ALL PRIVILEGES ON `boardvote%`.* TO wikiadmin@'$host' IDENTIFIED BY '$wikiadmin_pass';\n";
diff --git a/maintenance/parserTests.inc b/maintenance/parserTests.inc
index 0aabd27b..c85220d0 100644
--- a/maintenance/parserTests.inc
+++ b/maintenance/parserTests.inc
@@ -25,7 +25,7 @@
*/
/** */
-$options = array( 'quick', 'color', 'quiet', 'help' );
+$options = array( 'quick', 'color', 'quiet', 'help', 'show-output', 'record' );
$optionsWithArgs = array( 'regex' );
require_once( 'commandLine.inc' );
@@ -54,6 +54,11 @@ class ParserTest {
var $lightcolor;
/**
+ * boolean $showOutput Show test output
+ */
+ var $showOutput;
+
+ /**
* Sets terminal colorization and diff/quick modes depending on OS and
* command-line options (--color and --quick).
*
@@ -80,10 +85,14 @@ class ParserTest {
break;
}
}
+ $this->term = $this->color
+ ? new AnsiTermColorer( $this->lightcolor )
+ : new DummyTermColorer();
$this->showDiffs = !isset( $options['quick'] );
-
$this->quiet = isset( $options['quiet'] );
+ $this->showOutput = isset( $options['show-output'] );
+
if (isset($options['regex'])) {
$this->regex = $options['regex'];
@@ -92,7 +101,14 @@ class ParserTest {
$this->regex = '';
}
+ if( isset( $options['record'] ) ) {
+ $this->recorder = new DbTestRecorder( $this->term );
+ } else {
+ $this->recorder = new TestRecorder( $this->term );
+ }
+
$this->hooks = array();
+ $this->functionHooks = array();
}
/**
@@ -109,38 +125,53 @@ class ParserTest {
}
/**
- * Run a series of tests listed in the given text file.
+ * Run a series of tests listed in the given text files.
* Each test consists of a brief description, wikitext input,
* and the expected HTML output.
*
* Prints status updates on stdout and counts up the total
* number and percentage of passed tests.
*
- * @param string $filename
+ * @param array of strings $filenames
* @return bool True if passed all tests, false if any tests failed.
* @public
*/
- function runTestsFromFile( $filename ) {
+ function runTestsFromFiles( $filenames ) {
+ $this->recorder->start();
+ $ok = true;
+ foreach( $filenames as $filename ) {
+ $ok = $this->runFile( $filename ) && $ok;
+ }
+ $this->recorder->end();
+ $this->recorder->report();
+ return $ok;
+ }
+
+ private function runFile( $filename ) {
$infile = fopen( $filename, 'rt' );
if( !$infile ) {
wfDie( "Couldn't open $filename\n" );
+ } else {
+ print $this->term->color( 1 ) .
+ "Reading tests from \"$filename\"..." .
+ $this->term->reset() .
+ "\n";
}
$data = array();
$section = null;
- $success = 0;
- $total = 0;
$n = 0;
+ $ok = true;
while( false !== ($line = fgets( $infile ) ) ) {
$n++;
if( preg_match( '/^!!\s*(\w+)/', $line, $matches ) ) {
$section = strtolower( $matches[1] );
if( $section == 'endarticle') {
if( !isset( $data['text'] ) ) {
- wfDie( "'endarticle' without 'text' at line $n\n" );
+ wfDie( "'endarticle' without 'text' at line $n of $filename\n" );
}
if( !isset( $data['article'] ) ) {
- wfDie( "'endarticle' without 'article' at line $n\n" );
+ wfDie( "'endarticle' without 'article' at line $n of $filename\n" );
}
$this->addArticle($this->chomp($data['article']), $this->chomp($data['text']), $n);
$data = array();
@@ -149,7 +180,7 @@ class ParserTest {
}
if( $section == 'endhooks' ) {
if( !isset( $data['hooks'] ) ) {
- wfDie( "'endhooks' without 'hooks' at line $n\n" );
+ wfDie( "'endhooks' without 'hooks' at line $n of $filename\n" );
}
foreach( explode( "\n", $data['hooks'] ) as $line ) {
$line = trim( $line );
@@ -161,15 +192,29 @@ class ParserTest {
$section = null;
continue;
}
+ if( $section == 'endfunctionhooks' ) {
+ if( !isset( $data['functionhooks'] ) ) {
+ wfDie( "'endfunctionhooks' without 'functionhooks' at line $n of $filename\n" );
+ }
+ foreach( explode( "\n", $data['functionhooks'] ) as $line ) {
+ $line = trim( $line );
+ if( $line ) {
+ $this->requireFunctionHook( $line );
+ }
+ }
+ $data = array();
+ $section = null;
+ continue;
+ }
if( $section == 'end' ) {
if( !isset( $data['test'] ) ) {
- wfDie( "'end' without 'test' at line $n\n" );
+ wfDie( "'end' without 'test' at line $n of $filename\n" );
}
if( !isset( $data['input'] ) ) {
- wfDie( "'end' without 'input' at line $n\n" );
+ wfDie( "'end' without 'input' at line $n of $filename\n" );
}
if( !isset( $data['result'] ) ) {
- wfDie( "'end' without 'result' at line $n\n" );
+ wfDie( "'end' without 'result' at line $n of $filename\n" );
}
if( !isset( $data['options'] ) ) {
$data['options'] = '';
@@ -184,20 +229,19 @@ class ParserTest {
$section = null;
continue;
}
- if( $this->runTest(
+ $result = $this->runTest(
$this->chomp( $data['test'] ),
$this->chomp( $data['input'] ),
$this->chomp( $data['result'] ),
- $this->chomp( $data['options'] ) ) ) {
- $success++;
- }
- $total++;
+ $this->chomp( $data['options'] ) );
+ $ok = $ok && $result;
+ $this->recorder->record( $this->chomp( $data['test'] ), $result );
$data = array();
$section = null;
continue;
}
if ( isset ($data[$section] ) ) {
- wfDie( "duplicate section '$section' at line $n\n" );
+ wfDie( "duplicate section '$section' at line $n of $filename\n" );
}
$data[$section] = '';
continue;
@@ -206,19 +250,8 @@ class ParserTest {
$data[$section] .= $line;
}
}
- if( $total > 0 ) {
- $ratio = wfPercent( 100 * $success / $total );
- print $this->termColor( 1 ) . "\nPassed $success of $total tests ($ratio) ";
- if( $success == $total ) {
- print $this->termColor( 32 ) . "PASSED!";
- } else {
- print $this->termColor( 31 ) . "FAILED!";
- }
- print $this->termReset() . "\n";
- return ($success == $total);
- } else {
- wfDie( "No tests found.\n" );
- }
+ print "\n";
+ return $ok;
}
/**
@@ -258,6 +291,9 @@ class ParserTest {
foreach( $this->hooks as $tag => $callback ) {
$parser->setHook( $tag, $callback );
}
+ foreach( $this->functionHooks as $tag => $callback ) {
+ $parser->setFunctionHook( $tag, $callback );
+ }
wfRunHooks( 'ParserTestParser', array( &$parser ) );
$title =& Title::makeTitle( NS_MAIN, $titleText );
@@ -320,6 +356,12 @@ class ParserTest {
$lang = 'en';
}
+ if( preg_match( '/variant=([a-z]+(?:-[a-z]+)?)/', $opts, $m ) )
+ $variant = $m[1];
+ else
+ $variant = false;
+
+
$settings = array(
'wgServer' => 'http://localhost',
'wgScript' => '/index.php',
@@ -334,7 +376,7 @@ class ParserTest {
'wgLanguageCode' => $lang,
'wgContLanguageCode' => $lang,
'wgDBprefix' => 'parsertest_',
-
+ 'wgRawHtml' => preg_match('/\\brawhtml\\b/i', $opts),
'wgLang' => null,
'wgContLang' => null,
'wgNamespacesWithSubpages' => array( 0 => preg_match('/\\bsubpage\\b/i', $opts)),
@@ -345,6 +387,9 @@ class ParserTest {
'wgUseTeX' => false,
'wgLocaltimezone' => 'UTC',
'wgAllowExternalImages' => true,
+ 'wgUseTidy' => false,
+ 'wgDefaultLanguageVariant' => $variant,
+ 'wgVariantArticlePath' => false,
);
$this->savedGlobals = array();
foreach( $settings as $var => $val ) {
@@ -374,7 +419,8 @@ class ParserTest {
'recentchanges',
'watchlist', 'math', 'searchindex',
'interwiki', 'querycache',
- 'objectcache', 'job'
+ 'objectcache', 'job', 'redirect',
+ 'querycachetwo'
);
// FIXME manually adding additional table for the tasks extension
@@ -477,6 +523,7 @@ class ParserTest {
'img_media_type' => MEDIATYPE_BITMAP,
'img_major_mime' => "image",
'img_minor_mime' => "jpeg",
+ 'img_metadata' => serialize( array() ),
) );
# Update certain things in site_stats
@@ -532,22 +579,57 @@ class ParserTest {
* @private
*/
function teardownUploadDir( $dir ) {
- unlink( "$dir/3/3a/Foobar.jpg" );
- rmdir( "$dir/3/3a" );
- rmdir( "$dir/3" );
- @rmdir( "$dir/thumb/6/65" );
- @rmdir( "$dir/thumb/6" );
-
- @unlink( "$dir/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" );
- @rmdir( "$dir/thumb/3/3a/Foobar.jpg" );
- @rmdir( "$dir/thumb/3/3a" );
- @rmdir( "$dir/thumb/3/39" ); # wtf?
- @rmdir( "$dir/thumb/3" );
- @rmdir( "$dir/thumb" );
- @rmdir( "$dir" );
+ // delete the files first, then the dirs.
+ self::deleteFiles(
+ array (
+ "$dir/3/3a/Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/640px-Foobar.jpg",
+ "$dir/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg",
+ )
+ );
+
+ self::deleteDirs(
+ array (
+ "$dir/3/3a",
+ "$dir/3",
+ "$dir/thumb/6/65",
+ "$dir/thumb/6",
+ "$dir/thumb/3/3a/Foobar.jpg",
+ "$dir/thumb/3/3a",
+ "$dir/thumb/3",
+ "$dir/thumb",
+ "$dir",
+ )
+ );
}
/**
+ * @desc delete the specified files, if they exist.
+ * @param array $files full paths to files to delete.
+ */
+ private static function deleteFiles( $files ) {
+ foreach( $files as $file ) {
+ if( file_exists( $file ) ) {
+ unlink( $file );
+ }
+ }
+ }
+
+ /**
+ * @desc delete the specified directories, if they exist. Must be empty.
+ * @param array $dirs full paths to directories to delete.
+ */
+ private static function deleteDirs( $dirs ) {
+ foreach( $dirs as $dir ) {
+ if( is_dir( $dir ) ) {
+ rmdir( $dir );
+ }
+ }
+ }
+
+ /**
* "Running test $desc..."
* @private
*/
@@ -564,7 +646,7 @@ class ParserTest {
*/
function showSuccess( $desc ) {
if( !$this->quiet ) {
- print $this->termColor( '1;32' ) . 'PASSED' . $this->termReset() . "\n";
+ print $this->term->color( '1;32' ) . 'PASSED' . $this->term->reset() . "\n";
}
return true;
}
@@ -585,7 +667,10 @@ class ParserTest {
# test, in case it succeeded. Show it now:
$this->showTesting( $desc );
}
- print $this->termColor( '1;31' ) . 'FAILED!' . $this->termReset() . "\n";
+ print $this->term->color( '1;31' ) . 'FAILED!' . $this->term->reset() . "\n";
+ if ( $this->showOutput ) {
+ print "--- Expected ---\n$result\n--- Actual ---\n$html\n";
+ }
if( $this->showDiffs ) {
print $this->quickDiff( $result, $html );
if( !$this->wellFormed( $html ) ) {
@@ -636,33 +721,6 @@ class ParserTest {
}
/**
- * Return ANSI terminal escape code for changing text attribs/color,
- * or empty string if color output is disabled.
- *
- * @param string $color Semicolon-separated list of attribute/color codes
- * @return string
- * @private
- */
- function termColor( $color ) {
- if($this->lightcolor) {
- return $this->color ? "\x1b[1;{$color}m" : '';
- } else {
- return $this->color ? "\x1b[{$color}m" : '';
- }
- }
-
- /**
- * Return ANSI terminal escape code for restoring default text attributes,
- * or empty string if color output is disabled.
- *
- * @return string
- * @private
- */
- function termReset() {
- return $this->color ? "\x1b[0m" : '';
- }
-
- /**
* Colorize unified diff output if set for ANSI color output.
* Subtractions are colored blue, additions red.
*
@@ -673,8 +731,8 @@ class ParserTest {
function colorDiff( $text ) {
return preg_replace(
array( '/^(-.*)$/m', '/^(\+.*)$/m' ),
- array( $this->termColor( 34 ) . '$1' . $this->termReset(),
- $this->termColor( 31 ) . '$1' . $this->termReset() ),
+ array( $this->term->color( 34 ) . '$1' . $this->term->reset(),
+ $this->term->color( 31 ) . '$1' . $this->term->reset() ),
$text );
}
@@ -717,6 +775,22 @@ class ParserTest {
}
}
+
+ /**
+ * Steal a callback function from the primary parser, save it for
+ * application to our scary parser. If the hook is not installed,
+ * die a painful dead to warn the others.
+ * @param string $name
+ */
+ private function requireFunctionHook( $name ) {
+ global $wgParser;
+ if( isset( $wgParser->mFunctionHooks[$name] ) ) {
+ $this->functionHooks[$name] = $wgParser->mFunctionHooks[$name];
+ } else {
+ wfDie( "This test suite requires the '$name' function hook extension.\n" );
+ }
+ }
+
/*
* Run the "tidy" command on text if the $wgUseTidy
* global is true
@@ -762,25 +836,241 @@ class ParserTest {
$start = max( 0, $position - 10 );
$before = $position - $start;
$fragment = '...' .
- $this->termColor( 34 ) .
+ $this->term->color( 34 ) .
substr( $text, $start, $before ) .
- $this->termColor( 0 ) .
- $this->termColor( 31 ) .
- $this->termColor( 1 ) .
+ $this->term->color( 0 ) .
+ $this->term->color( 31 ) .
+ $this->term->color( 1 ) .
substr( $text, $position, 1 ) .
- $this->termColor( 0 ) .
- $this->termColor( 34 ) .
+ $this->term->color( 0 ) .
+ $this->term->color( 34 ) .
substr( $text, $position + 1, 9 ) .
- $this->termColor( 0 ) .
+ $this->term->color( 0 ) .
'...';
$display = str_replace( "\n", ' ', $fragment );
$caret = ' ' .
str_repeat( ' ', $before ) .
- $this->termColor( 31 ) .
+ $this->term->color( 31 ) .
'^' .
- $this->termColor( 0 );
+ $this->term->color( 0 );
return "$display\n$caret";
}
+
+}
+
+class AnsiTermColorer {
+ function __construct( $light ) {
+ $this->light = $light;
+ }
+
+ /**
+ * Return ANSI terminal escape code for changing text attribs/color
+ *
+ * @param string $color Semicolon-separated list of attribute/color codes
+ * @return string
+ * @private
+ */
+ function color( $color ) {
+ $light = $this->light ? "1;" : "";
+ return "\x1b[{$light}{$color}m";
+ }
+
+ /**
+ * Return ANSI terminal escape code for restoring default text attributes
+ *
+ * @return string
+ * @private
+ */
+ function reset() {
+ return "\x1b[0m";
+ }
+}
+
+/* A colour-less terminal */
+class DummyTermColorer {
+ function color( $color ) {
+ return '';
+ }
+
+ function reset() {
+ return '';
+ }
+}
+
+class TestRecorder {
+ function __construct( $term ) {
+ $this->term = $term;
+ }
+
+ function start() {
+ $this->total = 0;
+ $this->success = 0;
+ }
+
+ function record( $test, $result ) {
+ $this->total++;
+ $this->success += ($result ? 1 : 0);
+ }
+
+ function end() {
+ // dummy
+ }
+
+ function report() {
+ if( $this->total > 0 ) {
+ $this->reportPercentage( $this->success, $this->total );
+ } else {
+ wfDie( "No tests found.\n" );
+ }
+ }
+
+ function reportPercentage( $success, $total ) {
+ $ratio = wfPercent( 100 * $success / $total );
+ print $this->term->color( 1 ) . "Passed $success of $total tests ($ratio)... ";
+ if( $success == $total ) {
+ print $this->term->color( 32 ) . "PASSED!";
+ } else {
+ print $this->term->color( 31 ) . "FAILED!";
+ }
+ print $this->term->reset() . "\n";
+ return ($success == $total);
+ }
+}
+
+class DbTestRecorder extends TestRecorder {
+ private $db; ///< Database connection to the main DB
+ private $curRun; ///< run ID number for the current run
+ private $prevRun; ///< run ID number for the previous run, if any
+
+ function __construct( $term ) {
+ parent::__construct( $term );
+ $this->db = wfGetDB( DB_MASTER );
+ }
+
+ /**
+ * Set up result recording; insert a record for the run with the date
+ * and all that fun stuff
+ */
+ function start() {
+ parent::start();
+
+ $this->db->begin();
+
+ // We'll make comparisons against the previous run later...
+ $this->prevRun = $this->db->selectField( 'testrun', 'MAX(tr_id)' );
+
+ $this->db->insert( 'testrun',
+ array(
+ 'tr_date' => $this->db->timestamp(),
+ 'tr_mw_version' => SpecialVersion::getVersion(),
+ 'tr_php_version' => phpversion(),
+ 'tr_db_version' => $this->db->getServerVersion(),
+ 'tr_uname' => php_uname()
+ ),
+ __METHOD__ );
+ $this->curRun = $this->db->insertId();
+ }
+
+ /**
+ * Record an individual test item's success or failure to the db
+ * @param string $test
+ * @param bool $result
+ */
+ function record( $test, $result ) {
+ parent::record( $test, $result );
+ $this->db->insert( 'testitem',
+ array(
+ 'ti_run' => $this->curRun,
+ 'ti_name' => $test,
+ 'ti_success' => $result ? 1 : 0,
+ ),
+ __METHOD__ );
+ }
+
+ /**
+ * Commit transaction and clean up for result recording
+ */
+ function end() {
+ $this->db->commit();
+ parent::end();
+ }
+
+ function report() {
+ if( $this->prevRun ) {
+ $table = array(
+ array( 'previously failing test(s) now PASSING! :)', 0, 1 ),
+ array( 'previously PASSING test(s) removed o_O', 1, null ),
+ array( 'new PASSING test(s) :)', null, 1 ),
+
+ array( 'previously passing test(s) now FAILING! :(', 1, 0 ),
+ array( 'previously FAILING test(s) removed O_o', 0, null ),
+ array( 'new FAILING test(s) :(', null, 0 ),
+ );
+ foreach( $table as $criteria ) {
+ list( $label, $before, $after ) = $criteria;
+ $differences = $this->compareResult( $before, $after );
+ if( $differences ) {
+ $count = count($differences);
+ printf( "%4d %s\n", $count, $label );
+ foreach ($differences as $differing_test_name) {
+ print " * $differing_test_name\n";
+ }
+ }
+ }
+ } else {
+ print "No previous test runs to compare against.\n";
+ }
+ parent::report();
+ }
+
+ /**
+ ** @desc: Returns an array of the test names with changed results, based on the specified
+ ** before/after criteria.
+ */
+ private function compareResult( $before, $after ) {
+ $testitem = $this->db->tableName( 'testitem' );
+ $prevRun = intval( $this->prevRun );
+ $curRun = intval( $this->curRun );
+ $prevStatus = $this->condition( $before );
+ $curStatus = $this->condition( $after );
+
+ // note: requires mysql >= ver 4.1 for subselects
+ if( is_null( $after ) ) {
+ $sql = "
+ select prev.ti_name as t from $testitem as prev
+ where prev.ti_run=$prevRun and
+ prev.ti_success $prevStatus and
+ (select current.ti_success from $testitem as current
+ where current.ti_run=$curRun
+ and prev.ti_name=current.ti_name) $curStatus";
+ } else {
+ $sql = "
+ select current.ti_name as t from $testitem as current
+ where current.ti_run=$curRun and
+ current.ti_success $curStatus and
+ (select prev.ti_success from $testitem as prev
+ where prev.ti_run=$prevRun
+ and prev.ti_name=current.ti_name) $prevStatus";
+ }
+ $result = $this->db->query( $sql, __METHOD__ );
+ $retval = array();
+ while ($row = $this->db->fetchObject( $result )) {
+ $retval[] = $row->t;
+ }
+ $this->db->freeResult( $result );
+ return $retval;
+ }
+
+ /**
+ ** @desc: Helper function for compareResult() database querying.
+ */
+ private function condition( $value ) {
+ if( is_null( $value ) ) {
+ return 'IS NULL';
+ } else {
+ return '=' . intval( $value );
+ }
+ }
}
diff --git a/maintenance/parserTests.php b/maintenance/parserTests.php
index 309bf2e0..bd147788 100644
--- a/maintenance/parserTests.php
+++ b/maintenance/parserTests.php
@@ -26,22 +26,24 @@
require('parserTests.inc');
if( isset( $options['help'] ) ) {
- echo <<<END
+ echo <<<ENDS
MediaWiki $wgVersion parser test suite
-Usage: php parserTests.php [--quick] [--quiet] [--color[=(yes|no|light)]]
+Usage: php parserTests.php [--quick] [--quiet] [--show-output]
+ [--color[=(yes|no|light)]]
[--regex=<expression>] [--file=<testfile>]
[--help]
Options:
- --quick Suppress diff output of failed tests
- --quiet Suppress notification of passed tests (shows only failed tests)
- --color Override terminal detection and force color output on or off
- 'light' option is similar to 'yes' but with color for dark backgrounds
- --regex Only run tests whose descriptions which match given regex
- --file Run test cases from a custom file instead of parserTests.txt
- --help Show this help message
+ --quick Suppress diff output of failed tests
+ --quiet Suppress notification of passed tests (shows only failed tests)
+ --show-output Show expected and actual output
+ --color Override terminal detection and force color output on or off
+ 'light' option is similar to 'yes' but with color for dark backgrounds
+ --regex Only run tests whose descriptions which match given regex
+ --file Run test cases from a custom file instead of parserTests.txt
+ --help Show this help message
-END;
+ENDS;
exit( 0 );
}
@@ -52,13 +54,16 @@ $wgTitle = Title::newFromText( 'Parser test script do not use' );
$tester = new ParserTest();
if( isset( $options['file'] ) ) {
- $file = $options['file'];
+ $files = array( $options['file'] );
} else {
- # Note: the command line setup changes the current working directory
- # to the parent, which is why we have to put the subdir here:
- $file = $IP.'/maintenance/parserTests.txt';
+ // Default parser tests and any set from extensions or local config
+ $files = $wgParserTestFiles;
}
-$ok = $tester->runTestsFromFile( $file );
+
+# Print out software version to assist with locating regressions
+$version = SpecialVersion::getVersion();
+echo( "This is MediaWiki version {$version}.\n" );
+$ok = $tester->runTestsFromFiles( $files );
exit ($ok ? 0 : -1);
?>
diff --git a/maintenance/parserTests.txt b/maintenance/parserTests.txt
index 66b46a53..3d748aef 100644
--- a/maintenance/parserTests.txt
+++ b/maintenance/parserTests.txt
@@ -18,7 +18,8 @@
# subpage enable subpages (disabled by default)
# noxml don't check for XML well formdness
# title=[[XXX]] run test using article title XXX
-# language=XXX set content language to XXX for this test
+# language=XXX set content language to XXX for this test
+# variant=XXX set the variant of language for this test (eg zh-tw)
# disabled do not run test
#
# For testing purposes, temporary articles can created:
@@ -377,7 +378,7 @@ Simple definition
!! end
!! test
-Simple definition
+Definition list for indentation only
!! input
: Indented text
!! result
@@ -428,7 +429,7 @@ Definition list with wikilink containing colon
# At Brion's and JeLuF's insistence... :)
!! test
-Definition list with wikilink containing colon
+Definition list with news link containing colon
!! input
; news:alt.wikipedia.rox: This isn't even a real newsgroup!
!! result
@@ -2170,12 +2171,12 @@ Template with complex template as argument
!! end
!! test
-TODO: Template with thumb image (with link in description)
+Template with thumb image (with link in description)
!! input
{{paramtest|
param =[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]}}
!! result
-This is a test template with parameter <div class="thumb tright"><div style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Noimage.png" class="new" title="Image:Noimage.png">Image:Noimage.png</a> <div class="thumbcaption"><a href="/index.php?title=No_link&amp;action=edit" class="new" title="No link">link</a> <a href="/index.php?title=No_link&amp;action=edit" class="new" title="No link">caption</a></div></div></div>
+This is a test template with parameter <div class="thumb tright"><div class="thumbinner" style="width:122px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Noimage.png" class="new" title="Image:Noimage.png">Image:Noimage.png</a> <div class="thumbcaption"><a href="/index.php?title=No_link&amp;action=edit" class="new" title="No link">link</a> <a href="/index.php?title=No_link&amp;action=edit" class="new" title="No link">caption</a></div></div></div>
!! end
@@ -2284,7 +2285,7 @@ Template infinite loop
!! input
{{loop1}}
!! result
-<p>{{loop1}}<!-- WARNING: template loop detected -->
+<p><a href="/index.php?title=Loop1&amp;action=edit" class="new" title="Loop1">loop1</a><!-- WARNING: template loop detected -->
</p>
!! end
@@ -2826,6 +2827,25 @@ msg
Foo
!! end
+!! test
+{{#special:}} page name, known
+!! options
+msg
+!! input
+{{#special:Recentchanges}}
+!! result
+Special:Recentchanges
+!! end
+
+!! test
+{{#special:}} page name, unknown
+!! options
+msg
+!! input
+{{#special:foobarnonexistent}}
+!! result
+No such special page
+!! end
###
### Images
@@ -2862,7 +2882,7 @@ Image with frame and link
!! input
[[Image:Foobar.jpg|frame|left|This is a test image [[Main Page]]]]
!! result
-<div class="thumb tleft"><div style="width:1943px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This is a test image Main Page"><img src="http://example.com/images/3/3a/Foobar.jpg" alt="This is a test image Main Page" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a> <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div>
+<div class="thumb tleft"><div class="thumbinner" style="width:1943px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This is a test image Main Page"><img src="http://example.com/images/3/3a/Foobar.jpg" alt="This is a test image Main Page" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" /></a> <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div>
!! end
@@ -2891,16 +2911,16 @@ Thumbnail image caption with a free URL
!! input
[[Image:foobar.jpg|thumb|http://example.com]]
!! result
-<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="http://example.com"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="http://example.com" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div><a href="http://example.com" class="external free" title="http://example.com" rel="nofollow">http://example.com</a></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="http://example.com"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="http://example.com" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a href="http://example.com" class="external free" title="http://example.com" rel="nofollow">http://example.com</a></div></div></div>
!! end
!! test
BUG 1887: A ISBN with a thumbnail
!! input
-[[Image:foobar.jpg|thumb|ISBN 12354]]
+[[Image:foobar.jpg|thumb|ISBN 1235467890]]
!! result
-<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="ISBN 12354"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="ISBN 12354" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div><a href="/index.php?title=Special:Booksources&amp;isbn=12354" class="internal">ISBN 12354</a></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="ISBN 1235467890"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="ISBN 1235467890" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><a href="/index.php?title=Special:Booksources&amp;isbn=1235467890" class="internal">ISBN 1235467890</a></div></div></div>
!! end
@@ -2909,7 +2929,7 @@ BUG 1887: A RFC with a thumbnail
!! input
[[Image:foobar.jpg|thumb|This is RFC 12354]]
!! result
-<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This is RFC 12354"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="This is RFC 12354" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div>This is <a href="http://www.ietf.org/rfc/rfc12354.txt" class="external" title="http://www.ietf.org/rfc/rfc12354.txt">RFC 12354</a></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This is RFC 12354"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="This is RFC 12354" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is <a href="http://www.ietf.org/rfc/rfc12354.txt" class="external" title="http://www.ietf.org/rfc/rfc12354.txt">RFC 12354</a></div></div></div>
!! end
@@ -2918,7 +2938,7 @@ BUG 1887: A mailto link with a thumbnail
!! input
[[Image:foobar.jpg|thumb|Please mailto:nobody@example.com]]
!! result
-<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Please mailto:nobody@example.com"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="Please mailto:nobody@example.com" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div>Please <a href="mailto:nobody@example.com" class="external free" title="mailto:nobody@example.com" rel="nofollow">mailto:nobody@example.com</a></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Please mailto:nobody@example.com"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="Please mailto:nobody@example.com" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>Please <a href="mailto:nobody@example.com" class="external free" title="mailto:nobody@example.com" rel="nofollow">mailto:nobody@example.com</a></div></div></div>
!! end
@@ -2928,7 +2948,7 @@ so math is not stripped and turns up as escaped &lt;math&gt; tags.
!! input
[[Image:foobar.jpg|thumb|<math>2+2</math>]]
!! result
-<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="&lt;math&gt;2+2&lt;/math&gt;"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="&lt;math&gt;2+2&lt;/math&gt;" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div>&lt;math&gt;2+2&lt;/math&gt;</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="&lt;math&gt;2+2&lt;/math&gt;"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="&lt;math&gt;2+2&lt;/math&gt;" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>&lt;math&gt;2+2&lt;/math&gt;</div></div></div>
!! end
@@ -2939,7 +2959,7 @@ math
!! input
[[Image:foobar.jpg|thumb|<math>2+2</math>]]
!! result
-<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="2 + 2"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="2 + 2" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div><span class="texhtml">2 + 2</span></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="2 + 2"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="2 + 2" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div><span class="texhtml">2 + 2</span></div></div></div>
!! end
@@ -3012,7 +3032,7 @@ Image caption containing another image
!! input
[[Image:Foobar.jpg|thumb|This is a caption with another [[Image:icon.png|image]] inside it!]]
!! result
-<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This is a caption with another Image:Icon.png inside it!"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="This is a caption with another Image:Icon.png inside it!" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div>This is a caption with another <a href="/index.php?title=Special:Upload&amp;wpDestFile=Icon.png" class="new" title="Image:Icon.png">Image:Icon.png</a> inside it!</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This is a caption with another Image:Icon.png inside it!"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="This is a caption with another Image:Icon.png inside it!" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is a caption with another <a href="/index.php?title=Special:Upload&amp;wpDestFile=Icon.png" class="new" title="Image:Icon.png">Image:Icon.png</a> inside it!</div></div></div>
!! end
@@ -3032,7 +3052,7 @@ Bug 3090: External links other than http: in image captions
!! input
[[Image:Foobar.jpg|thumb|200px|This caption has [irc://example.net irc] and [https://example.com Secure] ext links in it.]]
!! result
-<div class="thumb tright"><div style="width:202px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This caption has irc and Secure ext links in it."><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" alt="This caption has irc and Secure ext links in it." width="200" height="23" longdesc="/wiki/Image:Foobar.jpg" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div>This caption has <a href="irc://example.net" class="external text" title="irc://example.net" rel="nofollow">irc</a> and <a href="https://example.com" class="external text" title="https://example.com" rel="nofollow">Secure</a> ext links in it.</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This caption has irc and Secure ext links in it."><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" alt="This caption has irc and Secure ext links in it." width="200" height="23" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This caption has <a href="irc://example.net" class="external text" title="irc://example.net" rel="nofollow">irc</a> and <a href="https://example.com" class="external text" title="https://example.com" rel="nofollow">Secure</a> ext links in it.</div></div></div>
!! end
@@ -3136,8 +3156,6 @@ es:Alimento fr:Nourriture zh:食品
###
!! test
Basic section headings
-!! options
-title=[[Parser test script]]
!! input
== Headline 1 ==
Some text
@@ -3147,21 +3165,19 @@ More
===Smaller headline===
Blah blah
!! result
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=1" title="Edit section: Headline 1">edit</a>]</div><a name="Headline_1"></a><h2> Headline 1 </h2>
+<a name="Headline_1"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Headline 1">edit</a>]</span> <span class="mw-headline"> Headline 1 </span></h2>
<p>Some text
</p>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=2" title="Edit section: Headline 2">edit</a>]</div><a name="Headline_2"></a><h2>Headline 2</h2>
+<a name="Headline_2"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Headline 2">edit</a>]</span> <span class="mw-headline">Headline 2</span></h2>
<p>More
</p>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=3" title="Edit section: Smaller headline">edit</a>]</div><a name="Smaller_headline"></a><h3>Smaller headline</h3>
+<a name="Smaller_headline"></a><h3><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Smaller headline">edit</a>]</span> <span class="mw-headline">Smaller headline</span></h3>
<p>Blah blah
</p>
!! end
!! test
Section headings with TOC
-!! options
-title=[[Parser test script]]
!! input
== Headline 1 ==
=== Subheadline 1 ===
@@ -3194,14 +3210,14 @@ Some text
</li>
</ul>
</td></tr></table><script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=1" title="Edit section: Headline 1">edit</a>]</div><a name="Headline_1"></a><h2> Headline 1 </h2>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=2" title="Edit section: Subheadline 1">edit</a>]</div><a name="Subheadline_1"></a><h3> Subheadline 1 </h3>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=3" title="Edit section: Skipping a level">edit</a>]</div><a name="Skipping_a_level"></a><h5> Skipping a level </h5>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=4" title="Edit section: Skipping a level">edit</a>]</div><a name="Skipping_a_level_2"></a><h6> Skipping a level </h6>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=5" title="Edit section: Headline 2">edit</a>]</div><a name="Headline_2"></a><h2> Headline 2 </h2>
+<a name="Headline_1"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Headline 1">edit</a>]</span> <span class="mw-headline"> Headline 1 </span></h2>
+<a name="Subheadline_1"></a><h3><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Subheadline 1">edit</a>]</span> <span class="mw-headline"> Subheadline 1 </span></h3>
+<a name="Skipping_a_level"></a><h5><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Skipping a level">edit</a>]</span> <span class="mw-headline"> Skipping a level </span></h5>
+<a name="Skipping_a_level_2"></a><h6><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=4" title="Edit section: Skipping a level">edit</a>]</span> <span class="mw-headline"> Skipping a level </span></h6>
+<a name="Headline_2"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=5" title="Edit section: Headline 2">edit</a>]</span> <span class="mw-headline"> Headline 2 </span></h2>
<p>Some text
</p>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=6" title="Edit section: Another headline">edit</a>]</div><a name="Another_headline"></a><h3>Another headline</h3>
+<a name="Another_headline"></a><h3><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=6" title="Edit section: Another headline">edit</a>]</span> <span class="mw-headline">Another headline</span></h3>
!! end
@@ -3249,29 +3265,27 @@ Handling of sections up to level 6 and beyond
</li>
</ul>
</td></tr></table><script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Level 1 Heading">edit</a>]</div><a name="Level_1_Heading"></a><h1> Level 1 Heading</h1>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Level 2 Heading">edit</a>]</div><a name="Level_2_Heading"></a><h2> Level 2 Heading</h2>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Level 3 Heading">edit</a>]</div><a name="Level_3_Heading"></a><h3> Level 3 Heading</h3>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=4" title="Edit section: Level 4 Heading">edit</a>]</div><a name="Level_4_Heading"></a><h4> Level 4 Heading</h4>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=5" title="Edit section: Level 5 Heading">edit</a>]</div><a name="Level_5_Heading"></a><h5> Level 5 Heading</h5>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=6" title="Edit section: Level 6 Heading">edit</a>]</div><a name="Level_6_Heading"></a><h6> Level 6 Heading</h6>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=7" title="Edit section: = Level 7 Heading=">edit</a>]</div><a name=".3D_Level_7_Heading.3D"></a><h6>= Level 7 Heading=</h6>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=8" title="Edit section: == Level 8 Heading==">edit</a>]</div><a name=".3D.3D_Level_8_Heading.3D.3D"></a><h6>== Level 8 Heading==</h6>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=9" title="Edit section: === Level 9 Heading===">edit</a>]</div><a name=".3D.3D.3D_Level_9_Heading.3D.3D.3D"></a><h6>=== Level 9 Heading===</h6>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=10" title="Edit section: ==== Level 10 Heading====">edit</a>]</div><a name=".3D.3D.3D.3D_Level_10_Heading.3D.3D.3D.3D"></a><h6>==== Level 10 Heading====</h6>
+<a name="Level_1_Heading"></a><h1><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Level 1 Heading">edit</a>]</span> <span class="mw-headline"> Level 1 Heading</span></h1>
+<a name="Level_2_Heading"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Level 2 Heading">edit</a>]</span> <span class="mw-headline"> Level 2 Heading</span></h2>
+<a name="Level_3_Heading"></a><h3><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Level 3 Heading">edit</a>]</span> <span class="mw-headline"> Level 3 Heading</span></h3>
+<a name="Level_4_Heading"></a><h4><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=4" title="Edit section: Level 4 Heading">edit</a>]</span> <span class="mw-headline"> Level 4 Heading</span></h4>
+<a name="Level_5_Heading"></a><h5><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=5" title="Edit section: Level 5 Heading">edit</a>]</span> <span class="mw-headline"> Level 5 Heading</span></h5>
+<a name="Level_6_Heading"></a><h6><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=6" title="Edit section: Level 6 Heading">edit</a>]</span> <span class="mw-headline"> Level 6 Heading</span></h6>
+<a name=".3D_Level_7_Heading.3D"></a><h6><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=7" title="Edit section: = Level 7 Heading=">edit</a>]</span> <span class="mw-headline">= Level 7 Heading=</span></h6>
+<a name=".3D.3D_Level_8_Heading.3D.3D"></a><h6><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=8" title="Edit section: == Level 8 Heading==">edit</a>]</span> <span class="mw-headline">== Level 8 Heading==</span></h6>
+<a name=".3D.3D.3D_Level_9_Heading.3D.3D.3D"></a><h6><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=9" title="Edit section: === Level 9 Heading===">edit</a>]</span> <span class="mw-headline">=== Level 9 Heading===</span></h6>
+<a name=".3D.3D.3D.3D_Level_10_Heading.3D.3D.3D.3D"></a><h6><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=10" title="Edit section: ==== Level 10 Heading====">edit</a>]</span> <span class="mw-headline">==== Level 10 Heading====</span></h6>
!! end
!! test
Resolving duplicate section names
-!! options
-title=[[Parser test script]]
!! input
== Foo bar ==
== Foo bar ==
!! result
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=1" title="Edit section: Foo bar">edit</a>]</div><a name="Foo_bar"></a><h2> Foo bar </h2>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=2" title="Edit section: Foo bar">edit</a>]</div><a name="Foo_bar_2"></a><h2> Foo bar </h2>
+<a name="Foo_bar"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Foo bar">edit</a>]</span> <span class="mw-headline"> Foo bar </span></h2>
+<a name="Foo_bar_2"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Foo bar">edit</a>]</span> <span class="mw-headline"> Foo bar </span></h2>
!! end
@@ -3284,18 +3298,16 @@ Template:sections
!! test
Template with sections, __NOTOC__
-!! options
-title=[[Parser test script]]
!! input
__NOTOC__
==Section 0==
{{sections}}
==Section 4==
!! result
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=1" title="Edit section: Section 0">edit</a>]</div><a name="Section_0"></a><h2>Section 0</h2>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Template:Sections&amp;action=edit&amp;section=1" title="Template:Sections">edit</a>]</div><a name="Section_1"></a><h3>Section 1</h3>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Template:Sections&amp;action=edit&amp;section=2" title="Template:Sections">edit</a>]</div><a name="Section_2"></a><h2>Section 2</h2>
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=2" title="Edit section: Section 4">edit</a>]</div><a name="Section_4"></a><h2>Section 4</h2>
+<a name="Section_0"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Section 0">edit</a>]</span> <span class="mw-headline">Section 0</span></h2>
+<a name="Section_1"></a><h3><span class="editsection">[<a href="/index.php?title=Template:Sections&amp;action=edit&amp;section=1" title="Template:Sections">edit</a>]</span> <span class="mw-headline">Section 1</span></h3>
+<a name="Section_2"></a><h2><span class="editsection">[<a href="/index.php?title=Template:Sections&amp;action=edit&amp;section=2" title="Template:Sections">edit</a>]</span> <span class="mw-headline">Section 2</span></h2>
+<a name="Section_4"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Section 4">edit</a>]</span> <span class="mw-headline">Section 4</span></h2>
!! end
@@ -3306,19 +3318,17 @@ __NOEDITSECTION__
==Section 1==
==Section 2==
!! result
-<a name="Section_1"></a><h2>Section 1</h2>
-<a name="Section_2"></a><h2>Section 2</h2>
+<a name="Section_1"></a><h2> <span class="mw-headline">Section 1</span></h2>
+<a name="Section_2"></a><h2> <span class="mw-headline">Section 2</span></h2>
!! end
!! test
Link inside a section heading
-!! options
-title=[[Parser test script]]
!! input
==Section with a [[Main Page|link]] in it==
!! result
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=1" title="Edit section: Section with a link in it">edit</a>]</div><a name="Section_with_a_link_in_it"></a><h2>Section with a <a href="/wiki/Main_Page" title="Main Page">link</a> in it</h2>
+<a name="Section_with_a_link_in_it"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Section with a link in it">edit</a>]</span> <span class="mw-headline">Section with a <a href="/wiki/Main_Page" title="Main Page">link</a> in it</span></h2>
!! end
@@ -3909,7 +3919,7 @@ Expansion of multi-line templates in attribute values (bug 6255 sanity check)
!! end
!! test
-Expansion of multi-line templates in attribute values (bug 6255 sanity check)
+Expansion of multi-line templates in attribute values (bug 6255 sanity check 2)
!! input
<div style="background: &#10;#00FF00">-</div>
!! result
@@ -4459,7 +4469,7 @@ Fuzz testing: Parser14
== onmouseover= ==
http://__TOC__
!! result
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: onmouseover=">edit</a>]</div><a name="onmouseover.3D"></a><h2> onmouseover= </h2>
+<a name="onmouseover.3D"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: onmouseover=">edit</a>]</span> <span class="mw-headline"> onmouseover= </span></h2>
http://<table id="toc" class="toc" summary="Contents"><tr><td><div id="toctitle"><h2>Contents</h2></div>
<ul>
<li class="toclevel-1"><a href="#onmouseover.3D"><span class="tocnumber">1</span> <span class="toctext">onmouseover=</span></a></li>
@@ -4474,7 +4484,7 @@ Fuzz testing: Parser14-table
==a==
{| STYLE=__TOC__
!! result
-<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: a">edit</a>]</div><a name="a"></a><h2>a</h2>
+<a name="a"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: a">edit</a>]</span> <span class="mw-headline">a</span></h2>
<table style="&#95;_TOC&#95;_">
<tr><td></td></tr>
</table>
@@ -4612,7 +4622,7 @@ Fuzz testing: image with bogus manual thumbnail
!!input
[[Image:foobar.jpg|thumbnail= ]]
!!result
-<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title=""><img src="http://example.com/images/3/3a/Foobar.jpg" alt="" width="180" height="-1" longdesc="/wiki/Image:Foobar.jpg" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div></div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title=""><img src="http://example.com/images/3/3a/Foobar.jpg" alt="" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div></div></div></div>
!!end
@@ -4750,6 +4760,42 @@ Special page transclusion twice (bug 5021)
!! end
!! test
+Transclusion of default MediaWiki message
+!! input
+{{MediaWiki:Mainpage}}
+!!result
+<p>Main Page
+</p>
+!! end
+
+!! test
+Transclusion of nonexistent MediaWiki message
+!! input
+{{MediaWiki:Mainpagexxx}}
+!!result
+<p><a href="/index.php?title=MediaWiki:Mainpagexxx&amp;action=edit" class="new" title="MediaWiki:Mainpagexxx">MediaWiki:Mainpagexxx</a>
+</p>
+!! end
+
+!! test
+Transclusion of MediaWiki message with underscore
+!! input
+{{MediaWiki:history_short}}
+!! result
+<p>History
+</p>
+!! end
+
+!! test
+Transclusion of MediaWiki message with space
+!! input
+{{MediaWiki:history short}}
+!! result
+<p>History
+</p>
+!! end
+
+!! test
Invalid header with following text
!! input
= x = y
@@ -5723,11 +5769,11 @@ image4 |300px| centre
!! end
!! test
-TODO: HTML Hex character encoding.
+HTML Hex character encoding (spells the word "JavaScript")
!! input
&#x4A;&#x061;&#x0076;&#x00061;&#x000053;&#x0000063;&#114;&#x0000069;&#00000112;&#x0000000074;
!! result
-<p>JavaScript
+<p>&#x4a;&#x61;&#x76;&#x61;&#x53;&#x63;&#114;&#x69;&#112;&#x74;
</p>
!! end
@@ -5744,9 +5790,9 @@ __FORCETOC__
!! test
ISBN code coverage
!! input
-ISBN 983&#x20;987
+ISBN 978-0-1234-56&#x20;789
!! result
-<p><a href="/index.php?title=Special:Booksources&amp;isbn=983" class="internal">ISBN 983</a>&#x20;987
+<p><a href="/index.php?title=Special:Booksources&amp;isbn=9780123456" class="internal">ISBN 978-0-1234-56</a>&#x20;789
</p>
!! end
@@ -5761,12 +5807,10 @@ ISBN
!! test
Double ISBN
-!! options
-disabled # Disabled until Bug 6560 resolved
!! input
-ISBN ISBN 1234
+ISBN ISBN 1234567890
!! result
-<p>ISBN <a href="/wiki/index.php?title=Special:Booksources&amp;isbn=1234" class="internal">ISBN 1234</a>
+<p>ISBN <a href="/index.php?title=Special:Booksources&amp;isbn=1234567890" class="internal">ISBN 1234567890</a>
</p>
!! end
@@ -5851,6 +5895,521 @@ TODO: dt/dd/dl test
!!end
+
+# Images with the "|" character in external URLs in comment tags; Eats half the comment, leaves unmatched "</a>" tag.
+!! test
+TODO: Images with the "|" character in the comment
+!! input
+[[image:Foobar.jpg|thumb|An [http://test/?param1=|left|&param2=|x external] URL]]
+!! result
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="An external URL"><img src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="An external URL" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>An <a href="http://test/?param1=|left|&amp;param2=|x" class="external text" title="http://test/?param1=|left|&amp;param2=|x" rel="nofollow">external</a> URL</div></div></div>
+
+!!end
+
+!! test
+[Before] HTML without raw HTML enabled ($wgRawHtml==false)
+!! input
+<html><script>alert(1);</script></html>
+!! result
+<p>&lt;html&gt;&lt;script&gt;alert(1);&lt;/script&gt;&lt;/html&gt;
+</p>
+!! end
+
+!! test
+HTML with raw HTML ($wgRawHtml==true)
+!! options
+rawhtml
+!! input
+<html><script>alert(1);</script></html>
+!! result
+<p><script>alert(1);</script>
+</p>
+!! end
+
+!! test
+Parents of subpages, one level up
+!! options
+subpage title=[[Subpage test/L1/L2/L3]]
+!! input
+[[../|L2]]
+!! result
+<p><a href="/index.php?title=Subpage_test/L1/L2&amp;action=edit" class="new" title="Subpage test/L1/L2">L2</a>
+</p>
+!! end
+
+
+!! test
+Parents of subpages, one level up, not named
+!! options
+subpage title=[[Subpage test/L1/L2/L3]]
+!! input
+[[../]]
+!! result
+<p><a href="/index.php?title=Subpage_test/L1/L2&amp;action=edit" class="new" title="Subpage test/L1/L2">Subpage test/L1/L2</a>
+</p>
+!! end
+
+
+
+!! test
+Parents of subpages, two levels up
+!! options
+disabled
+subpage title=[[Subpage test/L1/L2/L3]]
+!! input
+[[../../|L1]]2
+!! result
+<p><a href="/index.php?title=Subpage_test/L1&amp;action=edit" class="new" title="Subpage test/L1">L1</a>
+</p>
+!! end
+
+
+# Question: should result be "/index.php?title=Subpage_test/L1&amp;action=edit" instead?
+!! test
+TODO: Parents of subpages, two levels up, without trailing slash or name.
+!! options
+subpage title=[[Subpage test/L1/L2/L3]]
+!! input
+[[../..]]
+!! result
+<p><a href="/index.php?title=Subpage_test/L1/L2/..&amp;action=edit" class="new" title="Subpage test/L1">../..</a>
+</p>
+!! end
+
+# Question: Why should the link text in the above test be "../..", yet in this test the "../.." part is silently dropped?
+# Current result: <p><a href="/index.php?title=Subpage_test/L1////&amp;action=edit" class="new" title="Subpage test/L1////">///
+!! test
+TODO: Parents of subpages, two levels up, with lots of extra trailing slashes.
+!! options
+subpage title=[[Subpage test/L1/L2/L3]]
+!! input
+[[../../////]]
+!! result
+<p><a href="/index.php?title=Subpage_test/L1&amp;action=edit" class="new" title="Subpage test/L1">Subpage test/L1</a>
+</p>
+!! end
+
+!! test
+Definition list code coverage
+!! input
+; title : def
+; title : def
+;title: def
+!! result
+<dl><dt> title &nbsp;</dt><dd> def
+</dd><dt> title&nbsp;</dt><dd> def
+</dd><dt>title</dt><dd> def
+</dd></dl>
+
+!! end
+
+!! test
+TODO: Don't fall for the self-closing div
+!! input
+<div>hello world</div/>
+!! result
+<div>hello world</div>
+
+!! end
+
+!! test
+MSGNW magic word
+!! input
+{{MSGNW:msg}}
+!! result
+<p>&#91;&#91;:Template:Msg]]
+</p>
+!! end
+
+!! test
+RAW magic word
+!! input
+{{RAW:QUERTY}}
+!! result
+<p><a href="/index.php?title=Template:QUERTY&amp;action=edit" class="new" title="Template:QUERTY">Template:QUERTY</a>
+</p>
+!! end
+
+# This isn't needed for XHTML conformance, but would be handy as a fallback security measure
+!! test
+TODO: Always escape literal '>' in output, not just after '<'
+!! input
+><>
+!! result
+<p>&gt;&lt;&gt;
+</p>
+!! end
+
+!! test
+Template caching
+!! input
+{{Test}}
+{{Test}}
+!! result
+<p>This is a test template
+This is a test template
+</p>
+!! end
+
+
+!! article
+MediaWiki:Fake
+!! text
+==header==
+!! endarticle
+
+!! test
+Inclusion of !userCanEdit() content
+!! input
+{{MediaWiki:Fake}}
+!! result
+<a name="header"></a><h2><span class="editsection">[<a href="/index.php?title=MediaWiki:Fake&amp;action=edit&amp;section=1" title="MediaWiki:Fake">edit</a>]</span> <span class="mw-headline">header</span></h2>
+
+!! end
+
+
+!! test
+Out-of-order TOC heading levels
+!! input
+==2==
+======6======
+===3===
+=1=
+=====5=====
+==2==
+!! result
+<table id="toc" class="toc" summary="Contents"><tr><td><div id="toctitle"><h2>Contents</h2></div>
+<ul>
+<li class="toclevel-1"><a href="#2"><span class="tocnumber">1</span> <span class="toctext">2</span></a>
+<ul>
+<li class="toclevel-2"><a href="#6"><span class="tocnumber">1.1</span> <span class="toctext">6</span></a></li>
+<li class="toclevel-2"><a href="#3"><span class="tocnumber">1.2</span> <span class="toctext">3</span></a></li>
+</ul>
+</li>
+<li class="toclevel-1"><a href="#1_7"><span class="tocnumber">2</span> <span class="toctext">1</span></a>
+<ul>
+<li class="toclevel-2"><a href="#5"><span class="tocnumber">2.1</span> <span class="toctext">5</span></a></li>
+<li class="toclevel-2"><a href="#2_4"><span class="tocnumber">2.2</span> <span class="toctext">2</span></a></li>
+</ul>
+</li>
+</ul>
+</td></tr></table><script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script>
+<a name="2"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: 2">edit</a>]</span> <span class="mw-headline">2</span></h2>
+<a name="6"></a><h6><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: 6">edit</a>]</span> <span class="mw-headline">6</span></h6>
+<a name="3"></a><h3><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: 3">edit</a>]</span> <span class="mw-headline">3</span></h3>
+<a name="1_7"></a><h1><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=4" title="Edit section: 1">edit</a>]</span> <span class="mw-headline">1</span></h1>
+<a name="5"></a><h5><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=5" title="Edit section: 5">edit</a>]</span> <span class="mw-headline">5</span></h5>
+<a name="2_4"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=6" title="Edit section: 2">edit</a>]</span> <span class="mw-headline">2</span></h2>
+
+!! end
+
+
+!! test
+ISBN with a dummy number
+!! input
+ISBN ---
+!! result
+<p>ISBN ---
+</p>
+!! end
+
+
+!! test
+ISBN with space-delimited number
+!! input
+ISBN 92 9017 032 8
+!! result
+<p><a href="/index.php?title=Special:Booksources&amp;isbn=9290170328" class="internal">ISBN 92 9017 032 8</a>
+</p>
+!! end
+
+
+!! test
+ISBN with multiple spaces, no number
+!! input
+ISBN foo
+!! result
+<p>ISBN foo
+</p>
+!! end
+
+
+!! test
+ISBN length
+!! input
+ISBN 123456789
+
+ISBN 1234567890
+
+ISBN 12345678901
+!! result
+<p>ISBN 123456789
+</p><p><a href="/index.php?title=Special:Booksources&amp;isbn=1234567890" class="internal">ISBN 1234567890</a>
+</p><p>ISBN 12345678901
+</p>
+!! end
+
+
+!! test
+ISBN with trailing year (bug 8110)
+!! input
+ISBN 1-234-56789-0 - 2006
+
+ISBN 1 234 56789 0 - 2006
+!! result
+<p><a href="/index.php?title=Special:Booksources&amp;isbn=1234567890" class="internal">ISBN 1-234-56789-0</a> - 2006
+</p><p><a href="/index.php?title=Special:Booksources&amp;isbn=1234567890" class="internal">ISBN 1 234 56789 0</a> - 2006
+</p>
+!! end
+
+
+!! test
+Pages in namespace (Magic word disabled currently)
+!! input
+{{PAGESINNAMESPACE:}}
+!! result
+
+!! end
+
+
+!! test
+anchorencode
+!! input
+{{anchorencode:foo bar©#%n}}
+!! result
+<p>foo_bar.C2.A9.23.25n
+</p>
+!! end
+
+
+!! test
+Bug 8293: Use of center tag ruins paragraph formatting
+!! input
+<center>
+foo
+</center>
+
+bar
+
+ baz
+!! result
+<center>
+<p>foo
+</p>
+</center>
+<p>bar
+</p>
+<pre>baz
+</pre>
+!! end
+
+
+###
+### Language variants related tests
+###
+!! test
+Self-link in language variants
+!! options
+title=[[Dunav]] language=sr
+!! input
+Both [[Dunav]] and [[Дунав]] are names for this river.
+!! result
+<p>Both <strong class="selflink">Dunav</strong> and <strong class="selflink">Дунав</strong> are names for this river.
+</p>
+!!end
+
+
+!! test
+Link to pages in language variants
+!! options
+language=sr
+!! input
+Main Page can be written as [[Маин Паге]]
+!! result
+<p>Main Page can be written as <a href="/wiki/Main_Page" title="Main Page">Маин Паге</a>
+</p>
+!!end
+
+
+!! test
+Multiple links to pages in language variants
+!! options
+language=sr
+!! input
+[[Main Page]] can be written as [[Маин Паге]] same as [[Маин Паге]].
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">Main Page</a> can be written as <a href="/wiki/Main_Page" title="Main Page">Маин Паге</a> same as <a href="/wiki/Main_Page" title="Main Page">Маин Паге</a>.
+</p>
+!!end
+
+
+!! test
+Simple template in language variants
+!! options
+language=sr
+!! input
+{{тест}}
+!! result
+<p>This is a test template
+</p>
+!! end
+
+
+!! test
+Template with explicit namespace in language variants
+!! options
+language=sr
+!! input
+{{Template:тест}}
+!! result
+<p>This is a test template
+</p>
+!! end
+
+
+!! test
+Basic test for template parameter in language variants
+!! options
+language=sr
+!! input
+{{парамтест|param=foo}}
+!! result
+<p>This is a test template with parameter foo
+</p>
+!! end
+
+
+!! test
+Simple category in language variants
+!! options
+language=sr cat
+!! input
+[[:Category:МедиаWики Усер'с Гуиде]]
+!! result
+<a href="/wiki/Category:MediaWiki_User%27s_Guide" title="Category:MediaWiki User's Guide">MediaWiki User's Guide</a>
+!! end
+
+
+!! test
+Stripping -{}- tags (language variants)
+!! options
+language=sr
+!! input
+Latin proverb: -{Ne nuntium necare}-
+!! result
+<p>Latin proverb: Ne nuntium necare
+</p>
+!! end
+
+
+!! test
+Prevent conversion with -{}- tags (language variants)
+!! options
+language=sr variant=sr-ec
+!! input
+Latinski: -{Ne nuntium necare}-
+!! result
+<p>Латински: Ne nuntium necare
+</p>
+!! end
+
+
+!! test
+Prevent conversion of text with -{}- tags (language variants)
+!! options
+language=sr variant=sr-ec
+!! input
+Latinski: -{Ne nuntium necare}-
+!! result
+<p>Латински: Ne nuntium necare
+</p>
+!! end
+
+
+!! test
+Prevent conversion of links with -{}- tags (language variants)
+!! options
+language=sr variant=sr-ec
+!! input
+-{[[Main Page]]}-
+!! result
+<p><a href="/index.php?title=Main_Page&amp;variant=sr-ec" title="Main Page">Main Page</a>
+</p>
+!! end
+
+
+!! test
+-{}- tags within headlines (within html for parserConvert())
+!! options
+language=sr variant=sr-ec
+!! input
+== -{Naslov}- ==
+!! result
+<a name="-.7BNaslov.7D-"></a><h2><span class="editsection">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Уреди део: Naslov">уреди</a>]</span> <span class="mw-headline"> Naslov </span></h2>
+
+!! end
+
+
+!! test
+Explicit definition of language variant alternatives
+!! options
+language=zh variant=zh-tw
+!! input
+-{zh:China;zh-tw:Taiwan}-, not China
+!! result
+<p>Taiwan, not China
+</p>
+!! end
+
+
+!! test
+Adding explicit session-wise language variant mapping (A flag)
+!! options
+language=zh variant=zh-tw
+!! input
+-{A|zh:China;zh-tw:Taiwan}- is China
+!! result
+<p>Taiwan is Taiwan
+</p>
+!! end
+
+
+!! test
+Adding explicit conversion rule for title (T flag)
+!! options
+language=zh variant=zh-tw
+!! input
+Should be stripped-{T|zh:China;zh-tw:Taiwan}-!
+!! result
+<p>Should be stripped!
+</p>
+!! end
+
+
+!! test
+Raw output of variant escape tags (R flag)
+!! options
+language=zh variant=zh-tw
+!! input
+Raw: -{R|zh:China;zh-tw:Taiwan}-
+!! result
+<p>Raw: zh:China;zh-tw:Taiwan
+</p>
+!! end
+
+
+!! test
+Do not convert roman numbers to language variants
+!! options
+language=sr variant=sr-ec
+!! input
+Fridrih IV je car.
+!! result
+<p>Фридрих IV је цар.
+</p>
+!! end
+
+
#
#
#
diff --git a/maintenance/postgres/compare_schemas.pl b/maintenance/postgres/compare_schemas.pl
index 4a76b270..cdbbdf41 100644
--- a/maintenance/postgres/compare_schemas.pl
+++ b/maintenance/postgres/compare_schemas.pl
@@ -7,8 +7,9 @@ use strict;
use warnings;
use Data::Dumper;
-my @old = ("../tables.sql");
+my @old = ("../tables.sql", "../mysql5/tables.sql", "../mysql5/tables-binary.sql");
my $new = "tables.sql";
+my @xfile;
## Read in exceptions and other metadata
my %ok;
@@ -23,7 +24,7 @@ while (<DATA>) {
next;
}
if ($name eq 'XFILE') {
- push @old, $val;
+ push @xfile, $val;
next;
}
for (split(/\s+/ => $val)) {
@@ -31,12 +32,10 @@ while (<DATA>) {
}
}
-open my $newfh, "<", $new or die qq{Could not open $new: $!\n};
-
my $datatype = join '|' => qw(
bool
tinyint int bigint real float
-tinytext mediumtext text char varchar
+tinytext mediumtext text char varchar varbinary
timestamp datetime
tinyblob mediumblob blob
);
@@ -50,12 +49,43 @@ my $typeval2 = qr{ unsigned| binary| NOT NULL| NULL| auto_increment| default ['\
my $indextype = join '|' => qw(INDEX KEY FULLTEXT), "PRIMARY KEY", "UNIQUE INDEX", "UNIQUE KEY";
$indextype = qr{$indextype};
+my $engine = qr{TYPE|ENGINE};
+
my $tabletype = qr{InnoDB|MyISAM|HEAP|HEAP MAX_ROWS=\d+};
+my $charset = qr{utf8|binary};
+
+open my $newfh, "<", $new or die qq{Could not open $new: $!\n};
+
+
my ($table,%old);
-for my $old (@old) {
- open my $oldfh, "<", $old or die qq{Could not open $old: $!\n};
+## Read in the xfiles
+my %xinfo;
+for my $xfile (@xfile) {
+ print "Loading $xfile\n";
+ my $info = &parse_sql($xfile);
+ for (keys %$info) {
+ $xinfo{$_} = $info->{$_};
+ }
+}
+
+for my $oldfile (@old) {
+ print "Loading $oldfile\n";
+ my $info = &parse_sql($oldfile);
+ for (keys %xinfo) {
+ $info->{$_} = $xinfo{$_};
+ }
+ $old{$oldfile} = $info;
+}
+
+sub parse_sql {
+
+ my $oldfile = shift;
+
+ open my $oldfh, "<", $oldfile or die qq{Could not open $oldfile: $!\n};
+
+ my %info;
while (<$oldfh>) {
next if /^\s*\-\-/ or /^\s+$/;
s/\s*\-\- [\w ]+$//;
@@ -63,37 +93,66 @@ for my $old (@old) {
if (/CREATE\s*TABLE/i) {
m{^CREATE TABLE /\*\$wgDBprefix\*/(\w+) \($}
- or die qq{Invalid CREATE TABLE at line $. of $old\n};
+ or die qq{Invalid CREATE TABLE at line $. of $oldfile\n};
$table = $1;
- $old{$table}{name}=$table;
+ $info{$table}{name}=$table;
+ }
+ elsif (/^\) ($engine)=($tabletype);$/) {
+ $info{$table}{engine}=$1;
+ $info{$table}{type}=$2;
}
- elsif (/^\) TYPE=($tabletype);$/) {
- $old{$table}{type}=$1;
+ elsif (/^\) ($engine)=($tabletype), DEFAULT CHARSET=($charset);$/) {
+ $info{$table}{engine}=$1;
+ $info{$table}{type}=$2;
+ $info{$table}{charset}=$3;
}
elsif (/^ (\w+) $datatype$typeval$typeval2{0,3},?$/) {
- $old{$table}{column}{$1} = $2;
+ $info{$table}{column}{$1} = $2;
}
elsif (/^ ($indextype)(?: (\w+))? \(([\w, \(\)]+)\),?$/) {
- $old{$table}{lc $1."_name"} = $2 ? $2 : "";
- $old{$table}{lc $1."pk_target"} = $3;
+ $info{$table}{lc $1."_name"} = $2 ? $2 : "";
+ $info{$table}{lc $1."pk_target"} = $3;
}
else {
- die "Cannot parse line $. of $old:\n$_\n";
+ die "Cannot parse line $. of $oldfile:\n$_\n";
}
+
}
close $oldfh;
+
+ return \%info;
+
+} ## end of parse_sql
+
+for my $oldfile (@old) {
+
+## Begin non-standard indent
+
+## MySQL sanity checks
+for my $table (sort keys %{$old{$oldfile}}) {
+ my $t = $old{$oldfile}{$table};
+ if (($oldfile =~ /5/ and $t->{engine} ne 'ENGINE')
+ or
+ ($oldfile !~ /5/ and $t->{engine} ne 'TYPE')) {
+ die "Invalid engine for $oldfile: $t->{engine}\n" unless $t->{name} eq 'profiling';
+ }
+ my $charset = $t->{charset} || '';
+ if ($oldfile !~ /binary/ and $charset eq 'binary') {
+ die "Invalid charset for $oldfile: $charset\n";
+ }
}
-$datatype = join '|' => qw(
+my $dtype = join '|' => qw(
SMALLINT INTEGER BIGINT NUMERIC SERIAL
TEXT CHAR VARCHAR
BYTEA
TIMESTAMPTZ
CIDR
);
-$datatype = qr{($datatype)};
+$dtype = qr{($dtype)};
my %new;
my ($infunction,$inview,$inrule) = (0,0,0);
+seek $newfh, 0, 0;
while (<$newfh>) {
next if /^\s*\-\-/ or /^\s*$/;
s/\s*\-\- [\w ']+$//;
@@ -130,24 +189,23 @@ while (<$newfh>) {
}
elsif (/^\);$/) {
}
- elsif (/^ (\w+) +$datatype/) {
+ elsif (/^ (\w+) +$dtype/) {
$new{$table}{column}{$1} = $2;
}
else {
die "Cannot parse line $. of $new:\n$_\n";
}
}
-close $newfh;
## Old but not new
-for my $t (sort keys %old) {
+for my $t (sort keys %{$old{$oldfile}}) {
if (!exists $new{$t} and !exists $ok{OLD}{$t}) {
print "Table not in $new: $t\n";
next;
}
next if exists $ok{OLD}{$t} and !$ok{OLD}{$t};
my $newt = exists $ok{OLD}{$t} ? $ok{OLD}{$t} : $t;
- my $oldcol = $old{$t}{column};
+ my $oldcol = $old{$oldfile}{$t}{column};
my $newcol = $new{$newt}{column};
for my $c (keys %$oldcol) {
if (!exists $newcol->{$c}) {
@@ -164,12 +222,16 @@ for my $t (sort keys %old) {
}
## New but not old:
for (sort keys %new) {
- if (!exists $old{$_} and !exists $ok{NEW}{$_}) {
+ if (!exists $old{$oldfile}{$_} and !exists $ok{NEW}{$_}) {
print "Not in old: $_\n";
next;
}
}
+
+} ## end each file to be parsed
+
+
__DATA__
## Known exceptions
OLD: searchindex ## We use tsearch2 directly on the page table instead
diff --git a/maintenance/postgres/tables.sql b/maintenance/postgres/tables.sql
index 9ac329d8..e6cbbe2a 100644
--- a/maintenance/postgres/tables.sql
+++ b/maintenance/postgres/tables.sql
@@ -17,6 +17,7 @@ CREATE TABLE mwuser ( -- replace reserved word 'user'
user_real_name TEXT,
user_password TEXT,
user_newpassword TEXT,
+ user_newpass_time TIMESTAMPTZ,
user_token CHAR(32),
user_email TEXT,
user_email_token CHAR(32),
@@ -24,7 +25,8 @@ CREATE TABLE mwuser ( -- replace reserved word 'user'
user_email_authenticated TIMESTAMPTZ,
user_options TEXT,
user_touched TIMESTAMPTZ,
- user_registration TIMESTAMPTZ
+ user_registration TIMESTAMPTZ,
+ user_editcount INTEGER
);
CREATE INDEX user_email_token_idx ON mwuser (user_email_token);
@@ -86,7 +88,7 @@ CREATE TABLE revision (
rev_page INTEGER NULL REFERENCES page (page_id) ON DELETE CASCADE,
rev_text_id INTEGER NULL, -- FK
rev_comment TEXT,
- rev_user INTEGER NOT NULL REFERENCES mwuser(user_id),
+ rev_user INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE RESTRICT,
rev_user_text TEXT NOT NULL,
rev_timestamp TIMESTAMPTZ NOT NULL,
rev_minor_edit CHAR NOT NULL DEFAULT '0',
@@ -137,6 +139,14 @@ DO INSTEAD INSERT INTO archive2 VALUES (
);
+CREATE TABLE redirect (
+ rd_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
+ rd_namespace SMALLINT NOT NULL,
+ rd_title TEXT NOT NULL
+);
+CREATE INDEX redirect_ns_title ON redirect (rd_namespace,rd_title,rd_from);
+
+
CREATE TABLE pagelinks (
pl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
pl_namespace SMALLINT NOT NULL,
@@ -201,18 +211,19 @@ CREATE TABLE hitcounter (
CREATE SEQUENCE ipblocks_ipb_id_val;
CREATE TABLE ipblocks (
- ipb_id INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('ipblocks_ipb_id_val'),
- ipb_address CIDR NULL,
- ipb_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL,
- ipb_by INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE,
- ipb_reason TEXT NOT NULL,
- ipb_timestamp TIMESTAMPTZ NOT NULL,
- ipb_auto CHAR NOT NULL DEFAULT '0',
- ipb_anon_only CHAR NOT NULL DEFAULT '0',
- ipb_create_account CHAR NOT NULL DEFAULT '1',
- ipb_expiry TIMESTAMPTZ NOT NULL,
- ipb_range_start TEXT,
- ipb_range_end TEXT
+ ipb_id INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('ipblocks_ipb_id_val'),
+ ipb_address TEXT NULL,
+ ipb_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL,
+ ipb_by INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE,
+ ipb_reason TEXT NOT NULL,
+ ipb_timestamp TIMESTAMPTZ NOT NULL,
+ ipb_auto CHAR NOT NULL DEFAULT '0',
+ ipb_anon_only CHAR NOT NULL DEFAULT '0',
+ ipb_create_account CHAR NOT NULL DEFAULT '1',
+ ipb_enable_autoblock CHAR NOT NULL DEFAULT '1',
+ ipb_expiry TIMESTAMPTZ NOT NULL,
+ ipb_range_start TEXT,
+ ipb_range_end TEXT
);
CREATE INDEX ipb_address ON ipblocks (ipb_address);
CREATE INDEX ipb_user ON ipblocks (ipb_user);
@@ -300,7 +311,9 @@ CREATE TABLE recentchanges (
rc_moved_to_ns SMALLINT,
rc_moved_to_title TEXT,
rc_patrolled CHAR NOT NULL DEFAULT '0',
- rc_ip CIDR
+ rc_ip CIDR,
+ rc_old_len INTEGER,
+ rc_new_len INTEGER
);
CREATE INDEX rc_timestamp ON recentchanges (rc_timestamp);
CREATE INDEX rc_namespace_title ON recentchanges (rc_namespace, rc_title);
@@ -348,6 +361,19 @@ CREATE TABLE querycache_info (
qci_timestamp TIMESTAMPTZ NULL
);
+CREATE TABLE querycachetwo (
+ qcc_type TEXT NOT NULL,
+ qcc_value SMALLINT NOT NULL DEFAULT 0,
+ qcc_namespace INTEGER NOT NULL DEFAULT 0,
+ qcc_title TEXT NOT NULL DEFAULT '',
+ qcc_namespacetwo INTEGER NOT NULL DEFAULT 0,
+ qcc_titletwo TEXT NOT NULL DEFAULT ''
+);
+CREATE INDEX querycachetwo_type_value ON querycachetwo (qcc_type, qcc_value);
+CREATE INDEX querycachetwo_title ON querycachetwo (qcc_type,qcc_namespace,qcc_title);
+CREATE INDEX querycachetwo_titletwo ON querycachetwo (qcc_type,qcc_namespacetwo,qcc_titletwo);
+
+
CREATE TABLE objectcache (
keyname CHAR(255) UNIQUE,
value BYTEA NOT NULL DEFAULT '',
@@ -470,7 +496,7 @@ CREATE TABLE mediawiki_version (
);
INSERT INTO mediawiki_version (type,mw_version,sql_version,sql_date)
- VALUES ('Creation','??','$LastChangedRevision: 16747 $','$LastChangedDate: 2006-10-02 17:55:26 -0700 (Mon, 02 Oct 2006) $');
+ VALUES ('Creation','??','$LastChangedRevision: 18326 $','$LastChangedDate: 2006-12-14 07:34:56 -0800 (Thu, 14 Dec 2006) $');
COMMIT;
diff --git a/maintenance/postgres/wp_mysql2postgres.pl b/maintenance/postgres/wp_mysql2postgres.pl
index 788d9e0b..981d99f3 100644
--- a/maintenance/postgres/wp_mysql2postgres.pl
+++ b/maintenance/postgres/wp_mysql2postgres.pl
@@ -1,7 +1,7 @@
#!/usr/bin/perl
## Convert data from a MySQL mediawiki database into a Postgres mediawiki database
-## svn: $Id: wp_mysql2postgres.pl 16088 2006-08-16 01:12:20Z greg $
+## svn: $Id: wp_mysql2postgres.pl 18836 2007-01-05 03:37:19Z brion $
use strict;
use warnings;
@@ -160,7 +160,7 @@ $MYSQLSOCKET and $conninfo .= "\n-- socket $MYSQLSOCKET";
print qq{
-- Dump of MySQL Mediawiki tables for import into a Postgres Mediawiki schema
-- Performed by the program: $0
--- Version: $VERSION (subversion }.q{$LastChangedRevision: 16088 $}.qq{)
+-- Version: $VERSION (subversion }.q{$LastChangedRevision: 18836 $}.qq{)
-- Author: Greg Sabino Mullane <greg\@turnstep.com> Comments welcome
--
-- This file was created: $now
diff --git a/maintenance/purgeList.php b/maintenance/purgeList.php
new file mode 100644
index 00000000..9bf7c1bf
--- /dev/null
+++ b/maintenance/purgeList.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * Send purge requests for listed pages to squid
+ */
+
+require_once( "commandLine.inc" );
+
+$stdin = fopen( "php://stdin", "rt" );
+$urls = array();
+
+while( !feof( $stdin ) ) {
+ $page = trim( fgets( $stdin ) );
+ if ( substr( $page, 0, 7 ) == 'http://' ) {
+ $urls[] = $page;
+ } elseif( $page !== '' ) {
+ $title = Title::newFromText( $page );
+ if( $title ) {
+ $url = $title->getFullUrl();
+ echo "$url\n";
+ $urls[] = $url;
+ } else {
+ echo "(Invalid title '$page')\n";
+ }
+ }
+}
+
+echo "Purging " . count( $urls ) . " urls...\n";
+$u = new SquidUpdate( $urls );
+$u->doUpdate();
+
+echo "Done!\n";
+
+?>
diff --git a/maintenance/showStats.php b/maintenance/showStats.php
new file mode 100644
index 00000000..27f9be6b
--- /dev/null
+++ b/maintenance/showStats.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * Maintenance script to show the cached statistics.
+ * Give out the same output as [[Special:Statistics]]
+ *
+ * @author Ashar Voultoiz <hashar@altern.org>
+ * Based on initStats.php by:
+ * @author Brion Vibber
+ * @author Rob Church <robchur@gmail.com>
+ *
+ * @licence GNU General Public License 2.0 or later
+ */
+
+require_once( 'commandLine.inc' );
+
+#
+# Configuration
+#
+$fields = array(
+ 'ss_total_views' => 'Total views',
+ 'ss_total_edits' => 'Total edits',
+ 'ss_good_articles' => 'Number of articles',
+ 'ss_total_pages' => 'Total pages',
+ 'ss_users' => 'Number of users',
+ 'ss_admins' => 'Number of admins',
+ 'ss_images' => 'Number of images',
+);
+
+// Get cached stats from slave database
+$dbr =& wfGetDB( DB_SLAVE );
+$fname = 'showStats';
+$stats = $dbr->selectRow( 'site_stats', '*', '' );
+
+// Get maximum size for each column
+$max_length_value = $max_length_desc = 0;
+foreach( $fields as $field => $desc ) {
+ $max_length_value = max( $max_length_value, strlen( $stats->$field ) );
+ $max_length_desc = max( $max_length_desc , strlen( $desc )) ;
+}
+
+// Show them
+foreach( $fields as $field => $desc ) {
+ printf( "%-{$max_length_desc}s: %{$max_length_value}d\n", $desc, $stats->$field );
+}
+?>
diff --git a/maintenance/stats.php b/maintenance/stats.php
index bb19e671..25bb9cc7 100644
--- a/maintenance/stats.php
+++ b/maintenance/stats.php
@@ -1,6 +1,10 @@
<?php
require_once('commandLine.inc');
+if( get_class( $wgMemc ) == 'FakeMemCachedClient' ) {
+ die("You are running FakeMemCachedClient, I can not provide any statistics.\n");
+}
+
print "Requests\n";
$session = intval($wgMemc->get(wfMemcKey('stats','request_with_session')));
$noSession = intval($wgMemc->get(wfMemcKey('stats','request_without_session')));
diff --git a/maintenance/tables.sql b/maintenance/tables.sql
index 3ffa5e5f..188ca63e 100644
--- a/maintenance/tables.sql
+++ b/maintenance/tables.sql
@@ -64,7 +64,7 @@ CREATE TABLE /*$wgDBprefix*/user (
-- Password hashes, normally hashed like so:
-- MD5(CONCAT(user_id,'-',MD5(plaintext_password))), see
-- wfEncryptPassword() in GlobalFunctions.php
- user_password tinyblob NOT NULL default '',
+ user_password tinyblob NOT NULL,
-- When using 'mail me a new password', a random
-- password is generated and the hash stored here.
@@ -72,15 +72,19 @@ CREATE TABLE /*$wgDBprefix*/user (
-- someone actually logs in with the new password,
-- at which point the hash is moved to user_password
-- and the old password is invalidated.
- user_newpassword tinyblob NOT NULL default '',
+ user_newpassword tinyblob NOT NULL,
+ -- Timestamp of the last time when a new password was
+ -- sent, for throttling purposes
+ user_newpass_time char(14) binary,
+
-- Note: email should be restricted, not public info.
-- Same with passwords.
- user_email tinytext NOT NULL default '',
+ user_email tinytext NOT NULL,
-- Newline-separated list of name=value defining the user
-- preferences
- user_options blob NOT NULL default '',
+ user_options blob NOT NULL,
-- This is a timestamp which is updated when a user
-- logs in, logs out, changes preferences, or performs
@@ -109,6 +113,18 @@ CREATE TABLE /*$wgDBprefix*/user (
-- Timestamp of account registration.
-- Accounts predating this schema addition may contain NULL.
user_registration char(14) binary,
+
+ -- Count of edits and edit-like actions.
+ --
+ -- *NOT* intended to be an accurate copy of COUNT(*) WHERE rev_user=user_id
+ -- May contain NULL for old accounts if batch-update scripts haven't been
+ -- run, as well as listing deleted edits and other myriad ways it could be
+ -- out of sync.
+ --
+ -- Meant primarily for heuristic checks to give an impression of whether
+ -- the account has been used much.
+ --
+ user_editcount int,
PRIMARY KEY user_id (user_id),
UNIQUE INDEX user_name (user_name),
@@ -176,7 +192,7 @@ CREATE TABLE /*$wgDBprefix*/page (
-- Comma-separated set of permission keys indicating who
-- can move or edit the page.
- page_restrictions tinyblob NOT NULL default '',
+ page_restrictions tinyblob NOT NULL,
-- Number of times this page has been viewed.
page_counter bigint(20) unsigned NOT NULL default '0',
@@ -235,7 +251,7 @@ CREATE TABLE /*$wgDBprefix*/revision (
-- Text comment summarizing the change.
-- This text is shown in the history and other changes lists,
-- rendered in a subset of wiki markup by Linker::formatComment()
- rev_comment tinyblob NOT NULL default '',
+ rev_comment tinyblob NOT NULL,
-- Key to user.user_id of the user who made this edit.
-- Stores 0 for anonymous edits and for some mass imports.
@@ -282,7 +298,7 @@ CREATE TABLE /*$wgDBprefix*/text (
-- Depending on the contents of the old_flags field, the text
-- may be convenient plain text, or it may be funkily encoded.
- old_text mediumblob NOT NULL default '',
+ old_text mediumblob NOT NULL,
-- Comma-separated list of flags:
-- gzip: text is compressed with PHP's gzdeflate() function.
@@ -293,7 +309,7 @@ CREATE TABLE /*$wgDBprefix*/text (
-- The object either contains multiple versions compressed
-- together to achieve a better compression ratio, or it refers
-- to another row where the text can be found.
- old_flags tinyblob NOT NULL default '',
+ old_flags tinyblob NOT NULL,
PRIMARY KEY old_id (old_id)
@@ -315,17 +331,17 @@ CREATE TABLE /*$wgDBprefix*/archive (
-- so old archived pages will remain accessible after
-- upgrading from 1.4 to 1.5.
-- Text may be gzipped or otherwise funky.
- ar_text mediumblob NOT NULL default '',
+ ar_text mediumblob NOT NULL,
-- Basic revision stuff...
- ar_comment tinyblob NOT NULL default '',
+ ar_comment tinyblob NOT NULL,
ar_user int(5) unsigned NOT NULL default '0',
ar_user_text varchar(255) binary NOT NULL,
ar_timestamp char(14) binary NOT NULL default '',
ar_minor_edit tinyint(1) NOT NULL default '0',
-- See ar_text note.
- ar_flags tinyblob NOT NULL default '',
+ ar_flags tinyblob NOT NULL,
-- When revisions are deleted, their unique rev_id is stored
-- here so it can be retained after undeletion. This is necessary
@@ -367,7 +383,7 @@ CREATE TABLE /*$wgDBprefix*/pagelinks (
pl_title varchar(255) binary NOT NULL default '',
UNIQUE KEY pl_from (pl_from,pl_namespace,pl_title),
- KEY (pl_namespace,pl_title)
+ KEY (pl_namespace,pl_title,pl_from)
) TYPE=InnoDB;
@@ -387,7 +403,7 @@ CREATE TABLE /*$wgDBprefix*/templatelinks (
tl_title varchar(255) binary NOT NULL default '',
UNIQUE KEY tl_from (tl_from,tl_namespace,tl_title),
- KEY (tl_namespace,tl_title)
+ KEY (tl_namespace,tl_title,tl_from)
) TYPE=InnoDB;
@@ -406,7 +422,7 @@ CREATE TABLE /*$wgDBprefix*/imagelinks (
il_to varchar(255) binary NOT NULL default '',
UNIQUE KEY il_from (il_from,il_to),
- KEY (il_to)
+ KEY (il_to,il_from)
) TYPE=InnoDB;
@@ -458,7 +474,7 @@ CREATE TABLE /*$wgDBprefix*/externallinks (
el_from int(8) unsigned NOT NULL default '0',
-- The URL
- el_to blob NOT NULL default '',
+ el_to blob NOT NULL,
-- In the case of HTTP URLs, this is the URL with any username or password
-- removed, and with the labels in the hostname reversed and converted to
@@ -471,7 +487,7 @@ CREATE TABLE /*$wgDBprefix*/externallinks (
-- which allows for fast searching for all pages under example.com with the
-- clause:
-- WHERE el_index LIKE 'http://com.example.%'
- el_index blob NOT NULL default '',
+ el_index blob NOT NULL,
KEY (el_from, el_to(40)),
KEY (el_to(60), el_from),
@@ -553,7 +569,7 @@ CREATE TABLE /*$wgDBprefix*/ipblocks (
ipb_id int(8) NOT NULL auto_increment,
-- Blocked IP address in dotted-quad form or user name.
- ipb_address tinyblob NOT NULL default '',
+ ipb_address tinyblob NOT NULL,
-- Blocked user ID or 0 for IP blocks.
ipb_user int(8) unsigned NOT NULL default '0',
@@ -562,7 +578,7 @@ CREATE TABLE /*$wgDBprefix*/ipblocks (
ipb_by int(8) unsigned NOT NULL default '0',
-- Text comment made by blocker.
- ipb_reason tinyblob NOT NULL default '',
+ ipb_reason tinyblob NOT NULL,
-- Creation (or refresh) date in standard YMDHMS form.
-- IP blocks expire automatically.
@@ -578,14 +594,17 @@ CREATE TABLE /*$wgDBprefix*/ipblocks (
-- Block prevents account creation from matching IP addresses
ipb_create_account bool NOT NULL default 1,
+
+ -- Block triggers autoblocks
+ ipb_enable_autoblock bool NOT NULL default '1',
-- Time at which the block will expire.
ipb_expiry char(14) binary NOT NULL default '',
-- Start and end of an address range, in hexadecimal
-- Size chosen to allow IPv6
- ipb_range_start tinyblob NOT NULL default '',
- ipb_range_end tinyblob NOT NULL default '',
+ ipb_range_start tinyblob NOT NULL,
+ ipb_range_end tinyblob NOT NULL,
PRIMARY KEY ipb_id (ipb_id),
@@ -638,11 +657,11 @@ CREATE TABLE /*$wgDBprefix*/image (
-- Description field as entered by the uploader.
-- This is displayed in image upload history and logs.
- img_description tinyblob NOT NULL default '',
+ img_description tinyblob NOT NULL,
-- user_id and user_name of uploader.
img_user int(5) unsigned NOT NULL default '0',
- img_user_text varchar(255) binary NOT NULL default '',
+ img_user_text varchar(255) binary NOT NULL,
-- Time of the upload.
img_timestamp char(14) binary NOT NULL default '',
@@ -675,9 +694,9 @@ CREATE TABLE /*$wgDBprefix*/oldimage (
oi_width int(5) NOT NULL default 0,
oi_height int(5) NOT NULL default 0,
oi_bits int(3) NOT NULL default 0,
- oi_description tinyblob NOT NULL default '',
+ oi_description tinyblob NOT NULL,
oi_user int(5) unsigned NOT NULL default '0',
- oi_user_text varchar(255) binary NOT NULL default '',
+ oi_user_text varchar(255) binary NOT NULL,
oi_timestamp char(14) binary NOT NULL default '',
INDEX oi_name (oi_name(10))
@@ -723,9 +742,9 @@ CREATE TABLE /*$wgDBprefix*/filearchive (
fa_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
fa_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") default "unknown",
fa_minor_mime varchar(32) default "unknown",
- fa_description tinyblob default '',
+ fa_description tinyblob,
fa_user int(5) unsigned default '0',
- fa_user_text varchar(255) binary default '',
+ fa_user_text varchar(255) binary,
fa_timestamp char(14) binary default '',
PRIMARY KEY (fa_id),
@@ -748,7 +767,7 @@ CREATE TABLE /*$wgDBprefix*/recentchanges (
-- As in revision
rc_user int(10) unsigned NOT NULL default '0',
- rc_user_text varchar(255) binary NOT NULL default '',
+ rc_user_text varchar(255) binary NOT NULL,
-- When pages are renamed, their RC entries do _not_ change.
rc_namespace int NOT NULL default '0',
@@ -791,13 +810,19 @@ CREATE TABLE /*$wgDBprefix*/recentchanges (
-- $wgPutIPinRC option is enabled.
rc_ip char(15) NOT NULL default '',
+ -- Text length in characters before
+ -- and after the edit
+ rc_old_len int(10),
+ rc_new_len int(10),
+
PRIMARY KEY rc_id (rc_id),
INDEX rc_timestamp (rc_timestamp),
INDEX rc_namespace_title (rc_namespace, rc_title),
INDEX rc_cur_id (rc_cur_id),
INDEX new_name_timestamp (rc_new,rc_namespace,rc_timestamp),
INDEX rc_ip (rc_ip),
- INDEX rc_ns_usertext (rc_namespace, rc_user_text)
+ INDEX rc_ns_usertext (rc_namespace, rc_user_text),
+ INDEX rc_user_text (rc_user_text, rc_timestamp)
) TYPE=InnoDB;
@@ -862,7 +887,7 @@ CREATE TABLE /*$wgDBprefix*/searchindex (
si_title varchar(255) NOT NULL default '',
-- Munged version of body text
- si_text mediumtext NOT NULL default '',
+ si_text mediumtext NOT NULL,
UNIQUE KEY (si_page),
FULLTEXT si_title (si_title),
@@ -955,7 +980,7 @@ CREATE TABLE /*$wgDBprefix*/logging (
log_comment varchar(255) NOT NULL default '',
-- LF separated list of miscellaneous parameters
- log_params blob NOT NULL default '',
+ log_params blob NOT NULL,
KEY type_time (log_type, log_timestamp),
KEY user_time (log_user, log_timestamp),
@@ -991,7 +1016,7 @@ CREATE TABLE /*$wgDBprefix*/job (
-- Any other parameters to the command
-- Presently unused, format undefined
- job_params blob NOT NULL default '',
+ job_params blob NOT NULL,
PRIMARY KEY job_id (job_id),
KEY (job_cmd, job_namespace, job_title)
@@ -1012,4 +1037,42 @@ CREATE TABLE /*$wgDBprefix*/querycache_info (
) TYPE=InnoDB;
+-- For each redirect, this table contains exactly one row defining its target
+CREATE TABLE /*$wgDBprefix*/redirect (
+ -- Key to the page_id of the redirect page
+ rd_from int(8) unsigned NOT NULL default '0',
+
+ -- Key to page_namespace/page_title of the target page.
+ -- The target page may or may not exist, and due to renames
+ -- and deletions may refer to different page records as time
+ -- goes by.
+ rd_namespace int NOT NULL default '0',
+ rd_title varchar(255) binary NOT NULL default '',
+
+ PRIMARY KEY rd_from (rd_from),
+ KEY rd_ns_title (rd_namespace,rd_title,rd_from)
+) TYPE=InnoDB;
+
+-- Used for caching expensive grouped queries that need two links (for example double-redirects)
+CREATE TABLE /*$wgDBprefix*/querycachetwo (
+ -- A key name, generally the base name of of the special page.
+ qcc_type char(32) NOT NULL,
+
+ -- Some sort of stored value. Sizes, counts...
+ qcc_value int(5) unsigned NOT NULL default '0',
+
+ -- Target namespace+title
+ qcc_namespace int NOT NULL default '0',
+ qcc_title char(255) binary NOT NULL default '',
+
+ -- Target namespace+title2
+ qcc_namespacetwo int NOT NULL default '0',
+ qcc_titletwo char(255) binary NOT NULL default '',
+
+ KEY qcc_type (qcc_type,qcc_value),
+ KEY qcc_title (qcc_type,qcc_namespace,qcc_title),
+ KEY qcc_titletwo (qcc_type,qcc_namespacetwo,qcc_titletwo)
+
+) TYPE=InnoDB;
+
-- vim: sw=2 sts=2 et
diff --git a/maintenance/testRunner.sql b/maintenance/testRunner.sql
new file mode 100644
index 00000000..8591d81d
--- /dev/null
+++ b/maintenance/testRunner.sql
@@ -0,0 +1,35 @@
+--
+-- Optional tables for parserTests recording mode
+-- With --record option, success data will be saved to these tables,
+-- and comparisons of what's changed from the previous run will be
+-- displayed at the end of each run.
+--
+-- These tables currently require MySQL 5 (or maybe 4.1?) for subselects.
+--
+
+drop table if exists /*$wgDBprefix*/testitem;
+drop table if exists /*$wgDBprefix*/testrun;
+
+create table /*$wgDBprefix*/testrun (
+ tr_id int not null auto_increment,
+
+ tr_date char(14) binary,
+ tr_mw_version blob,
+ tr_php_version blob,
+ tr_db_version blob,
+ tr_uname blob,
+
+ primary key (tr_id)
+) engine=InnoDB;
+
+create table /*$wgDBprefix*/testitem (
+ ti_run int not null,
+ ti_name varchar(255),
+ ti_success bool,
+
+ unique key (ti_run, ti_name),
+ key (ti_run, ti_success),
+
+ foreign key (ti_run) references /*$wgDBprefix*/testrun(tr_id)
+ on delete cascade
+) engine=InnoDB;
diff --git a/maintenance/update.php b/maintenance/update.php
index 402818ce..490c3f63 100644
--- a/maintenance/update.php
+++ b/maintenance/update.php
@@ -10,7 +10,7 @@ require_once 'counter.php';
/** */
$wgUseMasterForMaintenance = true;
-$options = array( 'quick' );
+$options = array( 'quick', 'nopurge' );
require_once( "commandLine.inc" );
require_once( "updaters.inc" );
$wgTitle = Title::newFromText( "MediaWiki database updater" );
@@ -54,13 +54,10 @@ if( !isset( $options['quick'] ) ) {
echo "\n";
}
-if ( isset( $options['doshared'] ) ) {
- $doShared = true;
-} else {
- $doShared = false;
-}
+$shared = isset( $options['doshared'] );
+$purge = !isset( $options['nopurge'] );
-do_all_updates( $doShared );
+do_all_updates( $shared, $purge );
print "Done.\n";
diff --git a/maintenance/updateArticleCount.inc.php b/maintenance/updateArticleCount.inc.php
index 20546a78..7eaea749 100644
--- a/maintenance/updateArticleCount.inc.php
+++ b/maintenance/updateArticleCount.inc.php
@@ -39,12 +39,9 @@ class ArticleCounter {
function makeSql() {
extract( $this->dbr->tableNames( 'page', 'pagelinks' ) );
$nsset = $this->makeNsSet();
- return "SELECT COUNT(*) AS count FROM {$page}
- LEFT JOIN {$pagelinks} ON pl_from = page_id
- WHERE page_namespace IN ( $nsset )
- AND page_is_redirect = 0
- AND page_len > 0
- AND pl_namespace IS NOT NULL";
+ return "SELECT DISTINCT page_namespace,page_title FROM $page,$pagelinks " .
+ "WHERE pl_from=page_id and page_namespace IN ( $nsset ) " .
+ "AND page_is_redirect = 0 AND page_len > 0";
}
/**
@@ -55,14 +52,16 @@ class ArticleCounter {
function count() {
$res = $this->dbr->query( $this->makeSql(), __METHOD__ );
if( $res ) {
- $row = $this->dbr->fetchObject( $res );
+ $count = $this->dbr->numRows( $res );
$this->dbr->freeResult( $res );
- return (int)$row->count;
+ return $count;
} else {
- return false; # Look out for this when handling the result
+ # Look out for this when handling the result
+ # - Actually it's unreachable, !$res throws an exception -- TS
+ return false;
}
}
}
-?> \ No newline at end of file
+?>
diff --git a/maintenance/updateSpecialPages.php b/maintenance/updateSpecialPages.php
index a7a72b58..89b5aa94 100644
--- a/maintenance/updateSpecialPages.php
+++ b/maintenance/updateSpecialPages.php
@@ -28,6 +28,11 @@ foreach ( $wgQueryPages as $page ) {
continue;
}
+ if ( in_array( $special, $wgDisableQueryPageUpdate ) ) {
+ printf("%-30s disabled\n", $special);
+ continue;
+ }
+
$specialObj = SpecialPage::getPage( $special );
if ( !$specialObj ) {
print "No such special page: $special\n";
@@ -40,12 +45,12 @@ foreach ( $wgQueryPages as $page ) {
$queryPage = new $class;
if( !(isset($options['only'])) or ($options['only'] == $queryPage->getName()) ) {
- printf( '%-30s', $special );
+ printf( '%-30s ', $special );
if ( $queryPage->isExpensive() ) {
$t1 = explode( ' ', microtime() );
# Do the query
- $num = $queryPage->recache( $limit === null ? 1000 : $limit );
+ $num = $queryPage->recache( $limit === null ? $wgQueryCacheLimit : $limit );
$t2 = explode( ' ', microtime() );
if ( $num === false ) {
@@ -80,12 +85,15 @@ foreach ( $wgQueryPages as $page ) {
}
# Wait for the slave to catch up
+ /*
$slaveDB =& wfGetDB( DB_SLAVE, array('QueryPage::recache', 'vslow' ) );
while( $slaveDB->getLag() > 600 ) {
print "Slave lagged, waiting...\n";
sleep(30);
}
+ */
+ wfWaitForSlaves( 5 );
} else {
print "cheap, skipped\n";
diff --git a/maintenance/updaters.inc b/maintenance/updaters.inc
index d334660e..7909b13d 100644
--- a/maintenance/updaters.inc
+++ b/maintenance/updaters.inc
@@ -6,9 +6,14 @@
/** */
+if ( !defined( 'MEDIAWIKI' ) ) {
+ echo "This file is not a valid entry point\n";
+ exit( 1 );
+}
+
require_once 'convertLinks.inc';
-require_once 'InitialiseMessages.inc';
require_once 'userDupes.inc';
+require_once 'deleteDefaultMessages.php';
$wgRenamedTables = array(
# from to patch file
@@ -30,16 +35,20 @@ $wgNewTables = array(
array( 'langlinks', 'patch-langlinks.sql' ),
array( 'querycache_info', 'patch-querycacheinfo.sql' ),
array( 'filearchive', 'patch-filearchive.sql' ),
+ array( 'redirect', 'patch-redirect.sql' ),
+ array( 'querycachetwo', 'patch-querycachetwo.sql' ),
);
$wgNewFields = array(
# table field patch file (in maintenance/archives)
array( 'ipblocks', 'ipb_id', 'patch-ipblocks.sql' ),
array( 'ipblocks', 'ipb_expiry', 'patch-ipb_expiry.sql' ),
+ array( 'ipblocks', 'ipb_enable_autoblock', 'patch-ipb_optional_autoblock.sql' ),
array( 'recentchanges', 'rc_type', 'patch-rc_type.sql' ),
array( 'recentchanges', 'rc_ip', 'patch-rc_ip.sql' ),
array( 'recentchanges', 'rc_id', 'patch-rc_id.sql' ),
array( 'recentchanges', 'rc_patrolled', 'patch-rc-patrol.sql' ),
+ array( 'recentchanges', 'rc_old_len', 'patch-rc_len.sql' ),
array( 'user', 'user_real_name', 'patch-user-realname.sql' ),
array( 'user', 'user_token', 'patch-user_token.sql' ),
array( 'user', 'user_email_token', 'patch-user_email_token.sql' ),
@@ -57,6 +66,8 @@ $wgNewFields = array(
array( 'ipblocks', 'ipb_range_start', 'patch-ipb_range_start.sql' ),
array( 'site_stats', 'ss_images', 'patch-ss_images.sql' ),
array( 'ipblocks', 'ipb_anon_only', 'patch-ipb_anon_only.sql' ),
+ array( 'user', 'user_newpass_time','patch-user_newpass_time.sql' ),
+ array( 'user', 'user_editcount', 'patch-user_editcount.sql' ),
);
function rename_table( $from, $to, $patch ) {
@@ -379,7 +390,7 @@ function do_schema_restructuring() {
page_id int(8) unsigned NOT NULL auto_increment,
page_namespace int NOT NULL,
page_title varchar(255) binary NOT NULL,
- page_restrictions tinyblob NOT NULL default '',
+ page_restrictions tinyblob NOT NULL,
page_counter bigint(20) unsigned NOT NULL default '0',
page_is_redirect tinyint(1) unsigned NOT NULL default '0',
page_is_new tinyint(1) unsigned NOT NULL default '0',
@@ -396,7 +407,7 @@ function do_schema_restructuring() {
$wgDatabase->query("CREATE TABLE $revision (
rev_id int(8) unsigned NOT NULL auto_increment,
rev_page int(8) unsigned NOT NULL,
- rev_comment tinyblob NOT NULL default '',
+ rev_comment tinyblob NOT NULL,
rev_user int(5) unsigned NOT NULL default '0',
rev_user_text varchar(255) binary NOT NULL default '',
rev_timestamp char(14) binary NOT NULL default '',
@@ -775,12 +786,59 @@ function do_rc_indices_update() {
dbsource( archive( 'patch-recentchanges-utindex.sql' ) );
} else {
# Index seems to exist
- echo( "...seems to be ok\n" );
+ echo( "...index on ( rc_namespace, rc_user_text ) seems to be ok\n" );
+ }
+
+ #Add (rc_user_text, rc_timestamp) index [A. Garrett], November 2006
+ # See if we can find the index we want
+ $info = $wgDatabase->indexInfo( 'recentchanges', 'rc_user_text', __METHOD__ );
+ if( !$info ) {
+ # None, so create
+ echo( "...index on ( rc_user_text, rc_timestamp ) not found; creating\n" );
+ dbsource( archive( 'patch-rc_user_text-index.sql' ) );
+ } else {
+ # Index seems to exist
+ echo( "...index on ( rc_user_text, rc_timestamp ) seems to be ok\n" );
+ }
+}
+
+function index_has_field($table, $index, $field) {
+ global $wgDatabase;
+ echo( "Checking if $table index $index includes field $field...\n" );
+ $info = $wgDatabase->indexInfo( $table, $index, __METHOD__ );
+ if( $info ) {
+ foreach($info as $row) {
+ if($row->Column_name == $field) {
+ echo( "...index $index on table $table seems to be ok\n" );
+ return true;
+ }
+ }
}
+ echo( "...index $index on table $table has no field $field; adding\n" );
+ return false;
}
-function do_all_updates( $doShared = false ) {
- global $wgNewTables, $wgNewFields, $wgRenamedTables, $wgSharedDB, $wgDatabase, $wgDBtype;
+function do_backlinking_indices_update() {
+ echo( "Checking for backlinking indices...\n" );
+ if (!index_has_field('pagelinks', 'pl_namespace', 'pl_from') ||
+ !index_has_field('templatelinks', 'tl_namespace', 'tl_from') ||
+ !index_has_field('imagelinks', 'il_to', 'il_from'))
+ {
+ dbsource( archive( 'patch-backlinkindexes.sql' ) );
+ }
+}
+
+function purge_cache() {
+ global $wgDatabase;
+ # We can't guarantee that the user will be able to use TRUNCATE,
+ # but we know that DELETE is available to us
+ echo( "Purging caches..." );
+ $wgDatabase->delete( 'objectcache', '*', __METHOD__ );
+ echo( "done.\n" );
+}
+
+function do_all_updates( $shared = false, $purge = true ) {
+ global $wgNewTables, $wgNewFields, $wgRenamedTables, $wgSharedDB, $wgDatabase, $wgDBtype, $IP;
$doUser = !$wgSharedDB || $doShared;
@@ -844,8 +902,17 @@ function do_all_updates( $doShared = false ) {
do_page_random_update(); flush();
do_rc_indices_update(); flush();
+
+ do_backlinking_indices_update(); flush();
- initialiseMessages(); flush();
+ echo "Deleting old default messages..."; flush();
+ deleteDefaultMessages();
+ echo "Done\n"; flush();
+
+ if( $purge ) {
+ purge_cache();
+ flush();
+ }
}
function archive($name) {
@@ -861,20 +928,28 @@ function archive($name) {
function do_postgres_updates() {
global $wgDatabase, $wgVersion, $wgDBmwschema;
- $version = "1.7.1";
-
# Just in case their LocalSetings.php does not have this:
if ( !isset( $wgDBmwschema ))
$wgDBmwschema = 'mediawiki';
+ ## Default to the oldest supported version
+ $version = 1.7;
+
if ($wgDatabase->tableExists("mediawiki_version")) {
$version = "1.8";
+ $sql = "SELECT mw_version FROM mediawiki_version ORDER BY cdate DESC LIMIT 1";
+ $tempversion = pg_fetch_result($wgDatabase->doQuery($sql),0,0);
+ $thisver = array();
+ if (preg_match('/(\d+\.\d+)/', $tempversion, $thisver)) {
+ $version = $thisver[1];
+ }
}
- if ($version == '1.7.1') {
- $upgrade = <<<PGEND
+ print " Detected version: $version ";
+ $upgrade = '';
-BEGIN;
+ if ($version <= 1.7) {
+ $upgrade = <<<PGEND
-- Type tweaking:
ALTER TABLE oldimage ALTER oi_size TYPE INTEGER;
@@ -927,9 +1002,6 @@ CREATE TABLE mediawiki_version (
cdate TIMESTAMPTZ NOT NULL DEFAULT now()
);
-INSERT INTO mediawiki_version (type,mw_version,notes)
-VALUES ('Upgrade','MWVERSION','Upgrade from older version 1.7.1');
-
-- Special modifications
ALTER TABLE archive RENAME to archive2;
CREATE VIEW archive AS
@@ -957,20 +1029,69 @@ END;
CREATE TRIGGER page_deleted AFTER DELETE ON page
FOR EACH ROW EXECUTE PROCEDURE page_deleted();
-COMMIT;
-
PGEND;
- $upgrade = str_replace( 'MWVERSION', $wgVersion, $upgrade );
+ } ## end version 1.7
+
+ else if ($version <= 1.8) {
+ $upgrade = <<<PGEND
+
+-- Tighten up restrictions on the revision table so we don't lose data:
+ALTER TABLE revision DROP CONSTRAINT revision_rev_user_fkey;
+ALTER TABLE revision ADD CONSTRAINT revision_rev_user_fkey
+ FOREIGN KEY (rev_user) REFERENCES mwuser(user_id) ON DELETE RESTRICT;
+
+-- New columns for better password tracking:
+ALTER TABLE mwuser ADD user_newpass_time TIMESTAMPTZ;
+ALTER TABLE mwuser ADD user_editcount INTEGER;
- $res = $wgDatabase->query($upgrade);
+-- New column for autoblocking problem users
+ALTER TABLE ipblocks ADD ipb_enable_autoblock CHAR NOT NULL DEFAULT '1';
- } ## end version 1.7.1 upgrade
+-- Despite it's name, ipb_address does not necessarily contain IP addresses :)
+ALTER TABLE ipblocks ALTER ipb_address TYPE TEXT USING ipb_address::TEXT;
- else {
- print "No updates needed\n";
+-- New tables:
+CREATE TABLE redirect (
+ rd_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
+ rd_namespace SMALLINT NOT NULL,
+ rd_title TEXT NOT NULL
+);
+CREATE INDEX redirect_ns_title ON redirect (rd_namespace,rd_title,rd_from);
+
+CREATE TABLE querycachetwo (
+ qcc_type TEXT NOT NULL,
+ qcc_value SMALLINT NOT NULL DEFAULT 0,
+ qcc_namespace INTEGER NOT NULL DEFAULT 0,
+ qcc_title TEXT NOT NULL DEFAULT '',
+ qcc_namespacetwo INTEGER NOT NULL DEFAULT 0,
+ qcc_titletwo TEXT NOT NULL DEFAULT ''
+);
+CREATE INDEX querycachetwo_type_value ON querycachetwo (qcc_type, qcc_value);
+CREATE INDEX querycachetwo_title ON querycachetwo (qcc_type,qcc_namespace,qcc_title);
+CREATE INDEX querycachetwo_titletwo ON querycachetwo (qcc_type,qcc_namespacetwo,qcc_titletwo);
+
+-- New columns for fancy recentchanges display
+ALTER TABLE recentchanges ADD rc_old_len INT;
+ALTER TABLE recentchanges ADD rc_new_len INT;
+
+-- Note this upgrade
+INSERT INTO mediawiki_version (type,mw_version,notes)
+VALUES ('Upgrade','MWVERSION','Upgrade from older version THISVERSION');
+
+PGEND;
+
+ }
+
+ if ( !strlen($upgrade)) {
+ print "No updates needed for version $version\n";
+ return;
}
+ $upgrade = str_replace( 'MWVERSION', $wgVersion, $upgrade );
+ $upgrade = str_replace( 'THISVERSION', $version, $upgrade );
+ $res = $wgDatabase->query("BEGIN;\n\n $upgrade\n\nCOMMIT;\n");
+
return;
}
diff --git a/maintenance/userDupes.inc b/maintenance/userDupes.inc
index e632f737..9af66f11 100644
--- a/maintenance/userDupes.inc
+++ b/maintenance/userDupes.inc
@@ -46,7 +46,7 @@ class UserDupes {
# Confusingly, 'Non_unique' is 0 for *unique* indexes,
# and 1 for *non-unique* indexes. Pass the crack, MySQL,
# it's obviously some good stuff!
- return ( $info->Non_unique == 0 );
+ return ( $info[0]->Non_unique == 0 );
}
/**