summaryrefslogtreecommitdiff
path: root/maintenance
diff options
context:
space:
mode:
Diffstat (limited to 'maintenance')
-rw-r--r--maintenance/Doxyfile180
-rw-r--r--maintenance/Maintenance.php102
-rw-r--r--maintenance/Makefile7
-rw-r--r--maintenance/Site.php19
-rw-r--r--maintenance/addwiki.php479
-rw-r--r--maintenance/archives/patch-ar_sha1.sql3
-rw-r--r--maintenance/archives/patch-drop-user_options.sql1
-rw-r--r--maintenance/archives/patch-jobs-add-timestamp.sql2
-rw-r--r--maintenance/archives/patch-logging-type-action-index.sql1
-rw-r--r--maintenance/archives/patch-page_redirect_namespace_len.sql6
-rw-r--r--maintenance/archives/patch-rev_sha1.sql3
-rw-r--r--maintenance/archives/patch-trackbacks.sql10
-rw-r--r--maintenance/archives/patch-ufg_group-length-increase.sql2
-rw-r--r--maintenance/archives/patch-ug_group-length-increase.sql2
-rw-r--r--maintenance/archives/patch-uploadstash_chunk.sql3
-rw-r--r--maintenance/archives/patch-user_former_groups.sql2
-rw-r--r--maintenance/attachLatest.php4
-rw-r--r--maintenance/backup.inc14
-rw-r--r--maintenance/backupPrefetch.inc5
-rw-r--r--maintenance/benchmarks/Benchmarker.php3
-rw-r--r--maintenance/benchmarks/bench_HTTP_HTTPS.php4
-rw-r--r--maintenance/benchmarks/bench_delete_truncate.php4
-rw-r--r--maintenance/benchmarks/bench_if_switch.php4
-rw-r--r--maintenance/benchmarks/bench_strtr_str_replace.php4
-rw-r--r--maintenance/benchmarks/bench_wfIsWindows.php4
-rw-r--r--maintenance/benchmarks/benchmarkHooks.php80
-rw-r--r--maintenance/benchmarks/benchmarkPurge.php6
-rw-r--r--maintenance/changePassword.php2
-rw-r--r--maintenance/checkImages.php4
-rw-r--r--maintenance/checkSyntax.php10
-rw-r--r--maintenance/cleanupCaps.php13
-rw-r--r--maintenance/cleanupImages.php17
-rw-r--r--maintenance/cleanupSpam.php28
-rw-r--r--maintenance/cleanupTable.inc2
-rw-r--r--maintenance/cleanupTitles.php3
-rw-r--r--maintenance/cleanupUploadStash.php34
-rw-r--r--maintenance/clear_stats.php3
-rw-r--r--maintenance/commandLine.inc12
-rw-r--r--maintenance/convertUserOptions.php33
-rw-r--r--maintenance/deleteBatch.php39
-rw-r--r--maintenance/deleteDefaultMessages.php18
-rw-r--r--maintenance/dev/README7
-rw-r--r--maintenance/dev/includes/php.sh12
-rw-r--r--maintenance/dev/includes/require-php.sh8
-rw-r--r--maintenance/dev/includes/router.php82
-rw-r--r--maintenance/dev/install.sh8
-rw-r--r--maintenance/dev/installmw.sh18
-rw-r--r--maintenance/dev/installphp.sh57
-rw-r--r--maintenance/dev/start.sh14
-rw-r--r--maintenance/doMaintenance.php22
-rw-r--r--maintenance/dtrace/counts.d23
-rw-r--r--maintenance/dtrace/tree.d26
-rw-r--r--maintenance/dumpBackup.php2
-rw-r--r--maintenance/dumpHTML.php7
-rw-r--r--maintenance/dumpInterwiki.php251
-rw-r--r--maintenance/dumpLinks.php2
-rw-r--r--maintenance/dumpTextPass.php52
-rw-r--r--maintenance/edit.php4
-rw-r--r--maintenance/eval.php13
-rw-r--r--maintenance/fetchText.php2
-rw-r--r--maintenance/findHooks.php34
-rw-r--r--maintenance/fixExtLinksProtocolRelative.php4
-rw-r--r--maintenance/formatInstallDoc.php3
-rw-r--r--maintenance/fuzz-tester.php165
-rw-r--r--maintenance/gearman/gearman.inc104
-rw-r--r--maintenance/gearman/gearmanRefreshLinks.php45
-rw-r--r--maintenance/gearman/gearmanWorker.php43
-rw-r--r--maintenance/generateSitemap.php31
-rw-r--r--maintenance/getSlaveServer.php14
-rw-r--r--maintenance/hiphop/extra-files1
-rw-r--r--maintenance/hiphop/make3
-rw-r--r--maintenance/ibm_db2/foreignkeys.sql5
-rw-r--r--maintenance/ibm_db2/tables.sql984
-rw-r--r--maintenance/importDump.php32
-rw-r--r--maintenance/importImages.php390
-rw-r--r--maintenance/importSiteScripts.php22
-rw-r--r--maintenance/importTextFile.php4
-rw-r--r--maintenance/importUseModWiki.php375
-rw-r--r--maintenance/importUseModWikipedia.php892
-rw-r--r--maintenance/install.php1
-rw-r--r--maintenance/jsparse.php1
-rw-r--r--maintenance/language/StatOutputs.php4
-rw-r--r--maintenance/language/checkLanguage.inc10
-rw-r--r--maintenance/language/function-list.php63
-rw-r--r--maintenance/language/generateCollationData.php23
-rw-r--r--maintenance/language/languages.inc112
-rw-r--r--maintenance/language/messageTypes.inc33
-rw-r--r--maintenance/language/messages.inc280
-rw-r--r--maintenance/language/transstat.php4
-rw-r--r--maintenance/language/writeMessagesArray.inc3
-rw-r--r--maintenance/locking/LockServerDaemon.php617
-rw-r--r--maintenance/locking/file_locks.sql11
-rw-r--r--maintenance/mctest.php5
-rw-r--r--maintenance/mergeMessageFileList.php79
-rw-r--r--maintenance/moveBatch.php3
-rw-r--r--maintenance/mssql/tables.sql10
-rw-r--r--maintenance/mwdocgen.php69
-rw-r--r--maintenance/namespaceDupes.php20
-rw-r--r--maintenance/nextJobDB.php10
-rw-r--r--maintenance/nukeNS.php6
-rw-r--r--maintenance/oracle/archives/patch-ar_sha1_field.sql3
-rw-r--r--maintenance/oracle/archives/patch-config.sql8
-rw-r--r--maintenance/oracle/archives/patch-job_timestamp_field.sql4
-rw-r--r--maintenance/oracle/archives/patch-job_timestamp_index.sql4
-rw-r--r--maintenance/oracle/archives/patch-logging_type_action_index.sql4
-rw-r--r--maintenance/oracle/archives/patch-page_redirect_namespace_len.sql4
-rw-r--r--maintenance/oracle/archives/patch-rev_sha1_field.sql4
-rw-r--r--maintenance/oracle/archives/patch-ug_group-length-increase.sql3
-rw-r--r--maintenance/oracle/archives/patch-us_chunk_inx_field.sql4
-rw-r--r--maintenance/oracle/archives/patch_fk_rename_deferred.sql1
-rw-r--r--maintenance/oracle/archives/patch_rebuild_dupfunc.sql11
-rw-r--r--maintenance/oracle/archives/patch_remove_not_null_empty_defs2.sql3
-rw-r--r--maintenance/oracle/tables.sql75
-rw-r--r--maintenance/orphans.php11
-rw-r--r--maintenance/ourusers.php70
-rw-r--r--maintenance/parse.php110
-rw-r--r--maintenance/populateCategory.php2
-rw-r--r--maintenance/populateImageSha1.php (renamed from maintenance/populateSha1.php)38
-rw-r--r--maintenance/populateLogSearch.php42
-rw-r--r--maintenance/populateLogUsertext.php29
-rw-r--r--maintenance/populateParentId.php39
-rw-r--r--maintenance/populateRevisionLength.php44
-rw-r--r--maintenance/populateRevisionSha1.php185
-rw-r--r--maintenance/postgres/mediawiki_mysql2postgres.pl2
-rw-r--r--maintenance/postgres/tables.sql23
-rw-r--r--maintenance/protect.php25
-rw-r--r--maintenance/proxy_check.php1
-rw-r--r--maintenance/pruneFileCache.php105
-rw-r--r--maintenance/purgeDeletedFiles.php89
-rw-r--r--maintenance/purgeList.php2
-rw-r--r--maintenance/purgeParserCache.php26
-rw-r--r--maintenance/purgeStaleMemcachedText.php4
-rw-r--r--maintenance/reassignEdits.php7
-rw-r--r--maintenance/rebuildFileCache.php67
-rw-r--r--maintenance/rebuildImages.php26
-rw-r--r--maintenance/rebuildInterwiki.php275
-rw-r--r--maintenance/rebuildrecentchanges.php4
-rw-r--r--maintenance/rebuildtextindex.php2
-rw-r--r--maintenance/refreshImageMetadata.php12
-rw-r--r--maintenance/refreshLinks.php15
-rw-r--r--maintenance/removeUnusedAccounts.php2
-rw-r--r--maintenance/renamewiki.php89
-rw-r--r--maintenance/rollbackEdits.php9
-rw-r--r--maintenance/runBatchedQuery.php1
-rw-r--r--maintenance/runJobs.php6
-rw-r--r--maintenance/showJobs.php2
-rw-r--r--maintenance/showStats.php3
-rw-r--r--maintenance/sql.php74
-rw-r--r--maintenance/sqlite.php4
-rw-r--r--maintenance/sqlite/archives/initial-indexes.sql5
-rw-r--r--maintenance/sqlite/archives/patch-drop-user_options.sql31
-rw-r--r--maintenance/sqlite/archives/patch-jobs-add-timestamp.sql2
-rw-r--r--maintenance/sqlite/archives/patch-page_redirect_namespace_len.sql7
-rw-r--r--maintenance/sqlite/archives/patch-ufg_group-length-increase.sql15
-rw-r--r--maintenance/sqlite/archives/patch-ug_group-length-increase.sql15
-rw-r--r--maintenance/stats.php4
-rw-r--r--maintenance/storage/checkStorage.php39
-rw-r--r--maintenance/storage/compressOld.php19
-rw-r--r--maintenance/storage/fixBug20757.php3
-rw-r--r--maintenance/storage/recompressTracked.php7
-rw-r--r--maintenance/tables.sql54
-rw-r--r--maintenance/term/MWTerm.php50
-rw-r--r--maintenance/undelete.php3
-rw-r--r--maintenance/update.php6
-rw-r--r--maintenance/updateCollation.php8
-rw-r--r--maintenance/upgrade1_5.php14
-rw-r--r--maintenance/userOptions.inc34
-rw-r--r--maintenance/userOptions.php2
-rw-r--r--maintenance/wikipedia-interwiki.sql289
-rw-r--r--maintenance/wiktionary-interwiki.sql184
170 files changed, 3875 insertions, 4786 deletions
diff --git a/maintenance/Doxyfile b/maintenance/Doxyfile
index 7d7849c8..b7c1e5e8 100644
--- a/maintenance/Doxyfile
+++ b/maintenance/Doxyfile
@@ -1,4 +1,4 @@
-# Doxyfile 1.5.6
+# Doxyfile 1.7.5.1
#
# Some placeholders have been added for MediaWiki usage:
@@ -8,14 +8,16 @@
# {{SVNSTAT}}
# {{INPUT}}
#
-# A number of MediaWiki-specific aliases are near the end of this file.
# To generate documentation run: php mwdocgen.php --no-extensions
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = MediaWiki
PROJECT_NUMBER = {{CURRENT_VERSION}}
+PROJECT_BRIEF =
+PROJECT_LOGO =
OUTPUT_DIRECTORY = {{OUTPUT_DIRECTORY}}
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
@@ -36,18 +38,47 @@ ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH = {{STRIP_FROM_PATH}}
-STRIP_FROM_INC_PATH =
+STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
+QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
+ALIASES = "type{1}=<b> \1 </b>:" \
+ "types{2}=<b> \1 </b> or <b> \2 </b>:" \
+ "types{3}=<b> \1 </b>, <b> \2 </b>, or <b> \3 </b>:" \
+ "arrayof{2}=<b> Array </b> of \2" \
+ "null=\type{Null}" \
+ "boolean=\type{Boolean}" \
+ "bool=\type{Boolean}" \
+ "integer=\type{Integer}" \
+ "int=\type{Integer}" \
+ "string=\type{String}" \
+ "str=\type{String}" \
+ "mixed=\type{Mixed}" \
+ "access=\par Access:\n" \
+ "private=\access private" \
+ "protected=\access protected" \
+ "public=\access public" \
+ "copyright=\note" \
+ "license=\note"
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
+OPTIMIZE_FOR_FORTRAN = NO
+OPTIMIZE_OUTPUT_VHDL = NO
+EXTENSION_MAPPING =
BUILTIN_STL_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
+SIP_SUPPORT = NO
+IDL_PROPERTY_SUPPORT = NO
DISTRIBUTE_GROUP_DOC = YES
SUBGROUPING = YES
+INLINE_GROUPED_CLASSES = NO
+INLINE_SIMPLE_STRUCTS = NO
+TYPEDEF_HIDES_STRUCT = NO
+SYMBOL_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
@@ -56,6 +87,7 @@ EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
+EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
@@ -64,20 +96,27 @@ INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
+FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
-SORT_BRIEF_DOCS = NO
+SORT_BRIEF_DOCS = YES
+SORT_MEMBERS_CTORS_1ST = NO
+SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
+STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
-ENABLED_SECTIONS =
+ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
-SHOW_DIRECTORIES = NO
+SHOW_DIRECTORIES = YES
+SHOW_FILES = YES
SHOW_NAMESPACES = NO
FILE_VERSION_FILTER = {{SVNSTAT}}
+LAYOUT_FILE =
+CITE_BIB_FILES =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
@@ -87,11 +126,12 @@ WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
-WARN_LOGFILE =
+WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = {{INPUT}}
+INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
@@ -134,16 +174,18 @@ FILE_PATTERNS = *.c \
*.MM \
*.PY
RECURSIVE = YES
-EXCLUDE = {{EXCLUDE}}
+EXCLUDE = {{EXCLUDE}}
EXCLUDE_SYMLINKS = YES
EXCLUDE_PATTERNS = LocalSettings.php AdminSettings.php StartProfiler.php .svn */.git/* {{EXCLUDE_PATTERNS}}
-EXAMPLE_PATH =
+EXCLUDE_SYMBOLS =
+EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
-IMAGE_PATH =
-INPUT_FILTER =
-FILTER_PATTERNS =
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
+FILTER_SOURCE_PATTERNS =
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
@@ -152,6 +194,7 @@ INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
+REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
@@ -159,27 +202,58 @@ VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
-IGNORE_PREFIX =
+IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
-HTML_HEADER =
-HTML_FOOTER =
-HTML_STYLESHEET =
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_EXTRA_FILES =
+HTML_COLORSTYLE_HUE = 220
+HTML_COLORSTYLE_SAT = 100
+HTML_COLORSTYLE_GAMMA = 80
+HTML_TIMESTAMP = YES
HTML_ALIGN_MEMBERS = YES
+HTML_DYNAMIC_SECTIONS = NO
+GENERATE_DOCSET = NO
+DOCSET_FEEDNAME = "Doxygen generated docs"
+DOCSET_BUNDLE_ID = org.doxygen.Project
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
-CHM_FILE =
-HHC_LOCATION =
+CHM_FILE =
+HHC_LOCATION =
GENERATE_CHI = NO
+CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = YES
+GENERATE_QHP = NO
+QCH_FILE =
+QHP_NAMESPACE = org.doxygen.Project
+QHP_VIRTUAL_FOLDER = doc
+QHP_CUST_FILTER_NAME =
+QHP_CUST_FILTER_ATTRS =
+QHP_SECT_FILTER_ATTRS =
+QHG_LOCATION =
+GENERATE_ECLIPSEHELP = NO
+ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = YES
+USE_INLINE_TREES = YES
TREEVIEW_WIDTH = 250
+EXT_LINKS_IN_WINDOW = NO
+FORMULA_FONTSIZE = 10
+FORMULA_TRANSPARENT = YES
+USE_MATHJAX = NO
+MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+MATHJAX_EXTENSIONS =
+SEARCHENGINE = YES
+SERVER_BASED_SEARCH = YES
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
@@ -189,12 +263,15 @@ LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
-EXTRA_PACKAGES =
-LATEX_HEADER =
+EXTRA_PACKAGES =
+LATEX_HEADER =
+LATEX_FOOTER =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
+LATEX_SOURCE_CODE = NO
+LATEX_BIB_STYLE = plain
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
@@ -202,12 +279,12 @@ GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
-RTF_STYLESHEET_FILE =
-RTF_EXTENSIONS_FILE =
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
-GENERATE_MAN = NO
+GENERATE_MAN = {{GENERATE_MAN}}
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
@@ -216,8 +293,8 @@ MAN_LINKS = NO
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
-XML_SCHEMA =
-XML_DTD =
+XML_SCHEMA =
+XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
@@ -229,33 +306,38 @@ GENERATE_AUTOGEN_DEF = NO
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
-PERLMOD_MAKEVAR_PREFIX =
+PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
+# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
-INCLUDE_PATH =
-INCLUDE_FILE_PATTERNS =
-PREDEFINED =
-EXPAND_AS_DEFINED =
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
-# Configuration::additions related to external references
+# Configuration::additions related to external references
#---------------------------------------------------------------------------
-TAGFILES =
+TAGFILES =
GENERATE_TAGFILE = {{OUTPUT_DIRECTORY}}/html/tagfile.xml
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
+# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
+MSCGEN_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = {{HAVE_DOT}}
+DOT_NUM_THREADS = 0
+DOT_FONTNAME = Helvetica
+DOT_FONTSIZE = 10
+DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
@@ -268,34 +350,14 @@ CALLER_GRAPH = YES
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
-DOT_PATH =
-DOTFILE_DIRS =
+INTERACTIVE_SVG = NO
+DOT_PATH =
+DOTFILE_DIRS =
+MSCFILE_DIRS =
+DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine
-#---------------------------------------------------------------------------
-SEARCHENGINE = NO
-
-ALIASES = "type{1}=<b> \1 </b>:" \
- "types{2}=<b> \1 </b> or <b> \2 </b>:" \
- "types{3}=<b> \1 </b>, <b> \2 </b>, or <b> \3 </b>:" \
- "arrayof{2}=<b> Array </b> of \2" \
- "null=\type{Null}" \
- "boolean=\type{Boolean}" \
- "bool=\type{Boolean}" \
- "integer=\type{Integer}" \
- "int=\type{Integer}" \
- "string=\type{String}" \
- "str=\type{String}" \
- "mixed=\type{Mixed}" \
- "access=\par Access:\n" \
- "private=\access private" \
- "protected=\access protected" \
- "public=\access public" \
- "copyright=\note" \
- "license=\note"
diff --git a/maintenance/Maintenance.php b/maintenance/Maintenance.php
index 3618515a..082cf8be 100644
--- a/maintenance/Maintenance.php
+++ b/maintenance/Maintenance.php
@@ -20,6 +20,11 @@
* @defgroup Maintenance Maintenance
*/
+/**
+ * @defgroup MaintenanceArchive Maintenance archives
+ * @ingroup Maintenance
+ */
+
// Define this so scripts can easily find doMaintenance.php
define( 'RUN_MAINTENANCE_IF_MAIN', dirname( __FILE__ ) . '/doMaintenance.php' );
define( 'DO_MAINTENANCE', RUN_MAINTENANCE_IF_MAIN ); // original name, harmless
@@ -130,14 +135,15 @@ abstract class Maintenance {
*/
public static function shouldExecute() {
$bt = debug_backtrace();
- if ( count( $bt ) < 2 ) {
+ $count = count( $bt );
+ if ( $count < 2 ) {
return false; // sanity
}
if ( $bt[0]['class'] !== 'Maintenance' || $bt[0]['function'] !== 'shouldExecute' ) {
return false; // last call should be to this function
}
- $includeFuncs = array( 'require_once', 'require', 'include' );
- for( $i=1; $i < count( $bt ); $i++ ) {
+ $includeFuncs = array( 'require_once', 'require', 'include', 'include_once' );
+ for( $i=1; $i < $count; $i++ ) {
if ( !in_array( $bt[$i]['function'], $includeFuncs ) ) {
return false; // previous calls should all be "requires"
}
@@ -247,6 +253,20 @@ abstract class Maintenance {
*/
protected function setBatchSize( $s = 0 ) {
$this->mBatchSize = $s;
+
+ // If we support $mBatchSize, show the option.
+ // Used to be in addDefaultParams, but in order for that to
+ // work, subclasses would have to call this function in the constructor
+ // before they called parent::__construct which is just weird
+ // (and really wasn't done).
+ if ( $this->mBatchSize ) {
+ $this->addOption( 'batch-size', 'Run this many operations ' .
+ 'per batch, default: ' . $this->mBatchSize, false, true );
+ if ( isset( $this->mParams['batch-size'] ) ) {
+ // This seems a little ugly...
+ $this->mDependantParameters['batch-size'] = $this->mParams['batch-size'];
+ }
+ }
}
/**
@@ -299,8 +319,7 @@ abstract class Maintenance {
} else {
print( $out );
}
- }
- else {
+ } else {
$out = preg_replace( '/\n\z/', '', $out );
$this->outputChanneled( $out, $channel );
}
@@ -427,11 +446,7 @@ abstract class Maintenance {
$this->addOption( 'dbuser', 'The DB user to use for this script', false, true );
$this->addOption( 'dbpass', 'The password to use for this script', false, true );
}
- // If we support $mBatchSize, show the option
- if ( $this->mBatchSize ) {
- $this->addOption( 'batch-size', 'Run this many operations ' .
- 'per batch, default: ' . $this->mBatchSize, false, true );
- }
+
# Save additional script dependant options to display
# them separately in help
$this->mDependantParameters = array_diff_key( $this->mParams, $this->mGenericParameters );
@@ -455,6 +470,9 @@ abstract class Maintenance {
}
}
+ /**
+ * @var $child Maintenance
+ */
$child = new $maintClass();
$child->loadParamsAndArgs( $this->mSelf, $this->mOptions, $this->mArgs );
if ( !is_null( $this->mDb ) ) {
@@ -525,6 +543,7 @@ abstract class Maintenance {
* to allow sysadmins to explicitly set one if they'd prefer to override
* defaults (or for people using Suhosin which yells at you for trying
* to disable the limits)
+ * @return string
*/
public function memoryLimit() {
$limit = $this->getOption( 'memory-limit', 'max' );
@@ -851,6 +870,9 @@ abstract class Maintenance {
$wgDBpassword = $wgDBadminpassword;
if ( $wgDBservers ) {
+ /**
+ * @var $wgDBservers array
+ */
foreach ( $wgDBservers as $i => $server ) {
$wgDBservers[$i]['user'] = $wgDBuser;
$wgDBservers[$i]['password'] = $wgDBpassword;
@@ -890,57 +912,6 @@ abstract class Maintenance {
}
/**
- * Do setup specific to WMF
- */
- public function loadWikimediaSettings() {
- global $IP, $wgNoDBParam, $wgUseNormalUser, $wgConf, $site, $lang;
-
- if ( empty( $wgNoDBParam ) ) {
- # Check if we were passed a db name
- if ( isset( $this->mOptions['wiki'] ) ) {
- $db = $this->mOptions['wiki'];
- } else {
- $db = array_shift( $this->mArgs );
- }
- list( $site, $lang ) = $wgConf->siteFromDB( $db );
-
- # If not, work out the language and site the old way
- if ( is_null( $site ) || is_null( $lang ) ) {
- if ( !$db ) {
- $lang = 'aa';
- } else {
- $lang = $db;
- }
- if ( isset( $this->mArgs[0] ) ) {
- $site = array_shift( $this->mArgs );
- } else {
- $site = 'wikipedia';
- }
- }
- } else {
- $lang = 'aa';
- $site = 'wikipedia';
- }
-
- # This is for the IRC scripts, which now run as the apache user
- # The apache user doesn't have access to the wikiadmin_pass command
- if ( $_ENV['USER'] == 'apache' ) {
- # if ( posix_geteuid() == 48 ) {
- $wgUseNormalUser = true;
- }
-
- putenv( 'wikilang=' . $lang );
-
- ini_set( 'include_path', ".:$IP:$IP/includes:$IP/languages:$IP/maintenance" );
-
- if ( $lang == 'test' && $site == 'wikipedia' ) {
- if ( !defined( 'TESTWIKI' ) ) {
- define( 'TESTWIKI', 1 );
- }
- }
- }
-
- /**
* Generic setup for most installs. Returns the location of LocalSettings
* @return String
*/
@@ -1030,6 +1001,7 @@ abstract class Maintenance {
/**
* Get the maintenance directory.
+ * @return string
*/
protected function getDir() {
return dirname( __FILE__ );
@@ -1177,6 +1149,7 @@ abstract class Maintenance {
* Update the searchindex table for a given pageid
* @param $dbw Database: a database write handle
* @param $pageId Integer: the page ID to update.
+ * @return null|string
*/
public function updateSearchIndexForPage( $dbw, $pageId ) {
// Get current revision
@@ -1208,7 +1181,7 @@ abstract class Maintenance {
} else {
return posix_isatty( $fd );
}
-}
+ }
/**
* Prompt the console for input
@@ -1274,6 +1247,9 @@ abstract class Maintenance {
}
}
+/**
+ * Fake maintenance wrapper, mostly used for the web installer/updater
+ */
class FakeMaintenance extends Maintenance {
protected $mSelf = "FakeMaintenanceScript";
public function execute() {
@@ -1347,4 +1323,4 @@ abstract class LoggedUpdateMaintenance extends Maintenance {
* @return String
*/
abstract protected function getUpdateKey();
-} \ No newline at end of file
+}
diff --git a/maintenance/Makefile b/maintenance/Makefile
index a92751c9..30b568dc 100644
--- a/maintenance/Makefile
+++ b/maintenance/Makefile
@@ -1,6 +1,7 @@
help:
@echo "Run 'make test' to run the parser tests."
@echo "Run 'make doc' to run the doxygen generation."
+ @echo "Run 'make man' to run the doxygen generation with man pages."
test:
php tests/parserTests.php --quiet
@@ -8,3 +9,9 @@ test:
doc:
php mwdocgen.php --all
@echo 'Doc generation done. Look at ./docs/html/'
+
+man:
+ php mwdocgen.php --all --generate-man
+ @echo 'Doc generation done. Look at ./docs/html/ and ./docs/man'
+ @echo 'You might want to update your MANPATH currently:'
+ @echo 'MANPATH: $(MANPATH)'
diff --git a/maintenance/Site.php b/maintenance/Site.php
deleted file mode 100644
index 87d637b4..00000000
--- a/maintenance/Site.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-/**
- * @todo document
- * @ingroup Maintenance
- */
-class Site {
- var $suffix, $lateral, $url;
-
- function __construct( $s, $l, $u ) {
- $this->suffix = $s;
- $this->lateral = $l;
- $this->url = $u;
- }
-
- function getURL( $lang, $urlprotocol ) {
- $xlang = str_replace( '_', '-', $lang );
- return "$urlprotocol//$xlang.{$this->url}/wiki/\$1";
- }
-}
diff --git a/maintenance/addwiki.php b/maintenance/addwiki.php
deleted file mode 100644
index 43f42be5..00000000
--- a/maintenance/addwiki.php
+++ /dev/null
@@ -1,479 +0,0 @@
-<?php
-/**
- * @defgroup Wikimedia Wikimedia
- */
-
-/**
- * Add a new wiki
- * Wikimedia specific!
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- * @ingroup Wikimedia
- */
-
-require_once( dirname( __FILE__ ) . '/Maintenance.php' );
-
-class AddWiki extends Maintenance {
- public function __construct() {
- global $wgNoDBParam;
-
- parent::__construct();
- $this->mDescription = "Add a new wiki to the family. Wikimedia specific!";
- $this->addArg( 'language', 'Language code of new site, e.g. en' );
- $this->addArg( 'site', 'Type of site, e.g. wikipedia' );
- $this->addArg( 'dbname', 'Name of database to create, e.g. enwiki' );
- $this->addArg( 'domain', 'Domain name of the wiki, e.g. en.wikipedia.org' );
-
- $wgNoDBParam = true;
- }
-
- public function getDbType() {
- return Maintenance::DB_ADMIN;
- }
-
- public function execute() {
- global $IP, $wgDefaultExternalStore, $wgVersionNumber;
- if ( !$wgVersionNumber ) { // set in CommonSettings.php
- $this->error( '$wgVersionNumber is not set, please use MWScript.php wrapper.', true );
- }
-
- $lang = $this->getArg( 0 );
- $site = $this->getArg( 1 );
- $dbName = $this->getArg( 2 );
- $domain = $this->getArg( 3 );
- $languageNames = Language::getLanguageNames();
-
- if ( !isset( $languageNames[$lang] ) ) {
- $this->error( "Language $lang not found in Names.php", true );
- }
- $name = $languageNames[$lang];
-
- $dbw = wfGetDB( DB_MASTER );
- $common = "/home/wikipedia/common";
-
- $this->output( "Creating database $dbName for $lang.$site ($name)\n" );
-
- # Set up the database
- $dbw->query( "SET table_type=Innodb" );
- $dbw->query( "CREATE DATABASE $dbName" );
- $dbw->selectDB( $dbName );
-
- $this->output( "Initialising tables\n" );
- $dbw->sourceFile( $this->getDir() . '/tables.sql' );
- $dbw->sourceFile( "$IP/extensions/OAI/update_table.sql" );
- $dbw->sourceFile( "$IP/extensions/AntiSpoof/sql/patch-antispoof.mysql.sql" );
- $dbw->sourceFile( "$IP/extensions/CheckUser/cu_changes.sql" );
- $dbw->sourceFile( "$IP/extensions/CheckUser/cu_log.sql" );
- $dbw->sourceFile( "$IP/extensions/TitleKey/titlekey.sql" );
- $dbw->sourceFile( "$IP/extensions/Oversight/hidden.sql" );
- $dbw->sourceFile( "$IP/extensions/GlobalBlocking/localdb_patches/setup-global_block_whitelist.sql" );
- $dbw->sourceFile( "$IP/extensions/AbuseFilter/abusefilter.tables.sql" );
- $dbw->sourceFile( "$IP/extensions/PrefStats/patches/PrefStats.sql" );
- $dbw->sourceFile( "$IP/extensions/ProofreadPage/ProofreadPage.sql" );
- $dbw->sourceFile( "$IP/extensions/ClickTracking/patches/ClickTrackingEvents.sql" );
- $dbw->sourceFile( "$IP/extensions/ClickTracking/patches/ClickTracking.sql" );
- $dbw->sourceFile( "$IP/extensions/UserDailyContribs/patches/UserDailyContribs.sql" );
-
- $dbw->query( "INSERT INTO site_stats(ss_row_id) VALUES (1)" );
-
- # Initialise external storage
- if ( is_array( $wgDefaultExternalStore ) ) {
- $stores = $wgDefaultExternalStore;
- } elseif ( $wgDefaultExternalStore ) {
- $stores = array( $wgDefaultExternalStore );
- } else {
- $stores = array();
- }
- if ( count( $stores ) ) {
- global $wgDBuser, $wgDBpassword, $wgExternalServers;
- foreach ( $stores as $storeURL ) {
- $m = array();
- if ( !preg_match( '!^DB://(.*)$!', $storeURL, $m ) ) {
- continue;
- }
-
- $cluster = $m[1];
- $this->output( "Initialising external storage $cluster...\n" );
-
- # Hack
- $wgExternalServers[$cluster][0]['user'] = $wgDBuser;
- $wgExternalServers[$cluster][0]['password'] = $wgDBpassword;
-
- $store = new ExternalStoreDB;
- $extdb = $store->getMaster( $cluster );
- $extdb->query( "SET table_type=InnoDB" );
- $extdb->query( "CREATE DATABASE $dbName" );
- $extdb->selectDB( $dbName );
-
- # Hack x2
- $blobsTable = $store->getTable( $extdb );
- $sedCmd = "sed s/blobs\\\\\\>/$blobsTable/ " . $this->getDir() . "/storage/blobs.sql";
- $blobsFile = popen( $sedCmd, 'r' );
- $extdb->sourceStream( $blobsFile );
- pclose( $blobsFile );
- $extdb->commit();
- }
- }
-
- $title = Title::newFromText( wfMessage( 'mainpage' )->inLanguage( $lang )->useDatabase( false )->plain() );
- $this->output( "Writing main page to " . $title->getPrefixedDBkey() . "\n" );
- $article = new Article( $title );
- $ucsite = ucfirst( $site );
-
- $article->doEdit( $this->getFirstArticle( $ucsite, $name ), '', EDIT_NEW | EDIT_AUTOSUMMARY );
-
- $this->output( "Adding to dblists\n" );
-
- # Add to dblist
- $file = fopen( "$common/all.dblist", "a" );
- fwrite( $file, "$dbName\n" );
- fclose( $file );
-
- # Update the sublists
- shell_exec( "cd $common && ./refresh-dblist" );
-
- # Add to wikiversions.dat
- $file = fopen( "$common/wikiversions.dat", "a" );
- fwrite( $file, "$dbName php-$wgVersionNumber\n" );
- fclose( $file );
- # Rebuild wikiversions.cdb
- shell_exec( "cd $common/multiversion && ./refreshWikiversionsCDB" );
-
- # print "Constructing interwiki SQL\n";
- # Rebuild interwiki tables
- # passthru( '/home/wikipedia/conf/interwiki/update' );
-
- $time = wfTimestamp( TS_RFC2822 );
- // These arguments need to be escaped twice: once for echo and once for at
- $escDbName = wfEscapeShellArg( wfEscapeShellArg( $dbName ) );
- $escTime = wfEscapeShellArg( wfEscapeShellArg( $time ) );
- $escUcsite = wfEscapeShellArg( wfEscapeShellArg( $ucsite ) );
- $escName = wfEscapeShellArg( wfEscapeShellArg( $name ) );
- $escLang = wfEscapeShellArg( wfEscapeShellArg( $lang ) );
- $escDomain = wfEscapeShellArg( wfEscapeShellArg( $domain ) );
- shell_exec( "echo notifyNewProjects $escDbName $escTime $escUcsite $escName $escLang $escDomain | at now + 15 minutes" );
-
- $this->output( "Script ended. You still have to:
- * Add any required settings in InitialiseSettings.php
- * Run sync-common-all
- * Run /home/wikipedia/conf/interwiki/update
- " );
- }
-
- private function getFirstArticle( $ucsite, $name ) {
- return <<<EOT
-==This subdomain is reserved for the creation of a [[wikimedia:Our projects|$ucsite]] in '''[[w:en:{$name}|{$name}]]''' language==
-
-* Please '''do not start editing''' this new site. This site has a test project on the [[incubator:|Wikimedia Incubator]] (or on the [[betawikiversity:|BetaWikiversity]] or on the [[oldwikisource:|Old Wikisource]]) and it will be imported to here.
-
-* If you would like to help translating the interface to this language, please do not translate here, but go to [[translatewiki:|translatewiki]], a special wiki for translating the interface. That way everyone can use it on every wiki using the [[mw:|same software]].
-
-* For information about how to edit and for other general help, see [[m:Help:Contents|Help on Wikimedia's Meta-Wiki]] or [[mw:Help:Contents|Help on MediaWiki.org]].
-
-== Sister projects ==
-<span class="plainlinks">
-[http://www.wikipedia.org Wikipedia] |
-[http://www.wiktionary.org Wiktonary] |
-[http://www.wikibooks.org Wikibooks] |
-[http://www.wikinews.org Wikinews] |
-[http://www.wikiquote.org Wikiquote] |
-[http://www.wikisource.org Wikisource]
-[http://www.wikiversity.org Wikiversity]
-</span>
-
-See Wikimedia's [[m:|Meta-Wiki]] for the coordination of these projects.
-
-[[aa:]]
-[[ab:]]
-[[ace:]]
-[[af:]]
-[[ak:]]
-[[als:]]
-[[am:]]
-[[an:]]
-[[ang:]]
-[[ar:]]
-[[arc:]]
-[[arz:]]
-[[as:]]
-[[ast:]]
-[[av:]]
-[[ay:]]
-[[az:]]
-[[ba:]]
-[[bar:]]
-[[bat-smg:]]
-[[bcl:]]
-[[be:]]
-[[be-x-old:]]
-[[bg:]]
-[[bh:]]
-[[bi:]]
-[[bm:]]
-[[bn:]]
-[[bo:]]
-[[bpy:]]
-[[br:]]
-[[bs:]]
-[[bug:]]
-[[bxr:]]
-[[ca:]]
-[[cbk-zam:]]
-[[cdo:]]
-[[ce:]]
-[[ceb:]]
-[[ch:]]
-[[cho:]]
-[[chr:]]
-[[chy:]]
-[[ckb:]]
-[[co:]]
-[[cr:]]
-[[crh:]]
-[[cs:]]
-[[csb:]]
-[[cu:]]
-[[cv:]]
-[[cy:]]
-[[da:]]
-[[de:]]
-[[diq:]]
-[[dk:]]
-[[dsb:]]
-[[dv:]]
-[[dz:]]
-[[ee:]]
-[[el:]]
-[[eml:]]
-[[en:]]
-[[eo:]]
-[[es:]]
-[[et:]]
-[[eu:]]
-[[ext:]]
-[[fa:]]
-[[ff:]]
-[[fi:]]
-[[fiu-vro:]]
-[[fj:]]
-[[fo:]]
-[[fr:]]
-[[frp:]]
-[[fur:]]
-[[fy:]]
-[[ga:]]
-[[gan:]]
-[[gd:]]
-[[gl:]]
-[[glk:]]
-[[gn:]]
-[[got:]]
-[[gu:]]
-[[gv:]]
-[[ha:]]
-[[hak:]]
-[[haw:]]
-[[he:]]
-[[hi:]]
-[[hif:]]
-[[ho:]]
-[[hr:]]
-[[hsb:]]
-[[ht:]]
-[[hu:]]
-[[hy:]]
-[[hz:]]
-[[ia:]]
-[[id:]]
-[[ie:]]
-[[ig:]]
-[[ii:]]
-[[ik:]]
-[[ilo:]]
-[[io:]]
-[[is:]]
-[[it:]]
-[[iu:]]
-[[ja:]]
-[[jbo:]]
-[[jv:]]
-[[ka:]]
-[[kaa:]]
-[[kab:]]
-[[kg:]]
-[[ki:]]
-[[kj:]]
-[[kk:]]
-[[kl:]]
-[[km:]]
-[[kn:]]
-[[ko:]]
-[[kr:]]
-[[ks:]]
-[[ksh:]]
-[[ku:]]
-[[kv:]]
-[[kw:]]
-[[ky:]]
-[[la:]]
-[[lad:]]
-[[lb:]]
-[[lbe:]]
-[[lg:]]
-[[li:]]
-[[lij:]]
-[[lmo:]]
-[[ln:]]
-[[lo:]]
-[[lt:]]
-[[lv:]]
-[[map-bms:]]
-[[mdf:]]
-[[mg:]]
-[[mh:]]
-[[mhr:]]
-[[mi:]]
-[[mk:]]
-[[ml:]]
-[[mn:]]
-[[mo:]]
-[[mr:]]
-[[ms:]]
-[[mt:]]
-[[mus:]]
-[[mwl:]]
-[[my:]]
-[[myv:]]
-[[mzn:]]
-[[na:]]
-[[nan:]]
-[[nap:]]
-[[nds:]]
-[[nds-nl:]]
-[[ne:]]
-[[new:]]
-[[ng:]]
-[[nl:]]
-[[nn:]]
-[[no:]]
-[[nov:]]
-[[nrm:]]
-[[nv:]]
-[[ny:]]
-[[oc:]]
-[[om:]]
-[[or:]]
-[[os:]]
-[[pa:]]
-[[pag:]]
-[[pam:]]
-[[pap:]]
-[[pdc:]]
-[[pi:]]
-[[pih:]]
-[[pl:]]
-[[pms:]]
-[[pnt:]]
-[[pnb:]]
-[[ps:]]
-[[pt:]]
-[[qu:]]
-[[rm:]]
-[[rmy:]]
-[[rn:]]
-[[ro:]]
-[[roa-tara:]]
-[[ru:]]
-[[rup:]]
-[[rw:]]
-[[sa:]]
-[[sah:]]
-[[sc:]]
-[[scn:]]
-[[sco:]]
-[[sd:]]
-[[se:]]
-[[sg:]]
-[[sh:]]
-[[si:]]
-[[simple:]]
-[[sk:]]
-[[sl:]]
-[[sm:]]
-[[sn:]]
-[[so:]]
-[[sq:]]
-[[sr:]]
-[[srn:]]
-[[ss:]]
-[[st:]]
-[[stq:]]
-[[su:]]
-[[sv:]]
-[[sw:]]
-[[szl:]]
-[[ta:]]
-[[te:]]
-[[tet:]]
-[[tg:]]
-[[th:]]
-[[ti:]]
-[[tk:]]
-[[tl:]]
-[[tn:]]
-[[to:]]
-[[tpi:]]
-[[tr:]]
-[[ts:]]
-[[tt:]]
-[[tum:]]
-[[tw:]]
-[[ty:]]
-[[udm:]]
-[[ug:]]
-[[uk:]]
-[[ur:]]
-[[uz:]]
-[[ve:]]
-[[vec:]]
-[[vi:]]
-[[vls:]]
-[[vo:]]
-[[wa:]]
-[[war:]]
-[[wo:]]
-[[wuu:]]
-[[xal:]]
-[[xh:]]
-[[yi:]]
-[[yo:]]
-[[za:]]
-[[zea:]]
-[[zh:]]
-[[zh-classical:]]
-[[zh-min-nan:]]
-[[zh-yue:]]
-[[zu:]]
-
-EOT;
- }
-}
-
-$maintClass = "AddWiki";
-require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/archives/patch-ar_sha1.sql b/maintenance/archives/patch-ar_sha1.sql
new file mode 100644
index 00000000..1c7d8e91
--- /dev/null
+++ b/maintenance/archives/patch-ar_sha1.sql
@@ -0,0 +1,3 @@
+-- Adding ar_sha1 field
+ALTER TABLE /*$wgDBprefix*/archive
+ ADD ar_sha1 varbinary(32) NOT NULL default '';
diff --git a/maintenance/archives/patch-drop-user_options.sql b/maintenance/archives/patch-drop-user_options.sql
new file mode 100644
index 00000000..15b7d278
--- /dev/null
+++ b/maintenance/archives/patch-drop-user_options.sql
@@ -0,0 +1 @@
+ALTER TABLE /*_*/user DROP COLUMN user_options; \ No newline at end of file
diff --git a/maintenance/archives/patch-jobs-add-timestamp.sql b/maintenance/archives/patch-jobs-add-timestamp.sql
new file mode 100644
index 00000000..c5e6e711
--- /dev/null
+++ b/maintenance/archives/patch-jobs-add-timestamp.sql
@@ -0,0 +1,2 @@
+ALTER TABLE /*_*/job ADD COLUMN job_timestamp varbinary(14) NULL default NULL;
+CREATE INDEX /*i*/job_timestamp ON /*_*/job(job_timestamp);
diff --git a/maintenance/archives/patch-logging-type-action-index.sql b/maintenance/archives/patch-logging-type-action-index.sql
new file mode 100644
index 00000000..5edc61a5
--- /dev/null
+++ b/maintenance/archives/patch-logging-type-action-index.sql
@@ -0,0 +1 @@
+CREATE INDEX /*i*/type_action ON /*_*/logging(log_type, log_action, log_timestamp);
diff --git a/maintenance/archives/patch-page_redirect_namespace_len.sql b/maintenance/archives/patch-page_redirect_namespace_len.sql
new file mode 100644
index 00000000..392945fb
--- /dev/null
+++ b/maintenance/archives/patch-page_redirect_namespace_len.sql
@@ -0,0 +1,6 @@
+--
+-- Add the page_redirect_namespace_len index
+--
+
+CREATE INDEX /*i*/page_redirect_namespace_len ON /*_*/page (page_is_redirect, page_namespace, page_len);
+
diff --git a/maintenance/archives/patch-rev_sha1.sql b/maintenance/archives/patch-rev_sha1.sql
new file mode 100644
index 00000000..0100c365
--- /dev/null
+++ b/maintenance/archives/patch-rev_sha1.sql
@@ -0,0 +1,3 @@
+-- Adding rev_sha1 field
+ALTER TABLE /*$wgDBprefix*/revision
+ ADD rev_sha1 varbinary(32) NOT NULL default '';
diff --git a/maintenance/archives/patch-trackbacks.sql b/maintenance/archives/patch-trackbacks.sql
deleted file mode 100644
index e3a47aae..00000000
--- a/maintenance/archives/patch-trackbacks.sql
+++ /dev/null
@@ -1,10 +0,0 @@
-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 BLOB NOT NULL,
- tb_ex TEXT,
- tb_name VARCHAR(255),
-
- INDEX (tb_page)
-);
diff --git a/maintenance/archives/patch-ufg_group-length-increase.sql b/maintenance/archives/patch-ufg_group-length-increase.sql
new file mode 100644
index 00000000..e24cba02
--- /dev/null
+++ b/maintenance/archives/patch-ufg_group-length-increase.sql
@@ -0,0 +1,2 @@
+ALTER TABLE /*_*/user_former_groups
+ MODIFY COLUMN ufg_group varbinary(32) NOT NULL default '';
diff --git a/maintenance/archives/patch-ug_group-length-increase.sql b/maintenance/archives/patch-ug_group-length-increase.sql
new file mode 100644
index 00000000..e944a858
--- /dev/null
+++ b/maintenance/archives/patch-ug_group-length-increase.sql
@@ -0,0 +1,2 @@
+ALTER TABLE /*_*/user_groups
+ MODIFY COLUMN ug_group varbinary(32) NOT NULL default '';
diff --git a/maintenance/archives/patch-uploadstash_chunk.sql b/maintenance/archives/patch-uploadstash_chunk.sql
new file mode 100644
index 00000000..29e41870
--- /dev/null
+++ b/maintenance/archives/patch-uploadstash_chunk.sql
@@ -0,0 +1,3 @@
+-- Adding us_chunk_inx field
+ALTER TABLE /*$wgDBprefix*/uploadstash
+ ADD us_chunk_inx int unsigned NULL;
diff --git a/maintenance/archives/patch-user_former_groups.sql b/maintenance/archives/patch-user_former_groups.sql
index ed18b2b6..ef56db06 100644
--- a/maintenance/archives/patch-user_former_groups.sql
+++ b/maintenance/archives/patch-user_former_groups.sql
@@ -3,7 +3,7 @@
CREATE TABLE /*_*/user_former_groups (
-- Key to user_id
ufg_user int unsigned NOT NULL default 0,
- ufg_group varbinary(16) NOT NULL default ''
+ ufg_group varbinary(32) NOT NULL default ''
) /*$wgDBTableOptions*/;
CREATE UNIQUE INDEX /*i*/ufg_user_group ON /*_*/user_former_groups (ufg_user,ufg_group);
diff --git a/maintenance/attachLatest.php b/maintenance/attachLatest.php
index e6287f43..6e09671a 100644
--- a/maintenance/attachLatest.php
+++ b/maintenance/attachLatest.php
@@ -65,8 +65,8 @@ class AttachLatest extends Maintenance {
$id = $revision->getId();
$this->output( wfWikiID() . " $pageId [[$name]] latest time $latestTime, rev id $id\n" );
if ( $this->hasOption( 'fix' ) ) {
- $article = new Article( $title );
- $article->updateRevisionOn( $dbw, $revision );
+ $page = WikiPage::factory( $title );
+ $page->updateRevisionOn( $dbw, $revision );
}
$n++;
}
diff --git a/maintenance/backup.inc b/maintenance/backup.inc
index 4cb9c58a..9f67a1ac 100644
--- a/maintenance/backup.inc
+++ b/maintenance/backup.inc
@@ -47,6 +47,8 @@ class BackupDumper {
var $skipFooter = false; // don't output </mediawiki>
var $startId = 0;
var $endId = 0;
+ var $revStartId = 0;
+ var $revEndId = 0;
var $sink = null; // Output filters
var $stubText = false; // include rev_text_id instead of text; for 2-pass dump
var $dumpUploads = false;
@@ -56,7 +58,14 @@ class BackupDumper {
var $revCountLast = 0;
var $ID = 0;
- function BackupDumper( $args ) {
+ var $outputTypes = array(), $filterTypes = array();
+
+ /**
+ * @var LoadBalancer
+ */
+ protected $lb;
+
+ function __construct( $args ) {
$this->stderr = fopen( "php://stderr", "wt" );
// Built-in output and filter plugins
@@ -247,6 +256,7 @@ class BackupDumper {
* @todo Fixme: the --server parameter is currently not respected, as it
* doesn't seem terribly easy to ask the load balancer for a particular
* connection by name.
+ * @return DatabaseBase
*/
function backupDb() {
$this->lb = wfGetLBFactory()->newMainLB();
@@ -332,7 +342,7 @@ class BackupDumper {
}
class ExportProgressFilter extends DumpFilter {
- function ExportProgressFilter( &$sink, &$progress ) {
+ function __construct( &$sink, &$progress ) {
parent::__construct( $sink );
$this->progress = $progress;
}
diff --git a/maintenance/backupPrefetch.inc b/maintenance/backupPrefetch.inc
index 93f75c65..0e12a1ce 100644
--- a/maintenance/backupPrefetch.inc
+++ b/maintenance/backupPrefetch.inc
@@ -133,6 +133,7 @@ class BaseDump {
/**
* @access private
+ * @return string
*/
function nextText() {
$this->skipTo( 'text' );
@@ -141,6 +142,9 @@ class BaseDump {
/**
* @access private
+ * @param $name string
+ * @param $parent string
+ * @return bool|null
*/
function skipTo( $name, $parent = 'page' ) {
if ( $this->atEnd ) {
@@ -192,6 +196,7 @@ class BaseDump {
/**
* @access private
+ * @return null
*/
function close() {
$this->reader->close();
diff --git a/maintenance/benchmarks/Benchmarker.php b/maintenance/benchmarks/Benchmarker.php
index 57fb8759..0056c3c7 100644
--- a/maintenance/benchmarks/Benchmarker.php
+++ b/maintenance/benchmarks/Benchmarker.php
@@ -1,6 +1,7 @@
<?php
/**
* @defgroup Benchmark Benchmark
+ * @ingroup Maintenance
*/
/**
@@ -23,7 +24,7 @@
*
* @todo Report PHP version, OS ..
* @file
- * @ingroup Maintenance Benchmark
+ * @ingroup Benchmark
*/
require_once( dirname( __FILE__ ) . '/../Maintenance.php' );
diff --git a/maintenance/benchmarks/bench_HTTP_HTTPS.php b/maintenance/benchmarks/bench_HTTP_HTTPS.php
index 0038b2d1..cf62aadb 100644
--- a/maintenance/benchmarks/bench_HTTP_HTTPS.php
+++ b/maintenance/benchmarks/bench_HTTP_HTTPS.php
@@ -18,8 +18,8 @@
* http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @ingroup Maintenance
- * @author Platonides
+ * @ingroup Benchmark
+ * @author Platonides
*/
require_once( dirname( __FILE__ ) . '/Benchmarker.php' );
diff --git a/maintenance/benchmarks/bench_delete_truncate.php b/maintenance/benchmarks/bench_delete_truncate.php
index 9fe9bea9..71385520 100644
--- a/maintenance/benchmarks/bench_delete_truncate.php
+++ b/maintenance/benchmarks/bench_delete_truncate.php
@@ -1,4 +1,8 @@
<?php
+/**
+ * @file
+ * @ingroup Benchmark
+ */
require_once( dirname( __FILE__ ) . '/Benchmarker.php' );
diff --git a/maintenance/benchmarks/bench_if_switch.php b/maintenance/benchmarks/bench_if_switch.php
index 11c00b3c..dafce050 100644
--- a/maintenance/benchmarks/bench_if_switch.php
+++ b/maintenance/benchmarks/bench_if_switch.php
@@ -18,8 +18,8 @@
* http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @ingroup Maintenance
- * @author Platonides
+ * @ingroup Benchmark
+ * @author Platonides
*/
require_once( dirname( __FILE__ ) . '/Benchmarker.php' );
diff --git a/maintenance/benchmarks/bench_strtr_str_replace.php b/maintenance/benchmarks/bench_strtr_str_replace.php
index ae576981..73ace2bd 100644
--- a/maintenance/benchmarks/bench_strtr_str_replace.php
+++ b/maintenance/benchmarks/bench_strtr_str_replace.php
@@ -1,4 +1,8 @@
<?php
+/**
+ * @file
+ * @ingroup Benchmark
+ */
require_once( dirname( __FILE__ ) . '/Benchmarker.php' );
diff --git a/maintenance/benchmarks/bench_wfIsWindows.php b/maintenance/benchmarks/bench_wfIsWindows.php
index 4c35221d..4caebc5e 100644
--- a/maintenance/benchmarks/bench_wfIsWindows.php
+++ b/maintenance/benchmarks/bench_wfIsWindows.php
@@ -18,8 +18,8 @@
* http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @ingroup Maintenance
- * @author Platonides
+ * @ingroup Benchmark
+ * @author Platonides
*/
require_once( dirname( __FILE__ ) . '/Benchmarker.php' );
diff --git a/maintenance/benchmarks/benchmarkHooks.php b/maintenance/benchmarks/benchmarkHooks.php
new file mode 100644
index 00000000..4ec26168
--- /dev/null
+++ b/maintenance/benchmarks/benchmarkHooks.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Benchmark
+ */
+
+require_once( dirname( __FILE__ ) . '/Benchmarker.php' );
+
+class BenchmarkHooks extends Benchmarker {
+
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = 'Benchmark MediaWiki Hooks.';
+ }
+
+ public function execute() {
+ global $wgHooks;
+ $wgHooks['Test'] = array();
+
+ $time = $this->benchHooks();
+ $this->output( 'Empty hook: ' . $time . "\n" );
+
+ $wgHooks['Test'][] = array( $this, 'test' );
+ $time = $this->benchHooks();
+ $this->output( 'Loaded (one) hook: ' . $time . "\n" );
+
+ for( $i = 0; $i < 9; $i++ ) {
+ $wgHooks['Test'][] = array( $this, 'test' );
+ }
+ $time = $this->benchHooks();
+ $this->output( 'Loaded (ten) hook: ' . $time . "\n" );
+
+ for( $i = 0; $i < 90; $i++ ) {
+ $wgHooks['Test'][] = array( $this, 'test' );
+ }
+ $time = $this->benchHooks();
+ $this->output( 'Loaded (one hundred) hook: ' . $time . "\n" );
+ $this->output( "\n" );
+ }
+
+ /**
+ * @param $trials int
+ * @return string
+ */
+ private function benchHooks( $trials = 10 ) {
+ $start = wfTime();
+ for ( $i = 0; $i < $trials; $i++ ) {
+ wfRunHooks( 'Test' );
+ }
+ $delta = wfTime() - $start;
+ $pertrial = $delta / $trials;
+ return sprintf( "Took %6.2fs",
+ $pertrial );
+ }
+
+ /**
+ * @return bool
+ */
+ public function test() {
+ return true;
+ }
+}
+
+$maintClass = 'BenchmarkHooks';
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/benchmarks/benchmarkPurge.php b/maintenance/benchmarks/benchmarkPurge.php
index 4ab7aa10..e9d2ec7a 100644
--- a/maintenance/benchmarks/benchmarkPurge.php
+++ b/maintenance/benchmarks/benchmarkPurge.php
@@ -18,7 +18,7 @@
* http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @ingroup Maintenance
+ * @ingroup Benchmark
*/
require_once( dirname( __FILE__ ) . '/Benchmarker.php' );
@@ -54,6 +54,7 @@ class BenchmarkPurge extends Benchmarker {
* to benchmark Squid response times.
* @param $urls array A bunch of URLs to purge
* @param $trials int How many times to run the test?
+ * @return string
*/
private function benchSquid( $urls, $trials = 1 ) {
$start = wfTime();
@@ -70,6 +71,7 @@ class BenchmarkPurge extends Benchmarker {
/**
* Get an array of randomUrl()'s.
* @param $length int How many urls to add to the array
+ * @return array
*/
private function randomUrlList( $length ) {
$list = array();
@@ -82,6 +84,7 @@ class BenchmarkPurge extends Benchmarker {
/**
* Return a random URL of the wiki. Not necessarily an actual title in the
* database, but at least a URL that looks like one.
+ * @return string
*/
private function randomUrl() {
global $wgServer, $wgArticlePath;
@@ -91,6 +94,7 @@ class BenchmarkPurge extends Benchmarker {
/**
* Create a random title string (not necessarily a Title object).
* For use with randomUrl().
+ * @return string
*/
private function randomTitle() {
$str = '';
diff --git a/maintenance/changePassword.php b/maintenance/changePassword.php
index ef87dfbd..cfcac406 100644
--- a/maintenance/changePassword.php
+++ b/maintenance/changePassword.php
@@ -43,7 +43,7 @@ class ChangePassword extends Maintenance {
} else {
$this->error( "A \"user\" or \"userid\" must be set to change the password for" , true );
}
- if ( !$user->getId() ) {
+ if ( !$user || !$user->getId() ) {
$this->error( "No such user: " . $this->getOption( 'user' ), true );
}
try {
diff --git a/maintenance/checkImages.php b/maintenance/checkImages.php
index 96b93f22..484217d9 100644
--- a/maintenance/checkImages.php
+++ b/maintenance/checkImages.php
@@ -49,7 +49,9 @@ class CheckImages extends Maintenance {
$this->output( "{$row->img_name}: not locally accessible\n" );
continue;
}
- $stat = @stat( $file->getPath() );
+ wfSuppressWarnings();
+ $stat = stat( $file->getPath() );
+ wfRestoreWarnings();
if ( !$stat ) {
$this->output( "{$row->img_name}: missing\n" );
continue;
diff --git a/maintenance/checkSyntax.php b/maintenance/checkSyntax.php
index 83f73be5..cc4e5af5 100644
--- a/maintenance/checkSyntax.php
+++ b/maintenance/checkSyntax.php
@@ -165,6 +165,8 @@ class CheckSyntax extends Maintenance {
/**
* Returns true if $file is of a type we can check
+ * @param $file string
+ * @return bool
*/
private function isSuitableFile( $file ) {
$file = str_replace( '\\', '/', $file );
@@ -181,6 +183,8 @@ class CheckSyntax extends Maintenance {
/**
* Add given path to file list, searching it in include path if needed
+ * @param $path string
+ * @return bool
*/
private function addPath( $path ) {
global $IP;
@@ -188,8 +192,10 @@ class CheckSyntax extends Maintenance {
}
/**
- * Add given file to file list, or, if it's a directory, add its content
- */
+ * Add given file to file list, or, if it's a directory, add its content
+ * @param $path string
+ * @return bool
+ */
private function addFileOrDir( $path ) {
if ( is_dir( $path ) ) {
$this->addDirectoryContent( $path );
diff --git a/maintenance/cleanupCaps.php b/maintenance/cleanupCaps.php
index 2d945a52..6f8e180c 100644
--- a/maintenance/cleanupCaps.php
+++ b/maintenance/cleanupCaps.php
@@ -40,11 +40,15 @@ class CapsCleanup extends TableCleanup {
public function execute() {
global $wgCapitalLinks, $wgUser;
+
+ if ( $wgCapitalLinks ) {
+ $this->error( "\$wgCapitalLinks is on -- no need for caps links cleanup.", true );
+ }
+
+ $wgUser = User::newFromName( 'Conversion script' );
+
$this->namespace = intval( $this->getOption( 'namespace', 0 ) );
$this->dryrun = $this->hasOption( 'dry-run' );
- $wgUser->setName( 'Conversion script' );
- if ( $wgCapitalLinks )
- $this->error( "\$wgCapitalLinks is on -- no need for caps links cleanup.", true );
$this->runTable( array(
'table' => 'page',
@@ -88,9 +92,8 @@ class CapsCleanup extends TableCleanup {
return $this->processRow( $row );
}
}
- } else {
- $this->progress( 0 );
}
+ return $this->progress( 0 );
}
}
diff --git a/maintenance/cleanupImages.php b/maintenance/cleanupImages.php
index c8e90958..81d1c85b 100644
--- a/maintenance/cleanupImages.php
+++ b/maintenance/cleanupImages.php
@@ -73,8 +73,9 @@ class ImageCleanup extends TableCleanup {
if ( is_null( $title ) ) {
$this->output( "page $source ($cleaned) is illegal.\n" );
$safe = $this->buildSafeTitle( $cleaned );
- if ( $safe === false )
+ if ( $safe === false ) {
return $this->progress( 0 );
+ }
$this->pokeFile( $source, $safe );
return $this->progress( 1 );
}
@@ -86,9 +87,12 @@ class ImageCleanup extends TableCleanup {
return $this->progress( 1 );
}
- $this->progress( 0 );
+ return $this->progress( 0 );
}
+ /**
+ * @param $name string
+ */
private function killRow( $name ) {
if ( $this->dryrun ) {
$this->output( "DRY RUN: would delete bogus row '$name'\n" );
@@ -120,7 +124,8 @@ class ImageCleanup extends TableCleanup {
$path = $this->filePath( $orig );
if ( !file_exists( $path ) ) {
$this->output( "missing file: $path\n" );
- return $this->killRow( $orig );
+ $this->killRow( $orig );
+ return;
}
$db = wfGetDB( DB_MASTER );
@@ -135,7 +140,7 @@ class ImageCleanup extends TableCleanup {
$version = 0;
$final = $new;
$conflict = ( $this->imageExists( $final, $db ) ||
- ( $this->pageExists( $orig, $db ) && $this->pageExists( $final, $db ) ) );
+ ( $this->pageExists( $orig, $db ) && $this->pageExists( $final, $db ) ) );
while ( $conflict ) {
$this->output( "Rename conflicts with '$final'...\n" );
@@ -166,8 +171,8 @@ class ImageCleanup extends TableCleanup {
__METHOD__ );
$dir = dirname( $finalPath );
if ( !file_exists( $dir ) ) {
- if ( !wfMkdirParents( $dir ) ) {
- $this->log( "RENAME FAILED, COULD NOT CREATE $dir" );
+ if ( !wfMkdirParents( $dir, null, __METHOD__ ) ) {
+ $this->output( "RENAME FAILED, COULD NOT CREATE $dir" );
$db->rollback();
return;
}
diff --git a/maintenance/cleanupSpam.php b/maintenance/cleanupSpam.php
index 8561281d..ca1e302b 100644
--- a/maintenance/cleanupSpam.php
+++ b/maintenance/cleanupSpam.php
@@ -36,6 +36,9 @@ class CleanupSpam extends Maintenance {
$username = wfMsg( 'spambot_username' );
$wgUser = User::newFromName( $username );
+ if ( !$wgUser ) {
+ $this->error( "Invalid username", true );
+ }
// Create the user if necessary
if ( !$wgUser->getId() ) {
$wgUser->addToDatabase();
@@ -91,36 +94,29 @@ class CleanupSpam extends Maintenance {
$this->output( $title->getPrefixedDBkey() . " ..." );
$rev = Revision::newFromTitle( $title );
- $revId = $rev->getId();
- $currentRevId = $revId;
+ $currentRevId = $rev->getId();
- while ( $rev && LinkFilter::matchEntry( $rev->getText() , $domain ) ) {
- # Revision::getPrevious can't be used in this way before MW 1.6 (Revision.php 1.26)
- # $rev = $rev->getPrevious();
- $revId = $title->getPreviousRevisionID( $revId );
- if ( $revId ) {
- $rev = Revision::newFromTitle( $title, $revId );
- } else {
- $rev = false;
- }
+ while ( $rev && ( $rev->isDeleted( Revision::DELETED_TEXT ) || LinkFilter::matchEntry( $rev->getText() , $domain ) ) ) {
+ $rev = $rev->getPrevious();
}
- if ( $revId == $currentRevId ) {
+
+ if ( $rev && $rev->getId() == $currentRevId ) {
// The regex didn't match the current article text
// This happens e.g. when a link comes from a template rather than the page itself
$this->output( "False match\n" );
} else {
$dbw = wfGetDB( DB_MASTER );
$dbw->begin();
+ $page = WikiPage::factory( $title );
if ( !$rev ) {
// Didn't find a non-spammy revision, blank the page
$this->output( "blanking\n" );
- $article = new Article( $title );
- $article->doEdit( '', wfMsg( 'spam_blanking', $domain ) );
+ $page->doEdit( '', wfMsgForContent( 'spam_blanking', $domain ) );
} else {
// Revert to this revision
$this->output( "reverting\n" );
- $article = new Article( $title );
- $article->doEdit( $rev->getText(), wfMsg( 'spam_reverting', $domain ), EDIT_UPDATE );
+ $page->doEdit( $rev->getText(), wfMsgForContent( 'spam_reverting', $domain ),
+ EDIT_UPDATE, $rev->getId() );
}
$dbw->commit();
}
diff --git a/maintenance/cleanupTable.inc b/maintenance/cleanupTable.inc
index f63c6d74..1c279762 100644
--- a/maintenance/cleanupTable.inc
+++ b/maintenance/cleanupTable.inc
@@ -43,7 +43,7 @@ class TableCleanup extends Maintenance {
public function execute() {
global $wgUser;
- $wgUser->setName( 'Conversion script' );
+ $wgUser = User::newFromName( 'Conversion script' );
$this->dryrun = $this->hasOption( 'dry-run' );
if ( $this->dryrun ) {
$this->output( "Checking for bad titles...\n" );
diff --git a/maintenance/cleanupTitles.php b/maintenance/cleanupTitles.php
index f03b7957..4fc6415e 100644
--- a/maintenance/cleanupTitles.php
+++ b/maintenance/cleanupTitles.php
@@ -145,8 +145,7 @@ class TitleCleanup extends TableCleanup {
),
array( 'page_id' => $row->page_id ),
__METHOD__ );
- $linkCache = LinkCache::singleton();
- $linkCache->clear();
+ LinkCache::singleton()->clear();
}
}
}
diff --git a/maintenance/cleanupUploadStash.php b/maintenance/cleanupUploadStash.php
index 1926c05a..5f57ffdf 100644
--- a/maintenance/cleanupUploadStash.php
+++ b/maintenance/cleanupUploadStash.php
@@ -32,44 +32,52 @@ class UploadStashCleanup extends Maintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Clean up abandoned files in temporary uploaded file stash";
- }
+ }
- public function execute() {
+ public function execute() {
$repo = RepoGroup::singleton()->getLocalRepo();
-
+
$dbr = $repo->getSlaveDb();
-
+
+ // how far back should this look for files to delete?
+ global $wgUploadStashMaxAge;
+
$this->output( "Getting list of files to clean up...\n" );
$res = $dbr->select(
'uploadstash',
'us_key',
- 'us_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( time() - UploadStash::REPO_AGE * 3600 ) ),
+ 'us_timestamp < ' . $dbr->addQuotes( $dbr->timestamp( time() - $wgUploadStashMaxAge ) ),
__METHOD__
);
-
+
if( !is_object( $res ) || $res->numRows() == 0 ) {
+ $this->output( "No files to cleanup!\n" );
// nothing to do.
- return false;
+ return;
}
// finish the read before starting writes.
$keys = array();
- foreach($res as $row) {
+ foreach( $res as $row ) {
array_push( $keys, $row->us_key );
}
-
+
$this->output( 'Removing ' . count($keys) . " file(s)...\n" );
// this could be done some other, more direct/efficient way, but using
// UploadStash's own methods means it's less likely to fall accidentally
// out-of-date someday
$stash = new UploadStash( $repo );
-
+
foreach( $keys as $key ) {
- $stash->getFile( $key, true );
- $stash->removeFileNoAuth( $key );
+ try {
+ $stash->getFile( $key, true );
+ $stash->removeFileNoAuth( $key );
+ } catch ( UploadStashBadPathException $ex ) {
+ $this->output( "Failed removing stashed upload with key: $key\n" );
+ }
}
}
}
$maintClass = "UploadStashCleanup";
-require_once( RUN_MAINTENANCE_IF_MAIN ); \ No newline at end of file
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/clear_stats.php b/maintenance/clear_stats.php
index 8f91864e..61314e67 100644
--- a/maintenance/clear_stats.php
+++ b/maintenance/clear_stats.php
@@ -36,7 +36,6 @@ class clear_stats extends Maintenance {
$wgMemc->delete( "$db:stats:request_with_session" );
$wgMemc->delete( "$db:stats:request_without_session" );
$wgMemc->delete( "$db:stats:pcache_hit" );
- $wgMemc->delete( "$db:stats:pcache_miss_invalid" );
$wgMemc->delete( "$db:stats:pcache_miss_expired" );
$wgMemc->delete( "$db:stats:pcache_miss_absent" );
$wgMemc->delete( "$db:stats:pcache_miss_stub" );
@@ -46,6 +45,8 @@ class clear_stats extends Maintenance {
$wgMemc->delete( "$db:stats:diff_cache_hit" );
$wgMemc->delete( "$db:stats:diff_cache_miss" );
$wgMemc->delete( "$db:stats:diff_uncacheable" );
+ $wgMemc->delete( "$db:stats:job-insert" );
+ $wgMemc->delete( "$db:stats:job-pop" );
}
}
}
diff --git a/maintenance/commandLine.inc b/maintenance/commandLine.inc
index f57c0b67..c7adbfbc 100644
--- a/maintenance/commandLine.inc
+++ b/maintenance/commandLine.inc
@@ -21,7 +21,7 @@
* @ingroup Maintenance
*/
-require( dirname( __FILE__ ) . '/Maintenance.php' );
+require_once( dirname( __FILE__ ) . '/Maintenance.php' );
global $optionsWithArgs;
if ( !isset( $optionsWithArgs ) ) {
@@ -37,19 +37,13 @@ class CommandLineInc extends Maintenance {
}
}
- public function getDbType() {
- global $wgUseNormalUser;
-
- return ( isset( $wgUseNormalUser ) && $wgUseNormalUser ) ?
- Maintenance::DB_STD : Maintenance::DB_ADMIN;
- }
-
/**
* No help, it would just be misleading since it misses custom options
*/
protected function maybeHelp( $force = false ) {
- if ( !$force )
+ if ( !$force ) {
return;
+ }
parent::maybeHelp( true );
}
diff --git a/maintenance/convertUserOptions.php b/maintenance/convertUserOptions.php
index f46f710d..da6ff9b6 100644
--- a/maintenance/convertUserOptions.php
+++ b/maintenance/convertUserOptions.php
@@ -33,27 +33,38 @@ class ConvertUserOptions extends Maintenance {
}
public function execute() {
- $this->output( "Beginning batch conversion of user options.\n" );
+ $this->output( "...batch conversion of user_options: " );
$id = 0;
$dbw = wfGetDB( DB_MASTER );
+ if ( !$dbw->fieldExists( 'user', 'user_options', __METHOD__ ) ) {
+ $this->output( "nothing to migrate. " );
+ return;
+ }
while ( $id !== null ) {
- $idCond = 'user_id>' . $dbw->addQuotes( $id );
- $optCond = "user_options!=" . $dbw->addQuotes( '' ); // For compatibility
+ $idCond = 'user_id > ' . $dbw->addQuotes( $id );
+ $optCond = "user_options != " . $dbw->addQuotes( '' ); // For compatibility
$res = $dbw->select( 'user', '*',
- array( $optCond, $idCond ), __METHOD__,
- array( 'LIMIT' => 50, 'FOR UPDATE' ) );
+ array( $optCond, $idCond ), __METHOD__,
+ array( 'LIMIT' => 50, 'FOR UPDATE' )
+ );
$id = $this->convertOptionBatch( $res, $dbw );
$dbw->commit();
wfWaitForSlaves();
- if ( $id )
+ if ( $id ) {
$this->output( "--Converted to ID $id\n" );
+ }
}
- $this->output( "Conversion done. Converted " . $this->mConversionCount . " user records.\n" );
+ $this->output( "done. Converted " . $this->mConversionCount . " user records.\n" );
}
+ /**
+ * @param $res
+ * @param $dbw DatabaseBase
+ * @return null|int
+ */
function convertOptionBatch( $res, $dbw ) {
$id = null;
foreach ( $res as $row ) {
@@ -62,6 +73,14 @@ class ConvertUserOptions extends Maintenance {
$u = User::newFromRow( $row );
$u->saveSettings();
+
+ // Do this here as saveSettings() doesn't set user_options to '' anymore!
+ $dbw->update(
+ 'user',
+ array( 'user_options' => '' ),
+ array( 'user_id' => $row->user_id ),
+ __METHOD__
+ );
$id = $row->user_id;
}
diff --git a/maintenance/deleteBatch.php b/maintenance/deleteBatch.php
index eb2e1f34..56fe13a4 100644
--- a/maintenance/deleteBatch.php
+++ b/maintenance/deleteBatch.php
@@ -49,9 +49,16 @@ class DeleteBatch extends Maintenance {
chdir( $oldCwd );
# Options processing
- $user = $this->getOption( 'u', 'Delete page script' );
+ $username = $this->getOption( 'u', 'Delete page script' );
$reason = $this->getOption( 'r', '' );
$interval = $this->getOption( 'i', 0 );
+
+ $user = User::newFromName( $username );
+ if ( !$user ) {
+ $this->error( "Invalid username", true );
+ }
+ $wgUser = $user;
+
if ( $this->hasArg() ) {
$file = fopen( $this->getArg(), 'r' );
} else {
@@ -62,7 +69,7 @@ class DeleteBatch extends Maintenance {
if ( !$file ) {
$this->error( "Unable to read file, exiting", true );
}
- $wgUser = User::newFromName( $user );
+
$dbw = wfGetDB( DB_MASTER );
# Handle each entry
@@ -71,31 +78,27 @@ class DeleteBatch extends Maintenance {
if ( $line == '' ) {
continue;
}
- $page = Title::newFromText( $line );
- if ( is_null( $page ) ) {
+ $title = Title::newFromText( $line );
+ if ( is_null( $title ) ) {
$this->output( "Invalid title '$line' on line $linenum\n" );
continue;
}
- if ( !$page->exists() ) {
+ if ( !$title->exists() ) {
$this->output( "Skipping nonexistent page '$line'\n" );
continue;
}
-
- $this->output( $page->getPrefixedText() );
+ $this->output( $title->getPrefixedText() );
$dbw->begin();
- if ( $page->getNamespace() == NS_FILE ) {
- $art = new ImagePage( $page );
- $img = wfFindFile( $art->mTitle );
- if ( !$img
- || !$img->isLocal()
- || !$img->delete( $reason ) ) {
- $this->output( " FAILED to delete image file... " );
+ if ( $title->getNamespace() == NS_FILE ) {
+ $img = wfFindFile( $title );
+ if ( $img && $img->isLocal() && !$img->delete( $reason ) ) {
+ $this->output( " FAILED to delete associated file... " );
}
- } else {
- $art = new Article( $page );
}
- $success = $art->doDeleteArticle( $reason );
+ $page = WikiPage::factory( $title );
+ $error = '';
+ $success = $page->doDeleteArticle( $reason, false, 0, false, $error, $user );
$dbw->commit();
if ( $success ) {
$this->output( " Deleted!\n" );
@@ -107,7 +110,7 @@ class DeleteBatch extends Maintenance {
sleep( $interval );
}
wfWaitForSlaves();
-}
+ }
}
}
diff --git a/maintenance/deleteDefaultMessages.php b/maintenance/deleteDefaultMessages.php
index a33921b1..21d7755f 100644
--- a/maintenance/deleteDefaultMessages.php
+++ b/maintenance/deleteDefaultMessages.php
@@ -31,9 +31,7 @@ class DeleteDefaultMessages extends Maintenance {
}
public function execute() {
-
- $user = 'MediaWiki default';
- $reason = 'No longer required';
+ global $wgUser;
$this->output( "Checking existence of old default messages..." );
$dbr = wfGetDB( DB_SLAVE );
@@ -54,9 +52,12 @@ class DeleteDefaultMessages extends Maintenance {
# Deletions will be made by $user temporarly added to the bot group
# in order to hide it in RecentChanges.
- global $wgUser;
- $wgUser = User::newFromName( $user );
- $wgUser->addGroup( 'bot' );
+ $user = User::newFromName( 'MediaWiki default' );
+ if ( !$user ) {
+ $this->error( "Invalid username", true );
+ }
+ $user->addGroup( 'bot' );
+ $wgUser = $user;
# Handle deletion
$this->output( "\n...deleting old default messages (this may take a long time!)...", 'msg' );
@@ -66,9 +67,10 @@ class DeleteDefaultMessages extends Maintenance {
wfWaitForSlaves();
$dbw->ping();
$title = Title::makeTitle( $row->page_namespace, $row->page_title );
- $article = new Article( $title );
+ $page = WikiPage::factory( $title );
$dbw->begin();
- $article->doDeleteArticle( $reason );
+ $error = ''; // Passed by ref
+ $page->doDeleteArticle( 'No longer required', false, 0, false, $error, $user );
$dbw->commit();
}
diff --git a/maintenance/dev/README b/maintenance/dev/README
new file mode 100644
index 00000000..ca47d136
--- /dev/null
+++ b/maintenance/dev/README
@@ -0,0 +1,7 @@
+maintenance/dev/ scripts can help quickly setup a local MediaWiki for development purposes.
+
+Wikis setup in this way are NOT meant to be publicly available. They use a development database not acceptible for use in production. Place a sqlite database in an unsafe location a real wiki should never place it in. And use predictable default logins for the initial administrator user.
+
+Running maintenance/dev/install.sh will download and install a local copy of php 5.4, install a sqlite powered instance of MW for development, and then start up a local webserver to view the wiki.
+
+After installation you can bring the webserver back up at any time you want with maintenance/dev/start.sh
diff --git a/maintenance/dev/includes/php.sh b/maintenance/dev/includes/php.sh
new file mode 100644
index 00000000..3021b93b
--- /dev/null
+++ b/maintenance/dev/includes/php.sh
@@ -0,0 +1,12 @@
+# Include-able script to determine the location of our php if any
+
+if [ -d "$DEV/php" -a -x "$DEV/php/bin/php" ]; then
+ # Quick local copy
+ PHP="$DEV/php/bin/php"
+elif [ -d "$HOME/.mediawiki/php" -a -x "$HOME/.mediawiki/php/bin/php" ]; then
+ # Previous home directory location to install php in
+ PHP="$HOME/.mediawiki/php/bin/php"
+elif [ -d "$HOME/.mwphp" -a -x "$HOME/.mwphp/bin/php" ]; then
+ # Previous home directory location to install php in
+ PHP="$HOME/.mwphp/bin/php"
+fi
diff --git a/maintenance/dev/includes/require-php.sh b/maintenance/dev/includes/require-php.sh
new file mode 100644
index 00000000..470e6eb8
--- /dev/null
+++ b/maintenance/dev/includes/require-php.sh
@@ -0,0 +1,8 @@
+# Include-able script to require that we have a known php binary we can execute
+
+. "$DEV/includes/php.sh"
+
+if [ "x$PHP" == "x" -o ! -x "$PHP" ]; then
+ echo "Local copy of PHP is not installed"
+ exit 1
+fi
diff --git a/maintenance/dev/includes/router.php b/maintenance/dev/includes/router.php
new file mode 100644
index 00000000..f6a062b6
--- /dev/null
+++ b/maintenance/dev/includes/router.php
@@ -0,0 +1,82 @@
+<?php
+
+# Router for the php cli-server built-in webserver
+# http://ca2.php.net/manual/en/features.commandline.webserver.php
+
+if ( php_sapi_name() != 'cli-server' ) {
+ die( "This script can only be run by php's cli-server sapi." );
+}
+
+ini_set('display_errors', 1);
+error_reporting(E_ALL);
+
+if ( isset( $_SERVER["SCRIPT_FILENAME"] ) ) {
+ # Known resource, sometimes a script sometimes a file
+ $file = $_SERVER["SCRIPT_FILENAME"];
+} elseif ( isset( $_SERVER["SCRIPT_NAME"] ) ) {
+ # Usually unknown, document root relative rather than absolute
+ # Happens with some cases like /wiki/File:Image.png
+ if ( is_readable( $_SERVER['DOCUMENT_ROOT'] . $_SERVER["SCRIPT_NAME"] ) ) {
+ # Just in case this actually IS a file, set it here
+ $file = $_SERVER['DOCUMENT_ROOT'] . $_SERVER["SCRIPT_NAME"];
+ } else {
+ # Otherwise let's pretend that this is supposed to go to index.php
+ $file = $_SERVER['DOCUMENT_ROOT'] . '/index.php';
+ }
+} else {
+ # Meh, we'll just give up
+ return false;
+}
+
+# And now do handling for that $file
+
+if ( !is_readable( $file ) ) {
+ # Let the server throw the error if it doesn't exist
+ return false;
+}
+$ext = pathinfo( $file, PATHINFO_EXTENSION );
+if ( $ext == 'php' || $ext == 'php5' ) {
+ # Execute php files
+ # We use require and return true here because when you return false
+ # the php webserver will discard post data and things like login
+ # will not function in the dev environment.
+ require( $file );
+ return true;
+}
+$mime = false;
+$lines = explode( "\n", file_get_contents( "includes/mime.types" ) );
+foreach ( $lines as $line ) {
+ $exts = explode( " ", $line );
+ $mime = array_shift( $exts );
+ if ( in_array( $ext, $exts ) ) {
+ break; # this is the right value for $mime
+ }
+ $mime = false;
+}
+if ( !$mime ) {
+ $basename = basename( $file );
+ if ( $basename == strtoupper( $basename ) ) {
+ # IF it's something like README serve it as text
+ $mime = "text/plain";
+ }
+}
+if ( $mime ) {
+ # Use custom handling to serve files with a known mime type
+ # This way we can serve things like .svg files that the built-in
+ # PHP webserver doesn't understand.
+ # ;) Nicely enough we just happen to bundle a mime.types file
+ $f = fopen($file, 'rb');
+ if ( preg_match( '^text/', $mime ) ) {
+ # Text should have a charset=UTF-8 (php's webserver does this too)
+ header("Content-Type: $mime; charset=UTF-8");
+ } else {
+ header("Content-Type: $mime");
+ }
+ header("Content-Length: " . filesize($file));
+ // Stream that out to the browser
+ fpassthru($f);
+ return true;
+}
+
+# Let the php server handle things on it's own otherwise
+return false;
diff --git a/maintenance/dev/install.sh b/maintenance/dev/install.sh
new file mode 100644
index 00000000..2219894d
--- /dev/null
+++ b/maintenance/dev/install.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+if [ "x$BASH_SOURCE" == "x" ]; then echo '$BASH_SOURCE not set'; exit 1; fi
+DEV=$(cd -P "$(dirname "${BASH_SOURCE[0]}" )" && pwd)
+
+"$DEV/installphp.sh"
+"$DEV/installmw.sh"
+"$DEV/start.sh"
diff --git a/maintenance/dev/installmw.sh b/maintenance/dev/installmw.sh
new file mode 100644
index 00000000..9ae3c593
--- /dev/null
+++ b/maintenance/dev/installmw.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+if [ "x$BASH_SOURCE" == "x" ]; then echo '$BASH_SOURCE not set'; exit 1; fi
+DEV=$(cd -P "$(dirname "${BASH_SOURCE[0]}" )" && pwd)
+
+. "$DEV/includes/require-php.sh"
+
+set -e
+
+PORT=4881
+
+cd "$DEV/../../"; # $IP
+
+mkdir -p "$DEV/data"
+"$PHP" maintenance/install.php --server="http://localhost:$PORT" --scriptpath="" --dbtype=sqlite --dbpath="$DEV/data" --pass=admin "Trunk Test" "$USER"
+echo ""
+echo "Development wiki created with admin user $USER and password 'admin'."
+echo ""
diff --git a/maintenance/dev/installphp.sh b/maintenance/dev/installphp.sh
new file mode 100644
index 00000000..d26ffa67
--- /dev/null
+++ b/maintenance/dev/installphp.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+
+if [ "x$BASH_SOURCE" == "x" ]; then echo '$BASH_SOURCE not set'; exit 1; fi
+DEV=$(cd -P "$(dirname "${BASH_SOURCE[0]}" )" && pwd)
+
+set -e # DO NOT USE PIPES unless this is rewritten
+
+. "$DEV/includes/php.sh"
+
+if [ "x$PHP" != "x" -a -x "$PHP" ]; then
+ echo "PHP is already installed"
+ exit 0
+fi
+
+TAR=php5.4-latest.tar.gz
+PHPURL="http://snaps.php.net/$TAR"
+
+cd "$DEV"
+
+echo "Preparing to download and install a local copy of PHP 5.4, note that this can take some time to do."
+echo "If you wish to avoid re-doing this for uture dev installations of MediaWiki we suggest installing php in ~/.mediawiki/php"
+echo -n "Install PHP in ~/.mediawiki/php [y/N]: "
+read INSTALLINHOME
+
+case "$INSTALLINHOME" in
+ [Yy] | [Yy][Ee][Ss] )
+ PREFIX="$HOME/.mediawiki/php"
+ ;;
+ *)
+ PREFIX="$DEV/php/"
+ ;;
+esac
+
+# Some debain-like systems bundle wget but not curl, some other systems
+# like os x bundle curl but not wget... use whatever is available
+echo -n "Downloading PHP 5.4"
+if command -v wget &>/dev/null; then
+ echo "- using wget"
+ wget "$PHPURL"
+elif command -v curl &>/dev/null; then
+ echo "- using curl"
+ curl -O "$PHPURL"
+else
+ echo "- aborting"
+ echo "Could not find curl or wget." >&2;
+ exit 1;
+fi
+
+echo "Extracting php 5.4"
+tar -xzf "$TAR"
+
+cd php5.4-*/
+
+echo "Configuring and installing php 5.4 in $PREFIX"
+./configure --prefix="$PREFIX"
+make
+make install
diff --git a/maintenance/dev/start.sh b/maintenance/dev/start.sh
new file mode 100644
index 00000000..dd7363a8
--- /dev/null
+++ b/maintenance/dev/start.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+if [ "x$BASH_SOURCE" == "x" ]; then echo '$BASH_SOURCE not set'; exit 1; fi
+DEV=$(cd -P "$(dirname "${BASH_SOURCE[0]}" )" && pwd)
+
+. "$DEV/includes/require-php.sh"
+
+PORT=4881
+
+echo "Starting up MediaWiki at http://localhost:$PORT/"
+echo ""
+
+cd "$DEV/../../"; # $IP
+"$PHP" -S "localhost:$PORT" "$DEV/includes/router.php"
diff --git a/maintenance/doMaintenance.php b/maintenance/doMaintenance.php
index 44e00032..6b29c5fd 100644
--- a/maintenance/doMaintenance.php
+++ b/maintenance/doMaintenance.php
@@ -74,18 +74,18 @@ require_once( MWInit::compiledPath( 'includes/DefaultSettings.php' ) );
if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
# Use a callback function to configure MediaWiki
MWFunction::call( MW_CONFIG_CALLBACK );
-} elseif ( file_exists( "$IP/../wmf-config/wikimedia-mode" ) ) {
- // Load settings, using wikimedia-mode if needed
- // @todo FIXME: Replace this hack with general farm-friendly code
- # @todo FIXME: Wikimedia-specific stuff needs to go away to an ext
- # Maybe a hook?
- global $cluster;
- $cluster = 'pmtpa';
- require( MWInit::interpretedPath( '../wmf-config/wgConf.php' ) );
- $maintenance->loadWikimediaSettings();
- require( MWInit::interpretedPath( '../wmf-config/CommonSettings.php' ) );
} else {
- require_once( $maintenance->loadSettings() );
+ if ( file_exists( "$IP/../wmf-config/wikimedia-mode" ) ) {
+ // Load settings, using wikimedia-mode if needed
+ // @todo FIXME: Replace this hack with general farm-friendly code
+ # @todo FIXME: Wikimedia-specific stuff needs to go away to an ext
+ # Maybe a hook?
+ global $cluster;
+ $cluster = 'pmtpa';
+ require( MWInit::interpretedPath( '../wmf-config/wgConf.php' ) );
+ }
+ // Require the configuration (probably LocalSettings.php)
+ require( $maintenance->loadSettings() );
}
if ( $maintenance->getDbType() === Maintenance::DB_ADMIN &&
diff --git a/maintenance/dtrace/counts.d b/maintenance/dtrace/counts.d
deleted file mode 100644
index bedb4547..00000000
--- a/maintenance/dtrace/counts.d
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * This software is in the public domain.
- *
- * $Id$
- */
-
-#pragma D option quiet
-
-self int tottime;
-BEGIN {
- tottime = timestamp;
-}
-
-php$target:::function-entry
- @counts[copyinstr(arg0)] = count();
-}
-
-END {
- printf("Total time: %dus\n", (timestamp - tottime) / 1000);
- printf("# calls by function:\n");
- printa("%-40s %@d\n", @counts);
-}
-
diff --git a/maintenance/dtrace/tree.d b/maintenance/dtrace/tree.d
deleted file mode 100644
index a799cb12..00000000
--- a/maintenance/dtrace/tree.d
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This software is in the public domain.
- *
- * $Id$
- */
-
-#pragma D option quiet
-
-self int indent;
-self int times[int];
-
-php$target:::function-entry
-{
- @counts[copyinstr(arg0)] = count();
- printf("%*s", self->indent, "");
- printf("-> %s\n", copyinstr(arg0));
- self->times[self->indent] = timestamp;
- self->indent += 2;
-}
-
-php$target:::function-return
-{
- self->indent -= 2;
- printf("%*s", self->indent, "");
- printf("<- %s %dus\n", copyinstr(arg0), (timestamp - self->times[self->indent]) / 1000);
-}
diff --git a/maintenance/dumpBackup.php b/maintenance/dumpBackup.php
index 15189261..c49a2963 100644
--- a/maintenance/dumpBackup.php
+++ b/maintenance/dumpBackup.php
@@ -119,7 +119,7 @@ Options:
Fancy stuff: (Works? Add examples please.)
--plugin=<class>[:<file>] Load a dump plugin class
--output=<type>:<file> Begin a filtered output stream;
- <type>s: file, gzip, bzip2, 7zip
+ <type>s: file, gzip, bzip2, 7zip
--filter=<type>[:<options>] Add a filter on an output branch
ENDS
diff --git a/maintenance/dumpHTML.php b/maintenance/dumpHTML.php
deleted file mode 100644
index bd94958e..00000000
--- a/maintenance/dumpHTML.php
+++ /dev/null
@@ -1,7 +0,0 @@
-dumpHTML has moved to the DumpHTML extension.
-
-WebDAV/SVN:
-http://svn.wikimedia.org/svnroot/mediawiki/trunk/extensions/DumpHTML/
-
-Web:
-http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/DumpHTML/
diff --git a/maintenance/dumpInterwiki.php b/maintenance/dumpInterwiki.php
deleted file mode 100644
index 217afd88..00000000
--- a/maintenance/dumpInterwiki.php
+++ /dev/null
@@ -1,251 +0,0 @@
-<?php
-/**
- * Build constant slightly compact database of interwiki prefixes
- * Wikimedia specific!
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @todo document
- * @ingroup Maintenance
- * @ingroup Wikimedia
- */
-
-require_once( dirname( __FILE__ ) . '/Site.php' );
-
-require_once( dirname( __FILE__ ) . '/Maintenance.php' );
-
-class DumpInterwiki extends Maintenance {
-
- public function __construct() {
- parent::__construct();
- $this->mDescription = "Build constant slightly compact database of interwiki prefixes.";
- $this->addOption( 'langlist', 'File with one language code per line', false, true );
- $this->addOption( 'dblist', 'File with one db per line', false, true );
- $this->addOption( 'specialdbs', "File with one 'special' db per line", false, true );
- $this->addOption( 'o', 'Cdb output file', false, true );
- $this->addOption( 'protocolrelative', 'Output wikimedia interwiki urls as protocol relative', false, false );
- }
-
- function execute() {
- # List of language prefixes likely to be found in multi-language sites
- $this->langlist = array_map( "trim", file( $this->getOption( 'langlist', "/home/wikipedia/common/langlist" ) ) );
-
- # List of all database names
- $this->dblist = array_map( "trim", file( $this->getOption( 'dblist', "/home/wikipedia/common/all.dblist" ) ) );
-
- # Special-case databases
- $this->specials = array_flip( array_map( "trim", file( $this->getOption( 'specialdbs', "/home/wikipedia/common/special.dblist" ) ) ) );
-
- if ( $this->hasOption( 'o' ) ) {
- $this->dbFile = CdbWriter::open( $this->getOption( 'o' ) ) ;
- } else {
- $this->dbFile = false;
- }
-
- if ( $this->hasOption( 'protocolrelative' ) ) {
- $this->urlprotocol = '';
- } else {
- $this->urlprotocol = 'http:';
- }
-
- $this->getRebuildInterwikiDump();
- }
-
- function getRebuildInterwikiDump() {
- global $wgContLang;
-
- # Multi-language sites
- # db suffix => db suffix, iw prefix, hostname
- $sites = array(
- 'wiki' => new Site( 'wiki', 'w', 'wikipedia.org' ),
- 'wiktionary' => new Site( 'wiktionary', 'wikt', 'wiktionary.org' ),
- 'wikiquote' => new Site( 'wikiquote', 'q', 'wikiquote.org' ),
- 'wikibooks' => new Site( 'wikibooks', 'b', 'wikibooks.org' ),
- 'wikinews' => new Site( 'wikinews', 'n', 'wikinews.org' ),
- 'wikisource' => new Site( 'wikisource', 's', 'wikisource.org' ),
- 'wikimedia' => new Site( 'wikimedia', 'chapter', 'wikimedia.org' ),
- 'wikiversity' => new Site( 'wikiversity', 'v', 'wikiversity.org' ),
- );
-
- # Extra interwiki links that can't be in the intermap for some reason
- $extraLinks = array(
- array( 'm', $this->urlprotocol . '//meta.wikimedia.org/wiki/$1', 1 ),
- array( 'meta', $this->urlprotocol . '//meta.wikimedia.org/wiki/$1', 1 ),
- array( 'sep11', $this->urlprotocol . '//sep11.wikipedia.org/wiki/$1', 1 ),
- );
-
- # Language aliases, usually configured as redirects to the real wiki in apache
- # Interlanguage links are made directly to the real wiki
- # Something horrible happens if you forget to list an alias here, I can't
- # remember what
- $this->languageAliases = array(
- 'zh-cn' => 'zh',
- 'zh-tw' => 'zh',
- 'dk' => 'da',
- 'nb' => 'no',
- );
-
- # Special case prefix rewrites, for the benefit of Swedish which uses s:t
- # as an abbreviation for saint
- $this->prefixRewrites = array(
- 'svwiki' => array( 's' => 'src' ),
- );
-
- # Construct a list of reserved prefixes
- $reserved = array();
- foreach ( $this->langlist as $lang ) {
- $reserved[$lang] = 1;
- }
- foreach ( $this->languageAliases as $alias => $lang ) {
- $reserved[$alias] = 1;
- }
- foreach ( $sites as $site ) {
- $reserved[$site->lateral] = 1;
- }
-
- # Extract the intermap from meta
- $intermap = Http::get( 'http://meta.wikimedia.org/w/index.php?title=Interwiki_map&action=raw', 30 );
- $lines = array_map( 'trim', explode( "\n", trim( $intermap ) ) );
-
- if ( !$lines || count( $lines ) < 2 ) {
- $this->error( "m:Interwiki_map not found", true );
- }
-
- # Global iterwiki map
- foreach ( $lines as $line ) {
- if ( preg_match( '/^\|\s*(.*?)\s*\|\|\s*(.*?)\s*$/', $line, $matches ) ) {
- $prefix = $wgContLang->lc( $matches[1] );
- $prefix = str_replace( ' ', '_', $prefix );
-
- $url = $matches[2];
- if ( preg_match( '/(wikipedia|wiktionary|wikisource|wikiquote|wikibooks|wikimedia)\.org/', $url ) ) {
- if ( $this->hasOption( 'protocolrelative' ) ) {
- if ( substr( $url, 0, 5 ) == 'http:' ) {
- $url = substr( $url, 5 );
- } else if ( substr( $url, 0, 6 ) == 'https:' ) {
- $url = substr( $url, 6 );
- }
- }
- $local = 1;
- } else {
- $local = 0;
- }
-
- if ( empty( $reserved[$prefix] ) ) {
- $imap = array( "iw_prefix" => $prefix, "iw_url" => $url, "iw_local" => $local );
- $this->makeLink ( $imap, "__global" );
- }
- }
- }
-
- # Exclude Wikipedia for Wikipedia
- $this->makeLink ( array ( 'iw_prefix' => 'wikipedia', 'is_url' => null ), "_wiki" );
-
- # Multilanguage sites
- foreach ( $sites as $site ) {
- $this->makeLanguageLinks ( $site, "_" . $site->suffix );
- }
-
- foreach ( $this->dblist as $db ) {
- if ( isset( $this->specials[$db] ) ) {
- # Special wiki
- # Has interwiki links and interlanguage links to wikipedia
-
- $this->makeLink( array( 'iw_prefix' => $db, 'iw_url' => "wiki" ), "__sites" );
- # Links to multilanguage sites
- foreach ( $sites as $targetSite ) {
- $this->makeLink( array( 'iw_prefix' => $targetSite->lateral,
- 'iw_url' => $targetSite->getURL( 'en', $this->urlprotocol ),
- 'iw_local' => 1 ), $db );
- }
- } else {
- # Find out which site this DB belongs to
- $site = false;
- foreach ( $sites as $candidateSite ) {
- $suffix = $candidateSite->suffix;
- if ( preg_match( "/(.*)$suffix$/", $db, $matches ) ) {
- $site = $candidateSite;
- break;
- }
- }
- $this->makeLink( array( 'iw_prefix' => $db, 'iw_url' => $site->suffix ), "__sites" );
- if ( !$site ) {
- $this->error( "Invalid database $db\n" );
- continue;
- }
- $lang = $matches[1];
-
- # Lateral links
- foreach ( $sites as $targetSite ) {
- if ( $targetSite->suffix != $site->suffix ) {
- $this->makeLink( array( 'iw_prefix' => $targetSite->lateral,
- 'iw_url' => $targetSite->getURL( $lang, $this->urlprotocol ),
- 'iw_local' => 1 ), $db );
- }
- }
-
- if ( $site->suffix == "wiki" ) {
- $this->makeLink( array( 'iw_prefix' => 'w',
- 'iw_url' => $this->urlprotocol . "//en.wikipedia.org/wiki/$1",
- 'iw_local' => 1 ), $db );
- }
-
- }
- }
- foreach ( $extraLinks as $link ) {
- $this->makeLink( $link, "__global" );
- }
- }
-
- # ------------------------------------------------------------------------------------------
-
- # Executes part of an INSERT statement, corresponding to all interlanguage links to a particular site
- function makeLanguageLinks( &$site, $source ) {
- # Actual languages with their own databases
- foreach ( $this->langlist as $targetLang ) {
- $this->makeLink( array( $targetLang, $site->getURL( $targetLang, $this->urlprotocol ), 1 ), $source );
- }
-
- # Language aliases
- foreach ( $this->languageAliases as $alias => $lang ) {
- $this->makeLink( array( $alias, $site->getURL( $lang, $this->urlprotocol ), 1 ), $source );
- }
- }
-
- function makeLink( $entry, $source ) {
- if ( isset( $this->prefixRewrites[$source] ) && isset( $this->prefixRewrites[$source][$entry[0]] ) )
- $entry[0] = $this->prefixRewrites[$source][$entry[0]];
-
- if ( !array_key_exists( "iw_prefix", $entry ) ) {
- $entry = array( "iw_prefix" => $entry[0], "iw_url" => $entry[1], "iw_local" => $entry[2] );
- }
- if ( array_key_exists( $source, $this->prefixRewrites ) &&
- array_key_exists( $entry['iw_prefix'], $this->prefixRewrites[$source] ) ) {
- $entry['iw_prefix'] = $this->prefixRewrites[$source][$entry['iw_prefix']];
- }
-
- if ( $this->dbFile ) {
- $this->dbFile->set( "{$source}:{$entry['iw_prefix']}", trim( "{$entry['iw_local']} {$entry['iw_url']}" ) );
- } else {
- $this->output( "{$source}:{$entry['iw_prefix']} {$entry['iw_url']} {$entry['iw_local']}\n" );
- }
- }
-}
-
-$maintClass = "DumpInterwiki";
-require_once( RUN_MAINTENANCE_IF_MAIN );
-
diff --git a/maintenance/dumpLinks.php b/maintenance/dumpLinks.php
index 39a9e955..0101dc8d 100644
--- a/maintenance/dumpLinks.php
+++ b/maintenance/dumpLinks.php
@@ -26,7 +26,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
- * @ingroup Mainatenance
+ * @ingroup Maintenance
*/
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
diff --git a/maintenance/dumpTextPass.php b/maintenance/dumpTextPass.php
index 4e85e64e..0fed29fc 100644
--- a/maintenance/dumpTextPass.php
+++ b/maintenance/dumpTextPass.php
@@ -2,7 +2,7 @@
/**
* Script that postprocesses XML dumps from dumpBackup.php to add page text
*
- * Copyright © 2005 Brion Vibber <brion@pobox.com>, 2010 Alexandre Emsenhuber
+ * Copyright (C) 2005 Brion Vibber <brion@pobox.com>
* http://www.mediawiki.org/
*
* This program is free software; you can redistribute it and/or modify
@@ -66,6 +66,11 @@ class TextPassDumper extends BackupDumper {
var $checkpointJustWritten = false;
var $checkpointFiles = array();
+ /**
+ * @var DatabaseBase
+ */
+ protected $db;
+
function initProgress( $history ) {
parent::initProgress();
$this->timeOfCheckpoint = $this->startTime;
@@ -169,7 +174,8 @@ class TextPassDumper extends BackupDumper {
*/
function showReport() {
if ( !$this->prefetch ) {
- return parent::showReport();
+ parent::showReport();
+ return;
}
if ( $this->reporting ) {
@@ -186,8 +192,7 @@ class TextPassDumper extends BackupDumper {
$etats = wfTimestamp( TS_DB, intval( $eta ) );
if ( $this->fetchCount ) {
$fetchRate = 100.0 * $this->prefetchCount / $this->fetchCount;
- }
- else {
+ } else {
$fetchRate = '-';
}
$pageRate = $this->pageCount / $deltaAll;
@@ -201,8 +206,7 @@ class TextPassDumper extends BackupDumper {
if ( $deltaPart ) {
if ( $this->fetchCountLast ) {
$fetchRatePart = 100.0 * $this->prefetchCountLast / $this->fetchCountLast;
- }
- else {
+ } else {
$fetchRatePart = '-';
}
$pageRatePart = $this->pageCountPart / $deltaPart;
@@ -228,9 +232,9 @@ class TextPassDumper extends BackupDumper {
function checkIfTimeExceeded() {
if ( $this->maxTimeAllowed && ( $this->lastTime - $this->timeOfCheckpoint > $this->maxTimeAllowed ) ) {
- return True;
+ return true;
}
- return False;
+ return false;
}
function finalOptionCheck() {
@@ -286,7 +290,7 @@ class TextPassDumper extends BackupDumper {
// we wrote some stuff after last checkpoint that needs renamed
if (file_exists($filenameList[0])) {
$newFilenames = array();
- # we might have just written the header and footer and had no
+ # we might have just written the header and footer and had no
# pages or revisions written... perhaps they were all deleted
# there's no pageID 0 so we use that. the caller is responsible
# for deciding what to do with a file containing only the
@@ -332,7 +336,6 @@ class TextPassDumper extends BackupDumper {
}
private function doGetText( $id ) {
-
$id = intval( $id );
$this->failures = 0;
$ex = new MWException( "Graceful storage failure" );
@@ -345,9 +348,9 @@ class TextPassDumper extends BackupDumper {
$this->closeSpawn();
$this->openSpawn();
}
- $text = $this->getTextSpawned( $id );
+ $text = $this->getTextSpawned( $id );
} else {
- $text = $this->getTextDbSafe( $id );
+ $text = $this->getTextDbSafe( $id );
}
if ( $text === false ) {
$this->failures++;
@@ -359,11 +362,10 @@ class TextPassDumper extends BackupDumper {
$this->failedTextRetrievals++;
if ($this->failedTextRetrievals > $this->maxConsecutiveFailedTextRetrievals) {
throw $ex;
- }
- else {
+ } else {
// would be nice to return something better to the caller someday,
// log what we know about the failure and about the revision
- return("");
+ return "";
}
} else {
$this->progress( "Error $this->failures " .
@@ -373,16 +375,18 @@ class TextPassDumper extends BackupDumper {
}
} else {
$this->failedTextRetrievals= 0;
- return( $text );
+ return $text;
}
}
-
+ return '';
}
/**
* Fetch a text revision from the database, retrying in case of failure.
* This may survive some transitory errors by reconnecting, but
* may not survive a long-term server outage.
+ *
+ * FIXME: WTF? Why is it using a loop and then returning unconditionally?
*/
private function getTextDbSafe( $id ) {
while ( true ) {
@@ -397,6 +401,8 @@ class TextPassDumper extends BackupDumper {
/**
* May throw a database error if, say, the server dies during query.
+ * @param $id
+ * @return bool|string
*/
private function getTextDb( $id ) {
global $wgContLang;
@@ -584,15 +590,15 @@ class TextPassDumper extends BackupDumper {
$this->egress->writeClosePage( $this->buffer );
// nasty hack, we can't just write the chardata after the
// page tag, it will include leading blanks from the next line
- $this->egress->sink->write("\n");
-
+ $this->egress->sink->write("\n");
+
$this->buffer = $this->xmlwriterobj->closeStream();
$this->egress->writeCloseStream( $this->buffer );
$this->buffer = "";
$this->thisPage = "";
// this could be more than one file if we had more than one output arg
- $checkpointFilenames = array();
+
$filenameList = (array)$this->egress->getFilenames();
$newFilenames = array();
$firstPageID = str_pad($this->firstPageWritten,9,"0",STR_PAD_LEFT);
@@ -669,10 +675,10 @@ Options:
pressure on the database.
(Requires the XMLReader extension)
--maxtime=<minutes> Write out checkpoint file after this many minutes (writing
- out complete page, closing xml file properly, and opening new one
+ out complete page, closing xml file properly, and opening new one
with header). This option requires the checkpointfile option.
--checkpointfile=<filenamepattern> Use this string for checkpoint filenames,
- substituting first pageid written for the first %s (required) and the
+ substituting first pageid written for the first %s (required) and the
last pageid written for the second %s if it exists.
--quiet Don't dump status reports to stderr.
--report=n Report position and speed after every n pages processed.
@@ -684,3 +690,5 @@ Options:
ENDS
);
}
+
+
diff --git a/maintenance/edit.php b/maintenance/edit.php
index fb462a40..88573714 100644
--- a/maintenance/edit.php
+++ b/maintenance/edit.php
@@ -58,14 +58,14 @@ class EditCLI extends Maintenance {
$this->error( "Invalid title", true );
}
- $article = new Article( $wgTitle );
+ $page = WikiPage::factory( $wgTitle );
# Read the text
$text = $this->getStdin( Maintenance::STDIN_ALL );
# Do the edit
$this->output( "Saving... " );
- $status = $article->doEdit( $text, $summary,
+ $status = $page->doEdit( $text, $summary,
( $minor ? EDIT_MINOR : 0 ) |
( $bot ? EDIT_FORCE_BOT : 0 ) |
( $autoSummary ? EDIT_AUTOSUMMARY : 0 ) |
diff --git a/maintenance/eval.php b/maintenance/eval.php
index 1502ad3e..3bd164fd 100644
--- a/maintenance/eval.php
+++ b/maintenance/eval.php
@@ -31,12 +31,10 @@
* @ingroup Maintenance
*/
-$wgUseNormalUser = (bool)getenv( 'MW_WIKIUSER' );
-
$optionsWithArgs = array( 'd' );
/** */
-require_once( "commandLine.inc" );
+require_once( dirname( __FILE__ ) . "/commandLine.inc" );
if ( isset( $options['d'] ) ) {
$d = $options['d'];
@@ -57,13 +55,8 @@ if ( isset( $options['d'] ) ) {
}
}
-if ( function_exists( 'readline_add_history' )
- && Maintenance::posix_isatty( 0 /*STDIN*/ ) )
-{
- $useReadline = true;
-} else {
- $useReadline = false;
-}
+$useReadline = function_exists( 'readline_add_history' )
+ && Maintenance::posix_isatty( 0 /*STDIN*/ );
if ( $useReadline ) {
$historyFile = isset( $_ENV['HOME'] ) ?
diff --git a/maintenance/fetchText.php b/maintenance/fetchText.php
index 067ffe45..3b43bcd5 100644
--- a/maintenance/fetchText.php
+++ b/maintenance/fetchText.php
@@ -29,7 +29,7 @@ class FetchText extends Maintenance {
$this->mDescription = "Fetch the revision text from an old_id";
}
- /*
+ /**
* returns a string containing the following in order:
* textid
* \n
diff --git a/maintenance/findHooks.php b/maintenance/findHooks.php
index 5996fd3a..cb582857 100644
--- a/maintenance/findHooks.php
+++ b/maintenance/findHooks.php
@@ -12,7 +12,7 @@
*
* Any instance of wfRunHooks that doesn't meet these parameters will be noted.
*
- * Copyright © Ashar Voultoiz
+ * Copyright © Antoine Musso
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@
*
* @file
* @ingroup Maintenance
- * @author Ashar Voultoiz <hashar at free dot fr>
+ * @author Antoine Musso <hashar at free dot fr>
*/
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
@@ -59,6 +59,7 @@ class FindHooks extends Maintenance {
$IP . '/includes/actions/',
$IP . '/includes/api/',
$IP . '/includes/cache/',
+ $IP . '/includes/context/',
$IP . '/includes/db/',
$IP . '/includes/diff/',
$IP . '/includes/filerepo/',
@@ -106,6 +107,29 @@ class FindHooks extends Maintenance {
*/
private function getHooksFromDoc( $doc ) {
if ( $this->hasOption( 'online' ) ) {
+ return $this->getHooksFromOnlineDoc( );
+ } else {
+ return $this->getHooksFromLocalDoc( $doc );
+ }
+ }
+
+ /**
+ * Get hooks from a local file (for example docs/hooks.txt)
+ * @param $doc string: filename to look in
+ * @return array of documented hooks
+ */
+ private function getHooksFromLocalDoc( $doc ) {
+ $m = array();
+ $content = file_get_contents( $doc );
+ preg_match_all( "/\n'(.*?)'/", $content, $m );
+ return array_unique( $m[1] );
+ }
+
+ /**
+ * Get hooks from www.mediawiki.org using the API
+ * @return array of documented hooks
+ */
+ private function getHooksFromOnlineDoc( ) {
// All hooks
$allhookdata = Http::get( 'http://www.mediawiki.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:MediaWiki_hooks&cmlimit=500&format=php' );
$allhookdata = unserialize( $allhookdata );
@@ -129,12 +153,6 @@ class FindHooks extends Maintenance {
}
}
return array_diff( $allhooks, $removed );
- } else {
- $m = array();
- $content = file_get_contents( $doc );
- preg_match_all( "/\n'(.*?)'/", $content, $m );
- return array_unique( $m[1] );
- }
}
/**
diff --git a/maintenance/fixExtLinksProtocolRelative.php b/maintenance/fixExtLinksProtocolRelative.php
index 1a7025ad..0cabe816 100644
--- a/maintenance/fixExtLinksProtocolRelative.php
+++ b/maintenance/fixExtLinksProtocolRelative.php
@@ -37,7 +37,7 @@ class FixExtLinksProtocolRelative extends LoggedUpdateMaintenance {
protected function updateSkippedMessage() {
return 'protocol-relative URLs in externallinks table already fixed.';
}
-
+
protected function doDBUpdates() {
$db = wfGetDB( DB_MASTER );
if ( !$db->tableExists( 'externallinks' ) ) {
@@ -53,7 +53,7 @@ class FixExtLinksProtocolRelative extends LoggedUpdateMaintenance {
foreach ( $res as $row ) {
$count++;
if ( $count % 100 == 0 ) {
- $this->output( $count );
+ $this->output( $count . "\n" );
wfWaitForSlaves();
}
$db->insert( 'externallinks',
diff --git a/maintenance/formatInstallDoc.php b/maintenance/formatInstallDoc.php
index 9acc16a7..b3bb50ca 100644
--- a/maintenance/formatInstallDoc.php
+++ b/maintenance/formatInstallDoc.php
@@ -1,4 +1,7 @@
<?php
+/**
+ * @ingroup Maintenance
+ */
require_once( dirname( __FILE__ ) .'/Maintenance.php' );
diff --git a/maintenance/fuzz-tester.php b/maintenance/fuzz-tester.php
index 18af4de4..d87d6281 100644
--- a/maintenance/fuzz-tester.php
+++ b/maintenance/fuzz-tester.php
@@ -108,7 +108,6 @@ Wiki configuration for testing:
$wgGroupPermissions['*']['reupload-shared'] = true;
$wgGroupPermissions['*']['rollback'] = true;
$wgGroupPermissions['*']['siteadmin'] = true;
- $wgGroupPermissions['*']['trackback'] = true;
$wgGroupPermissions['*']['unwatchedpages'] = true;
$wgGroupPermissions['*']['upload'] = true;
$wgGroupPermissions['*']['userrights'] = true;
@@ -121,7 +120,6 @@ Wiki configuration for testing:
error_reporting (E_ALL); // At a later date could be increased to E_ALL | E_STRICT
$wgBlockOpenProxies = true; // Some block pages require this to be true in order to test.
$wgEnableUploads = true; // enable uploads.
- //$wgUseTrackbacks = true; // enable trackbacks; However this breaks the viewPageTest, so currently disabled.
$wgDBerrorLog = "/root/mediawiki-db-error-log.txt"; // log DB errors, replace with suitable path.
$wgShowSQLErrors = true; // Show SQL errors (instead of saying the query was hidden).
$wgShowExceptionDetails = true; // want backtraces.
@@ -139,11 +137,7 @@ Wiki configuration for testing:
// Install & enable Special Page extensions to increase code coverage. E.g.:
require_once("extensions/Cite/SpecialCite.php");
- require_once("extensions/Filepath/SpecialFilepath.php");
- require_once("extensions/Makebot/Makebot.php");
- require_once("extensions/Makesysop/SpecialMakesysop.php");
require_once("extensions/Renameuser/SpecialRenameuser.php");
- require_once("extensions/LinkSearch/LinkSearch.php");
// --------- End ---------
If you want to try E_STRICT error logging, add this to the above:
@@ -763,14 +757,18 @@ class wikiFuzz {
static private $maxparams = 10;
/**
- ** Returns random number between finish and start.
+ * Returns random number between finish and start.
+ * @param $finish
+ * @param $start int
+ * @return int
*/
static public function randnum( $finish, $start = 0 ) {
return mt_rand( $start, $finish );
}
/**
- ** Returns a mix of random text and random wiki syntax.
+ * Returns a mix of random text and random wiki syntax.
+ * @return string
*/
static private function randstring() {
$thestring = "";
@@ -800,18 +798,17 @@ class wikiFuzz {
}
/**
- ** Returns either random text, or random wiki syntax, or random data from "ints",
- ** or random data from "other".
+ * Returns either random text, or random wiki syntax, or random data from "ints",
+ * or random data from "other".
+ * @return string
*/
static private function makestring() {
$what = wikiFuzz::randnum( 2 );
if ( $what == 0 ) {
return wikiFuzz::randstring();
- }
- elseif ( $what == 1 ) {
+ } elseif ( $what == 1 ) {
return wikiFuzz::$ints[wikiFuzz::randnum( count( wikiFuzz::$ints ) - 1 )];
- }
- else {
+ } else {
return wikiFuzz::$other[wikiFuzz::randnum( count( wikiFuzz::$other ) - 1 )];
}
}
@@ -819,6 +816,8 @@ class wikiFuzz {
/**
* Returns the matched character slash-escaped as in a C string
* Helper for makeTitleSafe callback
+ * @param $matches
+ * @return atring
*/
static private function stringEscape( $matches ) {
return sprintf( "\\x%02x", ord( $matches[1] ) );
@@ -827,6 +826,8 @@ class wikiFuzz {
/**
** Strips out the stuff that Mediawiki balks at in a page's title.
** Implementation copied/pasted from cleanupTable.inc & cleanupImages.php
+ * @param $str string
+ * @return string
*/
static public function makeTitleSafe( $str ) {
$legalTitleChars = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF";
@@ -837,6 +838,7 @@ class wikiFuzz {
/**
** Returns a string of fuzz text.
+ * @return string
*/
static private function loop() {
switch ( wikiFuzz::randnum( 3 ) ) {
@@ -864,7 +866,8 @@ class wikiFuzz {
}
/**
- ** Returns one of the three styles of random quote: ', ", and nothing.
+ * Returns one of the three styles of random quote: ', ", and nothing.
+ * @return string
*/
static private function getRandQuote() {
switch ( wikiFuzz::randnum( 3 ) ) {
@@ -876,6 +879,8 @@ class wikiFuzz {
/**
** Returns fuzz text, with the parameter indicating approximately how many lines of text you want.
+ * @param $maxtypes int
+ * @return string
*/
static public function makeFuzz( $maxtypes = 2 ) {
$page = "";
@@ -1812,32 +1817,6 @@ class thumbTest extends pageTest {
}
}
-
-/**
- ** a test for trackback.php
- */
-class trackbackTest extends pageTest {
- function __construct() {
- $this->pagePath = "trackback.php";
-
- $this->params = array (
- "url" => wikiFuzz::makeFuzz( 2 ),
- "blog_name" => wikiFuzz::chooseInput( array( "80", wikiFuzz::randnum( 6000, -200 ), wikiFuzz::makeFuzz( 2 ) ) ),
- "article" => wikiFuzz::chooseInput( array( "Main Page", wikiFuzz::makeFuzz( 2 ) ) ),
- "title" => wikiFuzz::chooseInput( array( "Main Page", wikiFuzz::makeFuzz( 2 ) ) ),
- "excerpt" => wikiFuzz::makeFuzz( 2 ),
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["title"] );
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["excerpt"] );
-
- // page does not produce HTML.
- $this->tidyValidate = false;
- }
-}
-
-
/**
** a test for profileinfo.php
*/
@@ -1892,52 +1871,6 @@ class specialFilepathPageTest extends pageTest {
/**
- ** a test for Special:Makebot (extension Special page).
- */
-class specialMakebot extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Makebot";
-
- $this->params = array (
- "username" => wikiFuzz::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz::makeFuzz( 1 ) ) ),
- "dosearch" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "grant" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "comment" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- "token" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["dosearch"] );
- if ( wikiFuzz::randnum( 2 ) == 0 ) unset( $this->params["grant"] );
- if ( wikiFuzz::randnum( 5 ) == 0 ) unset( $this->params["token"] );
- }
-}
-
-
-/**
- ** a test for Special:Makesysop (extension Special page).
- */
-class specialMakesysop extends pageTest {
- function __construct() {
- $this->pagePath = "index.php?title=Special:Makesysop";
-
- $this->params = array (
- "wpMakesysopUser" => wikiFuzz::chooseInput( array( "Nickj2", "192.168.0.2", wikiFuzz::makeFuzz( 1 ) ) ),
- "action" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpMakesysopSubmit" => wikiFuzz::chooseInput( array( "0", "1", "++--34234", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpEditToken" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- "wpSetBureaucrat" => wikiFuzz::chooseInput( array( "20398702394", "", wikiFuzz::makeFuzz( 2 ) ) ),
- );
-
- // sometimes we don't want to specify certain parameters.
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["wpMakesysopSubmit"] );
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["wpEditToken"] );
- if ( wikiFuzz::randnum( 3 ) == 0 ) unset( $this->params["wpSetBureaucrat"] );
- }
-}
-
-
-/**
** a test for Special:Renameuser (extension Special page).
*/
class specialRenameuserPageTest extends pageTest {
@@ -2224,9 +2157,10 @@ class GeSHi_Test extends pageTest {
}
}
-
/**
** selects a page test to run.
+ * @param $count
+ * @return \api|\confirmEmail|\contributionsTest|\editPageTest|\imagelistTest|\imagepageTest|\ipblocklistTest|\listusersTest|\mimeSearchTest|\newImagesTest|\pageDeletion|\pageHistoryTest|\pageProtectionForm|\prefixindexTest|\profileInfo|\recentchangesTest|\redirectTest|\searchTest|\specialAllmessagesTest|\specialAllpagesTest|\specialBlockip|\specialBlockmeTest|\specialBooksourcesTest|\specialCategoryTree|\specialChemicalsourcesTest|\specialCitePageTest|\specialExportTest|\specialFilepathPageTest|\specialImportPageTest|\specialLinksearch|\specialLockdbPageTest|\specialLogTest|\specialMovePage|\specialNewpagesPageTest|\specialRenameuserPageTest|\specialRevisionDeletePageTest|\specialUndeletePageTest|\specialUnlockdbPageTest|\specialUserrights|\successfulUserLoginTest|\thumbTest|\userLoginTest|\viewPageTest|\watchlistTest
*/
function selectPageTest( $count ) {
@@ -2275,17 +2209,14 @@ function selectPageTest( $count ) {
case 33: return new specialRevisionDeletePageTest();
case 34: return new specialImportPageTest();
case 35: return new thumbTest();
- case 36: return new trackbackTest();
case 37: return new profileInfo();
case 38: return new specialCitePageTest();
case 39: return new specialFilepathPageTest();
- case 40: return new specialMakebot();
- case 41: return new specialMakesysop();
- case 42: return new specialRenameuserPageTest();
- case 43: return new specialLinksearch();
- case 44: return new specialCategoryTree();
- case 45: return new api();
- case 45: return new specialChemicalsourcesTest();
+ case 40: return new specialRenameuserPageTest();
+ case 41: return new specialLinksearch();
+ case 42: return new specialCategoryTree();
+ case 43: return new api();
+ case 44: return new specialChemicalsourcesTest();
default: return new editPageTest();
}
}
@@ -2300,11 +2231,12 @@ function saveFile( $data, $name ) {
file_put_contents( $name, $data );
}
-
/**
** Returns a test as an experimental GET-to-POST URL.
** This doesn't seem to always work though, and sometimes the output is too long
** to be a valid GET URL, so we also save in other formats.
+ * @param $test pageTest
+ * @return string
*/
function getAsURL( pageTest $test ) {
$used_question_mark = ( strpos( $test->getPagePath(), "?" ) !== false );
@@ -2356,11 +2288,12 @@ function saveTestAsPHP( pageTest $test, $filename ) {
saveFile( $str, $filename );
}
-
/**
- ** Escapes a value so that it can be used on the command line by Curl.
- ** Specifically, "<" and "@" need to be escaped if they are the first character,
- ** otherwise curl interprets these as meaning that we want to insert a file.
+ * Escapes a value so that it can be used on the command line by Curl.
+ * Specifically, "<" and "@" need to be escaped if they are the first character,
+ * otherwise curl interprets these as meaning that we want to insert a file.
+ * @param $input_params array
+ * @return array
*/
function escapeForCurl( array $input_params ) {
$output_params = array();
@@ -2411,18 +2344,21 @@ function saveTest( pageTest $test, $testname ) {
saveTestData ( $test, $base_name . DATA_FILE );
}
-
// ////////////////// MEDIAWIKI OUTPUT /////////////////////////
/**
- ** Asks MediaWiki for the HTML output of a test.
+ * Asks MediaWiki for the HTML output of a test.
+ * @param $test pageTest
+ * @return string
*/
function wikiTestOutput( pageTest $test ) {
$ch = curl_init();
// specify the cookie, if required.
- if ( $test->getCookie() ) curl_setopt( $ch, CURLOPT_COOKIE, $test->getCookie() );
+ if ( $test->getCookie() ) {
+ curl_setopt( $ch, CURLOPT_COOKIE, $test->getCookie() );
+ }
curl_setopt( $ch, CURLOPT_POST, 1 ); // save form using a POST
$params = escapeForCurl( $test->getParams() );
@@ -2447,8 +2383,10 @@ function wikiTestOutput( pageTest $test ) {
// ////////////////// HTML VALIDATION /////////////////////////
-/*
- ** Asks the validator whether this is valid HTML, or not.
+/**
+ * Asks the validator whether this is valid HTML, or not.
+ * @param $text string
+ * @return array
*/
function validateHTML( $text ) {
@@ -2477,9 +2415,10 @@ function validateHTML( $text ) {
return array( $valid, $result );
}
-
/**
- ** 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).
+ * @param $name
+ * @return bool
*/
function tidyCheckFile( $name ) {
$file = DIRECTORY . "/" . $name;
@@ -2498,10 +2437,10 @@ function tidyCheckFile( $name ) {
}
}
-
/**
** Returns whether or not an database error log file has changed in size since
** the last time this was run. This is used to tell if a test caused a DB error.
+ * @return bool
*/
function dbErrorLogged() {
static $filesize;
@@ -2529,8 +2468,12 @@ function dbErrorLogged() {
// //////////////// TOP-LEVEL PROBLEM-FINDING FUNCTION ////////////////////////
/**
- ** takes a page test, and runs it and tests it for problems in the output.
- ** Returns: False on finding a problem, or True on no problems being found.
+ * takes a page test, and runs it and tests it for problems in the output.
+ * Returns: False on finding a problem, or True on no problems being found.
+ * @param $test pageTest
+ * @param $testname
+ * @param $can_overwrite bool
+ * @return bool
*/
function runWikiTest( pageTest $test, &$testname, $can_overwrite = false ) {
diff --git a/maintenance/gearman/gearman.inc b/maintenance/gearman/gearman.inc
deleted file mode 100644
index 15f80e62..00000000
--- a/maintenance/gearman/gearman.inc
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-
-require( 'Net/Gearman/Client.php' );
-require( 'Net/Gearman/Worker.php' );
-
-class MWGearmanJob extends Net_Gearman_Job_Common {
- function switchWiki( $wiki, $params ) {
- echo "Switching to $wiki\n";
-
- # Pretend that we have completed it right now, because the new process won't do it
- $this->complete( array( 'result' => true ) );
- socket_close( $this->conn );
-
- # Close some more sockets
- LBFactory::destroyInstance();
- global $wgMemc;
- $wgMemc->disconnect_all();
-
- # Find PHP
- $php = readlink( '/proc/' . posix_getpid() . '/exe' );
-
- # Run the worker script
- $args = array( $_SERVER['PHP_SELF'],
- '--wiki', $wiki,
- '--fake-job', serialize( $params ) );
- $args = array_merge( $args, $GLOBALS['args'] );
- pcntl_exec( $php, $args, $_ENV );
- echo "Error running exec\n";
- }
-
- function run( $params ) {
- if ( wfWikiID() !== $params['wiki'] ) {
- $this->switchWiki( $params['wiki'], $params );
- }
- return self::runNoSwitch( $params );
- }
-
- static function runNoSwitch( $params ) {
- echo implode( ' ', $params ) . "\n";
- $title = Title::newFromText( $params['title'] );
- $mwJob = Job::factory( $params['command'], $title, $params['params'] );
- return $mwJob->run();
- }
-}
-
-class NonScaryGearmanWorker extends Net_Gearman_Worker {
-
- /**
- * Copied from Net_Gearman_Worker but with the scary "run any PHP file in
- * the filesystem" feature removed.
- */
- protected function doWork($socket) {
- Net_Gearman_Connection::send($socket, 'grab_job');
-
- $resp = array('function' => 'noop');
- while (count($resp) && $resp['function'] == 'noop') {
- $resp = Net_Gearman_Connection::blockingRead($socket);
- }
-
- if (in_array($resp['function'], array('noop', 'no_job'))) {
- return false;
- }
-
- if ($resp['function'] != 'job_assign') {
- throw new Net_Gearman_Exception('Holy Cow! What are you doing?!');
- }
-
- $name = $resp['data']['func'];
- $handle = $resp['data']['handle'];
- $arg = array();
-
- if (isset($resp['data']['arg']) &&
- Net_Gearman_Connection::stringLength($resp['data']['arg'])) {
- $arg = json_decode($resp['data']['arg'], true);
- }
-
- ### START MW DIFFERENT BIT
- if ( $name != 'mw_job' ) {
- throw new Net_Gearman_Job_Exception('Invalid function');
- }
- $job = new MWGearmanJob($socket, $handle);
- ### END MW DIFFERENT BIT
-
- try {
- $this->start($handle, $name, $arg);
- $res = $job->run($arg);
- if (!is_array($res)) {
- $res = array('result' => $res);
- }
-
- $job->complete($res);
- $this->complete($handle, $name, $res);
- } catch (Net_Gearman_Job_Exception $e) {
- $job->fail();
- $this->fail($handle, $name, $e);
- }
-
- // Force the job's destructor to run
- $job = null;
-
- return true;
- }
-}
-
diff --git a/maintenance/gearman/gearmanRefreshLinks.php b/maintenance/gearman/gearmanRefreshLinks.php
deleted file mode 100644
index 730db96b..00000000
--- a/maintenance/gearman/gearmanRefreshLinks.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-$optionsWithArgs = array( 'fake-job' );
-
-require( dirname( __FILE__ ) . '/../commandLine.inc' );
-require( dirname( __FILE__ ) . '/gearman.inc' );
-
-if ( !$args ) {
- $args = array( 'localhost' );
-}
-$client = new Net_Gearman_Client( $args );
-$batchSize = 1000;
-
-$dbr = wfGetDB( DB_SLAVE );
-$startId = 0;
-$endId = $dbr->selectField( 'page', 'MAX(page_id)', false, __METHOD__ );
-while ( true ) {
- $res = $dbr->select(
- 'page',
- array( 'page_namespace', 'page_title', 'page_id' ),
- array( 'page_id > ' . intval( $startId ) ),
- __METHOD__,
- array( 'LIMIT' => $batchSize )
- );
-
- if ( $res->numRows() == 0 ) {
- break;
- }
- $set = new Net_Gearman_Set;
- foreach ( $res as $row ) {
- $startId = $row->page_id;
- $title = Title::makeTitle( $row->page_namespace, $row->page_title );
- $params = array(
- 'wiki' => wfWikiID(),
- 'title' => $title->getPrefixedDBkey(),
- 'command' => 'refreshLinks',
- 'params' => false,
- );
- $task = new Net_Gearman_Task( 'mw_job', $params );
- $set->addTask( $task );
- }
- $client->runSet( $set );
- print "$startId / $endId\n";
-}
-
diff --git a/maintenance/gearman/gearmanWorker.php b/maintenance/gearman/gearmanWorker.php
deleted file mode 100644
index 3ea10081..00000000
--- a/maintenance/gearman/gearmanWorker.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-$optionsWithArgs = array( 'fake-job', 'procs' );
-require( dirname( __FILE__ ) . '/../commandLine.inc' );
-require( dirname( __FILE__ ) . '/gearman.inc' );
-
-ini_set( 'memory_limit', '150M' );
-
-if ( isset( $options['procs'] ) ) {
- $procs = $options['procs'];
- if ( $procs < 1 || $procs > 1000 ) {
- echo "Invalid number of processes, please specify a number between 1 and 1000\n";
- exit( 1 );
- }
- $fc = new ForkController( $procs, ForkController::RESTART_ON_ERROR );
- if ( $fc->start() != 'child' ) {
- exit( 0 );
- }
-}
-
-if ( !$args ) {
- $args = array( 'localhost' );
-}
-
-if ( isset( $options['fake-job'] ) ) {
- $params = unserialize( $options['fake-job'] );
- MWGearmanJob::runNoSwitch( $params );
-}
-
-$worker = new NonScaryGearmanWorker( $args );
-$worker->addAbility( 'mw_job' );
-$worker->beginWork( 'wfGearmanMonitor' );
-
-function wfGearmanMonitor( $idle, $lastJob ) {
- static $lastSleep = 0;
- $interval = 5;
- $now = time();
- if ( $now - $lastSleep >= $interval ) {
- wfWaitForSlaves();
- $lastSleep = $now;
- }
- return false;
-}
diff --git a/maintenance/generateSitemap.php b/maintenance/generateSitemap.php
index 403e5a24..80d31f97 100644
--- a/maintenance/generateSitemap.php
+++ b/maintenance/generateSitemap.php
@@ -162,6 +162,8 @@ class GenerateSitemap extends Maintenance {
}
private function setNamespacePriorities() {
+ global $wgSitemapNamespacesPriorities;
+
// Custom main namespaces
$this->priorities[self::GS_MAIN] = '0.5';
// Custom talk namesspaces
@@ -183,10 +185,28 @@ class GenerateSitemap extends Maintenance {
$this->priorities[NS_HELP_TALK] = '0.1';
$this->priorities[NS_CATEGORY] = '0.5';
$this->priorities[NS_CATEGORY_TALK] = '0.1';
+
+ // Custom priorities
+ if ( $wgSitemapNamespacesPriorities !== false ) {
+ /**
+ * @var $wgSitemapNamespacesPriorities array
+ */
+ foreach ( $wgSitemapNamespacesPriorities as $namespace => $priority ) {
+ $float = floatval( $priority );
+ if ( $float > 1.0 ) {
+ $priority = '1.0';
+ } elseif ( $float < 0.0 ) {
+ $priority = '0.0';
+ }
+ $this->priorities[$namespace] = $priority;
+ }
+ }
}
/**
* Create directory if it does not exist and return pathname with a trailing slash
+ * @param $fspath string
+ * @return null|string
*/
private static function init_path( $fspath ) {
if ( !isset( $fspath ) ) {
@@ -194,7 +214,7 @@ class GenerateSitemap extends Maintenance {
}
# Create directory if needed
if ( $fspath && !is_dir( $fspath ) ) {
- wfMkdirParents( $fspath ) or die( "Can not create directory $fspath.\n" );
+ wfMkdirParents( $fspath, null, __METHOD__ ) or die( "Can not create directory $fspath.\n" );
}
return realpath( $fspath ) . DIRECTORY_SEPARATOR ;
@@ -327,13 +347,20 @@ class GenerateSitemap extends Maintenance {
* @return Resource
*/
function open( $file, $flags ) {
- return $this->compress ? gzopen( $file, $flags ) : fopen( $file, $flags );
+ $resource = $this->compress ? gzopen( $file, $flags ) : fopen( $file, $flags );
+ if( $resource === false ) {
+ wfDebugDieBacktrace( __METHOD__ . " error opening file $file with flags $flags. Check permissions?" );
+ }
+ return $resource;
}
/**
* gzwrite() / fwrite() wrapper
*/
function write( &$handle, $str ) {
+ if( $handle === true || $handle === false ) {
+ wfDebugDieBacktrace( __METHOD__ . " was passed a boolean as a file handle.\n" );
+ }
if ( $this->compress )
gzwrite( $handle, $str );
else
diff --git a/maintenance/getSlaveServer.php b/maintenance/getSlaveServer.php
index a9d93f1d..3d13bc4e 100644
--- a/maintenance/getSlaveServer.php
+++ b/maintenance/getSlaveServer.php
@@ -32,15 +32,13 @@ class GetSlaveServer extends Maintenance {
global $wgAllDBsAreLocalhost;
if ( $wgAllDBsAreLocalhost ) {
$host = 'localhost';
+ } elseif ( $this->hasOption( 'group' ) ) {
+ $db = wfGetDB( DB_SLAVE, $this->getOption( 'group' ) );
+ $host = $db->getServer();
} else {
- if ( $this->hasOption( 'group' ) ) {
- $db = wfGetDB( DB_SLAVE, $this->getOption( 'group' ) );
- $host = $db->getServer();
- } else {
- $lb = wfGetLB();
- $i = $lb->getReaderIndex();
- $host = $lb->getServerName( $i );
- }
+ $lb = wfGetLB();
+ $i = $lb->getReaderIndex();
+ $host = $lb->getServerName( $i );
}
$this->output( "$host\n" );
}
diff --git a/maintenance/hiphop/extra-files b/maintenance/hiphop/extra-files
index 15f48577..f07f7c7c 100644
--- a/maintenance/hiphop/extra-files
+++ b/maintenance/hiphop/extra-files
@@ -1,5 +1,4 @@
img_auth.php
-includes/AjaxFunctions.php
includes/AutoLoader.php
includes/DefaultSettings.php
includes/Defines.php
diff --git a/maintenance/hiphop/make b/maintenance/hiphop/make
index e792e08b..2bb9951f 100644
--- a/maintenance/hiphop/make
+++ b/maintenance/hiphop/make
@@ -1,9 +1,12 @@
#!/usr/bin/hphpi -f
<?php
+define( 'MW_CONFIG_CALLBACK', 'MakeHipHop::noConfigNeeded' );
require( dirname( __FILE__ ) . '/../Maintenance.php' );
class MakeHipHop extends Maintenance {
+ function noConfigNeeded() {}
+
function execute() {
global $wgHipHopBuildDirectory;
diff --git a/maintenance/ibm_db2/foreignkeys.sql b/maintenance/ibm_db2/foreignkeys.sql
index 81a88eb9..4f1450d9 100644
--- a/maintenance/ibm_db2/foreignkeys.sql
+++ b/maintenance/ibm_db2/foreignkeys.sql
@@ -93,11 +93,6 @@ ALTER TABLE oldimage ADD CONSTRAINT OLDIMAGE_NAME_FK FOREIGN KEY (oi_name) REFER
ALTER TABLE watchlist ADD CONSTRAINT WATCHLIST_USER_FK FOREIGN KEY (wl_user) REFERENCES user(user_id) ON DELETE CASCADE
;
--- good
--- already in MySQL schema
-ALTER TABLE trackbacks ADD CONSTRAINT TRACKBACKS_PAGE_FK FOREIGN KEY (tb_page) REFERENCES page(page_id) ON DELETE CASCADE
-;
-
-- cannot contain null values
-- ALTER TABLE protected_titles ADD CONSTRAINT PROTECTED_TITLES_USER_FK FOREIGN KEY (pt_user) REFERENCES user(user_id) ON DELETE SET NULL
--;
diff --git a/maintenance/ibm_db2/tables.sql b/maintenance/ibm_db2/tables.sql
index 261a3a2b..66fc6564 100644
--- a/maintenance/ibm_db2/tables.sql
+++ b/maintenance/ibm_db2/tables.sql
@@ -1,16 +1,20 @@
--- DB2
+-- IBM DB2
-- 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.
--- This is the IBM DB2 version.
--- For information about each table, please see the notes in maintenance/tables.sql
+
+-- Notes:
+-- * DB2 will convert all table and column names to all caps internally.
+-- * DB2 has a 32k limit on SQL filesize, so it may be necessary
+-- to split this into two files soon.
CREATE TABLE user (
-- Needs to start with 0
- user_id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 0),
- user_name VARCHAR(255) NOT NULL UNIQUE,
+ user_id BIGINT
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 0),
+ user_name VARCHAR(255) NOT NULL UNIQUE,
user_real_name VARCHAR(255),
user_password VARCHAR(1024),
user_newpassword VARCHAR(1024),
@@ -21,225 +25,277 @@ CREATE TABLE user (
user_email_token_expires TIMESTAMP(3),
user_email_authenticated TIMESTAMP(3),
-- obsolete, replace by user_properties table
- user_options CLOB(64K) INLINE LENGTH 4096,
+ -- user_options CLOB(64K) INLINE LENGTH 4096,
user_touched TIMESTAMP(3),
user_registration TIMESTAMP(3),
user_editcount INTEGER
);
-CREATE INDEX user_email_token_idx ON user (user_email_token);
---leonsp:
+CREATE INDEX user_email_token_idx
+ ON user (user_email_token);
CREATE UNIQUE INDEX user_include_idx
- ON user(user_id)
- INCLUDE (user_name, user_real_name, user_password, user_newpassword, user_newpass_time, user_token,
- user_email, user_email_token, user_email_token_expires, user_email_authenticated,
- user_touched, user_registration, user_editcount);
+ ON user (user_id)
+ INCLUDE (user_name, user_real_name, user_password, user_newpassword,
+ user_newpass_time, user_token,
+ user_email, user_email_token, user_email_token_expires,
+ user_email_authenticated,
+ user_touched, user_registration, user_editcount);
+CREATE UNIQUE INDEX user_email
+ ON user (user_email);
+
+
-- Create a dummy user to satisfy fk contraints especially with revisions
INSERT INTO user(
-user_name, user_real_name, user_password, user_newpassword, user_newpass_time,
-user_email, user_email_authenticated, user_options, user_token, user_registration, user_editcount)
+ user_name, user_real_name, user_password, user_newpassword, user_newpass_time,
+ user_email, user_email_authenticated, user_token, user_registration, user_editcount
+)
VALUES (
-'Anonymous','', NULL, NULL, CURRENT_TIMESTAMP,
-NULL, NULL, NULL, NULL, CURRENT_timestamp, 0);
+ 'Anonymous', '', NULL, NULL, CURRENT_TIMESTAMP,
+ NULL, NULL, NULL, CURRENT_TIMESTAMP, 0
+);
+
CREATE TABLE user_groups (
ug_user BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE CASCADE,
- ug_group VARCHAR(255) NOT NULL
+ ug_group VARCHAR(255) NOT NULL
);
-CREATE INDEX user_groups_unique ON user_groups (ug_user, ug_group);
+CREATE INDEX user_groups_unique
+ ON user_groups (ug_user, ug_group);
+
CREATE TABLE user_newtalk (
-- registered users key
- user_id BIGINT NOT NULL DEFAULT 0,
+ user_id BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE CASCADE,
-- anonymous users key
user_ip VARCHAR(40),
user_last_timestamp TIMESTAMP(3)
);
-CREATE INDEX user_newtalk_id_idx ON user_newtalk (user_id);
-CREATE INDEX user_newtalk_ip_idx ON user_newtalk (user_ip);
---leonsp:
+CREATE INDEX user_newtalk_id_idx
+ ON user_newtalk (user_id);
+CREATE INDEX user_newtalk_ip_idx
+ ON user_newtalk (user_ip);
CREATE UNIQUE INDEX user_newtalk_include_idx
- ON user_newtalk(user_id, user_ip)
- INCLUDE (user_last_timestamp);
+ ON user_newtalk (user_id, user_ip)
+ INCLUDE (user_last_timestamp);
+
CREATE TABLE page (
- page_id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- page_namespace SMALLINT NOT NULL,
- page_title VARCHAR(255) NOT NULL,
+ page_id BIGINT
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ page_namespace SMALLINT NOT NULL,
+ page_title VARCHAR(255) NOT NULL,
page_restrictions VARCHAR(1024),
- page_counter BIGINT NOT NULL DEFAULT 0,
- page_is_redirect SMALLINT NOT NULL DEFAULT 0,
- page_is_new SMALLINT NOT NULL DEFAULT 0,
+ page_counter BIGINT NOT NULL DEFAULT 0,
+ page_is_redirect SMALLINT NOT NULL DEFAULT 0,
+ page_is_new SMALLINT NOT NULL DEFAULT 0,
page_random NUMERIC(15,14) NOT NULL,
page_touched TIMESTAMP(3),
- page_latest BIGINT NOT NULL, -- FK?
- page_len BIGINT NOT NULL
-);
-CREATE UNIQUE INDEX page_unique_name ON page (page_namespace, page_title);
-CREATE INDEX page_random_idx ON page (page_random);
-CREATE INDEX page_len_idx ON page (page_len);
---leonsp:
+ page_latest BIGINT NOT NULL, -- FK?
+ page_len BIGINT NOT NULL
+);
+CREATE UNIQUE INDEX page_unique_name
+ ON page (page_namespace, page_title);
+CREATE INDEX page_random_idx
+ ON page (page_random);
+CREATE INDEX page_len_idx
+ ON page (page_len);
CREATE UNIQUE INDEX page_id_include
- ON page (page_id)
- INCLUDE (page_namespace, page_title, page_restrictions, page_counter, page_is_redirect, page_is_new, page_random, page_touched, page_latest, page_len);
+ ON page (page_id)
+ INCLUDE (page_namespace, page_title, page_restrictions, page_counter, page_is_redirect, page_is_new, page_random, page_touched, page_latest, page_len);
CREATE UNIQUE INDEX page_name_include
- ON page (page_namespace, page_title)
- INCLUDE (page_id, page_restrictions, page_counter, page_is_redirect, page_is_new, page_random, page_touched, page_latest, page_len);
+ ON page (page_namespace, page_title)
+ INCLUDE (page_id, page_restrictions, page_counter, page_is_redirect, page_is_new, page_random, page_touched, page_latest, page_len);
+
CREATE TABLE revision (
- rev_id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- rev_page BIGINT NOT NULL DEFAULT 0,
+ rev_id BIGINT
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ rev_page BIGINT NOT NULL DEFAULT 0,
-- REFERENCES page (page_id) ON DELETE CASCADE,
- rev_text_id BIGINT, -- FK
- rev_comment VARCHAR(1024),
- rev_user BIGINT NOT NULL DEFAULT 0,
+ rev_text_id BIGINT, -- FK
+ rev_comment VARCHAR(1024),
+ rev_user BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE RESTRICT,
- rev_user_text VARCHAR(255) NOT NULL,
- rev_timestamp TIMESTAMP(3) NOT NULL,
- rev_minor_edit SMALLINT NOT NULL DEFAULT 0,
- rev_deleted SMALLINT NOT NULL DEFAULT 0,
- rev_len BIGINT,
- rev_parent_id BIGINT DEFAULT NULL
-);
-CREATE UNIQUE INDEX revision_unique ON revision (rev_page, rev_id);
-CREATE INDEX rev_text_id_idx ON revision (rev_text_id);
-CREATE INDEX rev_timestamp_idx ON revision (rev_timestamp);
-CREATE INDEX rev_user_idx ON revision (rev_user);
-CREATE INDEX rev_user_text_idx ON revision (rev_user_text);
+ rev_user_text VARCHAR(255) NOT NULL,
+ rev_timestamp TIMESTAMP(3) NOT NULL,
+ rev_minor_edit SMALLINT NOT NULL DEFAULT 0,
+ rev_deleted SMALLINT NOT NULL DEFAULT 0,
+ rev_len BIGINT,
+ rev_parent_id BIGINT DEFAULT NULL,
+ rev_sha1 VARCHAR(255) NOT NULL DEFAULT ''
+);
+CREATE UNIQUE INDEX revision_unique
+ ON revision (rev_page, rev_id);
+CREATE INDEX rev_text_id_idx
+ ON revision (rev_text_id);
+CREATE INDEX rev_timestamp_idx
+ ON revision (rev_timestamp);
+CREATE INDEX rev_user_idx
+ ON revision (rev_user);
+CREATE INDEX rev_user_text_idx
+ ON revision (rev_user_text);
CREATE TABLE text ( -- replaces reserved word 'text'
- old_id INTEGER PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ old_id INTEGER
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
old_text CLOB(16M) INLINE LENGTH 4096,
old_flags VARCHAR(1024)
);
+
CREATE TABLE page_restrictions (
- --pr_id INTEGER NOT NULL UNIQUE, --DEFAULT nextval('pr_id_val'),
- --pr_id INTEGER PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- pr_id BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- pr_page INTEGER NOT NULL DEFAULT 0,
+ pr_id BIGINT
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ pr_page INTEGER NOT NULL DEFAULT 0,
--(used to be nullable)
-- REFERENCES page (page_id) ON DELETE CASCADE,
- pr_type VARCHAR(60) NOT NULL,
- pr_level VARCHAR(60) NOT NULL,
- pr_cascade SMALLINT NOT NULL,
+ pr_type VARCHAR(60) NOT NULL,
+ pr_level VARCHAR(60) NOT NULL,
+ pr_cascade SMALLINT NOT NULL,
pr_user INTEGER,
pr_expiry TIMESTAMP(3)
--PRIMARY KEY (pr_page, pr_type)
);
---ALTER TABLE page_restrictions ADD CONSTRAINT page_restrictions_pk PRIMARY KEY (pr_page,pr_type);
-CREATE UNIQUE INDEX pr_pagetype ON page_restrictions (pr_page,pr_type);
-CREATE INDEX pr_typelevel ON page_restrictions (pr_type,pr_level);
-CREATE INDEX pr_level ON page_restrictions (pr_level);
-CREATE INDEX pr_cascade ON page_restrictions (pr_cascade);
+--ALTER TABLE page_restrictions ADD CONSTRAINT page_restrictions_pk PRIMARY KEY (pr_page, pr_type);
+CREATE UNIQUE INDEX pr_pagetype
+ ON page_restrictions (pr_page, pr_type);
+CREATE INDEX pr_typelevel
+ ON page_restrictions (pr_type, pr_level);
+CREATE INDEX pr_level
+ ON page_restrictions (pr_level);
+CREATE INDEX pr_cascade
+ ON page_restrictions (pr_cascade);
+
+
CREATE TABLE page_props (
- pp_page INTEGER NOT NULL DEFAULT 0,
+ pp_page INTEGER NOT NULL DEFAULT 0,
-- REFERENCES page (page_id) ON DELETE CASCADE,
- pp_propname VARCHAR(255) NOT NULL,
- pp_value CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- PRIMARY KEY (pp_page,pp_propname)
+ pp_propname VARCHAR(255) NOT NULL,
+ pp_value CLOB(64K) INLINE LENGTH 4096 NOT NULL,
+ PRIMARY KEY (pp_page, pp_propname)
);
---ALTER TABLE page_props ADD CONSTRAINT page_props_pk PRIMARY KEY (pp_page,pp_propname);
-CREATE INDEX page_props_propname ON page_props (pp_propname);
+CREATE INDEX page_props_propname
+ ON page_props (pp_propname);
CREATE TABLE archive (
- ar_namespace SMALLINT NOT NULL,
- ar_title VARCHAR(255) NOT NULL,
+ ar_namespace SMALLINT NOT NULL,
+ ar_title VARCHAR(255) NOT NULL,
ar_text CLOB(16M) INLINE LENGTH 4096,
ar_comment VARCHAR(1024),
ar_user BIGINT NOT NULL,
-- no foreign keys in MySQL
-- REFERENCES user(user_id) ON DELETE SET NULL,
- ar_user_text VARCHAR(255) NOT NULL,
- ar_timestamp TIMESTAMP(3) NOT NULL,
- ar_minor_edit SMALLINT NOT NULL DEFAULT 0,
+ ar_user_text VARCHAR(255) NOT NULL,
+ ar_timestamp TIMESTAMP(3) NOT NULL,
+ ar_minor_edit SMALLINT NOT NULL DEFAULT 0,
ar_flags VARCHAR(1024),
ar_rev_id INTEGER,
ar_text_id INTEGER,
- ar_deleted SMALLINT NOT NULL DEFAULT 0,
+ ar_deleted SMALLINT NOT NULL DEFAULT 0,
ar_len INTEGER,
ar_page_id INTEGER,
- ar_parent_id INTEGER
+ ar_parent_id INTEGER,
+ ar_sha1 VARCHAR(255) NOT NULL DEFAULT ''
);
-CREATE INDEX archive_name_title_timestamp ON archive (ar_namespace,ar_title,ar_timestamp);
-CREATE INDEX archive_user_text ON archive (ar_user_text);
+CREATE INDEX archive_name_title_timestamp
+ ON archive (ar_namespace, ar_title, ar_timestamp);
+CREATE INDEX archive_user_text
+ ON archive (ar_user_text);
CREATE TABLE redirect (
- rd_from BIGINT NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ rd_from BIGINT NOT NULL
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
--REFERENCES page(page_id) ON DELETE CASCADE,
- rd_namespace SMALLINT NOT NULL DEFAULT 0,
- rd_title VARCHAR(255) NOT NULL DEFAULT '',
- rd_interwiki varchar(32),
+ rd_namespace SMALLINT NOT NULL DEFAULT 0,
+ rd_title VARCHAR(255) NOT NULL DEFAULT '',
+ rd_interwiki VARCHAR(32),
rd_fragment VARCHAR(255)
);
-CREATE INDEX redirect_ns_title ON redirect (rd_namespace,rd_title,rd_from);
+CREATE INDEX redirect_ns_title
+ ON redirect (rd_namespace, rd_title, rd_from);
CREATE TABLE pagelinks (
- pl_from BIGINT NOT NULL DEFAULT 0,
+ pl_from BIGINT NOT NULL DEFAULT 0,
-- REFERENCES page(page_id) ON DELETE CASCADE,
- pl_namespace SMALLINT NOT NULL,
- pl_title VARCHAR(255) NOT NULL
+ pl_namespace SMALLINT NOT NULL,
+ pl_title VARCHAR(255) NOT NULL
);
-CREATE UNIQUE INDEX pagelink_unique ON pagelinks (pl_from,pl_namespace,pl_title);
+CREATE UNIQUE INDEX pagelink_unique
+ ON pagelinks (pl_from, pl_namespace, pl_title);
+
+
CREATE TABLE templatelinks (
- tl_from BIGINT NOT NULL DEFAULT 0,
+ tl_from BIGINT NOT NULL DEFAULT 0,
-- REFERENCES page(page_id) ON DELETE CASCADE,
tl_namespace SMALLINT NOT NULL,
- tl_title VARCHAR(255) NOT NULL
+ tl_title VARCHAR(255) NOT NULL
);
-CREATE UNIQUE INDEX templatelinks_unique ON templatelinks (tl_namespace,tl_title,tl_from);
-CREATE UNIQUE INDEX tl_from_idx ON templatelinks (tl_from,tl_namespace,tl_title);
+CREATE UNIQUE INDEX templatelinks_unique
+ ON templatelinks (tl_namespace, tl_title, tl_from);
+CREATE UNIQUE INDEX tl_from_idx
+ ON templatelinks (tl_from, tl_namespace, tl_title);
+
+
CREATE TABLE imagelinks (
- il_from BIGINT NOT NULL DEFAULT 0,
+ il_from BIGINT NOT NULL DEFAULT 0,
-- REFERENCES page(page_id) ON DELETE CASCADE,
- il_to VARCHAR(255) NOT NULL
+ il_to VARCHAR(255) NOT NULL
);
-CREATE UNIQUE INDEX il_from_idx ON imagelinks (il_to,il_from);
-CREATE UNIQUE INDEX il_to_idx ON imagelinks (il_from,il_to);
+CREATE UNIQUE INDEX il_from_idx
+ ON imagelinks (il_to, il_from);
+CREATE UNIQUE INDEX il_to_idx
+ ON imagelinks (il_from, il_to);
+
+
CREATE TABLE categorylinks (
- cl_from BIGINT NOT NULL DEFAULT 0,
+ cl_from BIGINT NOT NULL DEFAULT 0,
-- REFERENCES page(page_id) ON DELETE CASCADE,
- cl_to VARCHAR(255) NOT NULL,
+ cl_to VARCHAR(255) NOT NULL,
-- cl_sortkey has to be at least 86 wide
-- in order to be compatible with the old MySQL schema from MW 1.10
--cl_sortkey VARCHAR(86),
- cl_sortkey VARCHAR(230) FOR BIT DATA NOT NULL ,
- cl_sortkey_prefix VARCHAR(255) FOR BIT DATA NOT NULL ,
- cl_timestamp TIMESTAMP(3) NOT NULL,
- cl_collation VARCHAR(32) FOR BIT DATA NOT NULL ,
- cl_type VARCHAR(6) FOR BIT DATA NOT NULL
+ cl_sortkey VARCHAR(230) FOR BIT DATA NOT NULL,
+ cl_sortkey_prefix VARCHAR(255) FOR BIT DATA NOT NULL,
+ cl_timestamp TIMESTAMP(3) NOT NULL,
+ cl_collation VARCHAR(32) FOR BIT DATA NOT NULL,
+ cl_type VARCHAR(6) FOR BIT DATA NOT NULL
);
-CREATE UNIQUE INDEX cl_from ON categorylinks (cl_from, cl_to);
-CREATE INDEX cl_sortkey ON categorylinks (cl_to, cl_sortkey, cl_from);
+CREATE UNIQUE INDEX cl_from
+ ON categorylinks (cl_from, cl_to);
+CREATE INDEX cl_sortkey
+ ON categorylinks (cl_to, cl_sortkey, cl_from);
CREATE TABLE externallinks (
- el_from BIGINT NOT NULL DEFAULT 0,
+ el_from BIGINT NOT NULL DEFAULT 0,
-- REFERENCES page(page_id) ON DELETE CASCADE,
- el_to VARCHAR(1024) NOT NULL,
- el_index VARCHAR(1024) NOT NULL
+ el_to VARCHAR(1024) NOT NULL,
+ el_index VARCHAR(1024) NOT NULL
);
-CREATE INDEX externallinks_from_to ON externallinks (el_from,el_to);
-CREATE INDEX externallinks_index ON externallinks (el_index);
+CREATE INDEX externallinks_from_to
+ ON externallinks (el_from, el_to);
+CREATE INDEX externallinks_index
+ ON externallinks (el_index);
+
--
@@ -247,494 +303,636 @@ CREATE INDEX externallinks_index ON externallinks (el_index);
--
CREATE TABLE external_user (
-- Foreign key to user_id
- eu_local_id BIGINT NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ eu_local_id BIGINT NOT NULL
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
-- Some opaque identifier provided by the external database
- eu_external_id VARCHAR(255) NOT NULL
+ eu_external_id VARCHAR(255) NOT NULL
);
CREATE UNIQUE INDEX eu_external_id_idx
- ON external_user (eu_external_id)
- INCLUDE (eu_local_id);
+ ON external_user (eu_external_id)
+ INCLUDE (eu_local_id);
CREATE UNIQUE INDEX eu_local_id_idx
- ON external_user (eu_local_id)
- INCLUDE (eu_external_id);
+ ON external_user (eu_local_id)
+ INCLUDE (eu_external_id);
CREATE TABLE langlinks (
- ll_from BIGINT NOT NULL DEFAULT 0,
+ ll_from BIGINT NOT NULL DEFAULT 0,
-- REFERENCES page (page_id) ON DELETE CASCADE,
ll_lang VARCHAR(20),
ll_title VARCHAR(255)
);
-CREATE UNIQUE INDEX langlinks_unique ON langlinks (ll_from,ll_lang);
-CREATE INDEX langlinks_lang_title ON langlinks (ll_lang,ll_title);
+CREATE UNIQUE INDEX langlinks_unique
+ ON langlinks (ll_from, ll_lang);
+CREATE INDEX langlinks_lang_title
+ ON langlinks (ll_lang, ll_title);
+
CREATE TABLE site_stats (
- ss_row_id BIGINT NOT NULL UNIQUE,
- ss_total_views BIGINT DEFAULT 0,
- ss_total_edits BIGINT DEFAULT 0,
- ss_good_articles BIGINT DEFAULT 0,
- ss_total_pages INTEGER DEFAULT -1,
- ss_users INTEGER DEFAULT -1,
- ss_active_users INTEGER DEFAULT -1,
- ss_admins INTEGER DEFAULT -1,
- ss_images INTEGER DEFAULT 0
+ ss_row_id BIGINT NOT NULL UNIQUE,
+ ss_total_views BIGINT DEFAULT 0,
+ ss_total_edits BIGINT DEFAULT 0,
+ ss_good_articles BIGINT DEFAULT 0,
+ ss_total_pages INTEGER DEFAULT -1,
+ ss_users INTEGER DEFAULT -1,
+ ss_active_users INTEGER DEFAULT -1,
+ ss_admins INTEGER DEFAULT -1,
+ ss_images INTEGER DEFAULT 0
);
+
+
CREATE TABLE hitcounter (
- hc_id BIGINT NOT NULL
+ hc_id BIGINT NOT NULL
);
+
+
CREATE TABLE ipblocks (
- ipb_id INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- --DEFAULT nextval('ipblocks_ipb_id_val'),
+ ipb_id INTEGER NOT NULL
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
ipb_address VARCHAR(1024),
ipb_user BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE SET NULL,
- ipb_by BIGINT NOT NULL DEFAULT 0,
+ ipb_by BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE CASCADE,
- ipb_by_text VARCHAR(255) NOT NULL DEFAULT '',
- ipb_reason VARCHAR(1024) NOT NULL,
- ipb_timestamp TIMESTAMP(3) NOT NULL,
- ipb_auto SMALLINT NOT NULL DEFAULT 0,
- ipb_anon_only SMALLINT NOT NULL DEFAULT 0,
- ipb_create_account SMALLINT NOT NULL DEFAULT 1,
- ipb_enable_autoblock SMALLINT NOT NULL DEFAULT 1,
- ipb_expiry TIMESTAMP(3) NOT NULL,
+ ipb_by_text VARCHAR(255) NOT NULL DEFAULT '',
+ ipb_reason VARCHAR(1024) NOT NULL,
+ ipb_timestamp TIMESTAMP(3) NOT NULL,
+ ipb_auto SMALLINT NOT NULL DEFAULT 0,
+ ipb_anon_only SMALLINT NOT NULL DEFAULT 0,
+ ipb_create_account SMALLINT NOT NULL DEFAULT 1,
+ ipb_enable_autoblock SMALLINT NOT NULL DEFAULT 1,
+ ipb_expiry TIMESTAMP(3) NOT NULL,
ipb_range_start VARCHAR(1024),
ipb_range_end VARCHAR(1024),
- ipb_deleted SMALLINT NOT NULL DEFAULT 0,
- ipb_block_email SMALLINT NOT NULL DEFAULT 0,
- ipb_allow_usertalk SMALLINT NOT NULL DEFAULT 0
+ ipb_deleted SMALLINT NOT NULL DEFAULT 0,
+ ipb_block_email SMALLINT NOT NULL DEFAULT 0,
+ ipb_allow_usertalk SMALLINT NOT NULL DEFAULT 0
);
-CREATE INDEX ipb_address ON ipblocks (ipb_address);
-CREATE INDEX ipb_user ON ipblocks (ipb_user);
-CREATE INDEX ipb_range ON ipblocks (ipb_range_start,ipb_range_end);
+CREATE INDEX ipb_address
+ ON ipblocks (ipb_address);
+CREATE INDEX ipb_user
+ ON ipblocks (ipb_user);
+CREATE INDEX ipb_range
+ ON ipblocks (ipb_range_start, ipb_range_end);
CREATE TABLE image (
- img_name VARCHAR(255) NOT NULL PRIMARY KEY,
- img_size BIGINT NOT NULL,
- img_width INTEGER NOT NULL,
- img_height INTEGER NOT NULL,
- img_metadata CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
+ img_name VARCHAR(255) NOT NULL
+ PRIMARY KEY,
+ img_size BIGINT NOT NULL,
+ img_width INTEGER NOT NULL,
+ img_height INTEGER NOT NULL,
+ img_metadata CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
img_bits SMALLINT,
img_media_type VARCHAR(255),
- img_major_mime VARCHAR(255) DEFAULT 'unknown',
- img_minor_mime VARCHAR(32) DEFAULT 'unknown',
- img_description VARCHAR(1024) NOT NULL DEFAULT '',
+ img_major_mime VARCHAR(255) DEFAULT 'unknown',
+ img_minor_mime VARCHAR(32) DEFAULT 'unknown',
+ img_description VARCHAR(1024) NOT NULL DEFAULT '',
img_user BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE SET NULL,
- img_user_text VARCHAR(255) NOT NULL DEFAULT '',
+ img_user_text VARCHAR(255) NOT NULL DEFAULT '',
img_timestamp TIMESTAMP(3),
- img_sha1 VARCHAR(255) NOT NULL DEFAULT ''
+ img_sha1 VARCHAR(255) NOT NULL DEFAULT ''
);
-CREATE INDEX img_size_idx ON image (img_size);
-CREATE INDEX img_timestamp_idx ON image (img_timestamp);
-CREATE INDEX img_sha1 ON image (img_sha1);
+CREATE INDEX img_size_idx
+ ON image (img_size);
+CREATE INDEX img_timestamp_idx
+ ON image (img_timestamp);
+CREATE INDEX img_sha1
+ ON image (img_sha1);
+
CREATE TABLE oldimage (
- oi_name VARCHAR(255) NOT NULL DEFAULT '',
- oi_archive_name VARCHAR(255) NOT NULL,
- oi_size BIGINT NOT NULL,
- oi_width INTEGER NOT NULL,
- oi_height INTEGER NOT NULL,
- oi_bits SMALLINT NOT NULL,
+ oi_name VARCHAR(255) NOT NULL DEFAULT '',
+ oi_archive_name VARCHAR(255) NOT NULL,
+ oi_size BIGINT NOT NULL,
+ oi_width INTEGER NOT NULL,
+ oi_height INTEGER NOT NULL,
+ oi_bits SMALLINT NOT NULL,
oi_description VARCHAR(1024),
oi_user BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE SET NULL,
- oi_user_text VARCHAR(255) NOT NULL,
- oi_timestamp TIMESTAMP(3) NOT NULL,
- oi_metadata CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
- oi_media_type VARCHAR(255) ,
- oi_major_mime VARCHAR(255) NOT NULL DEFAULT 'unknown',
- oi_minor_mime VARCHAR(255) NOT NULL DEFAULT 'unknown',
- oi_deleted SMALLINT NOT NULL DEFAULT 0,
- oi_sha1 VARCHAR(255) NOT NULL DEFAULT ''
+ oi_user_text VARCHAR(255) NOT NULL,
+ oi_timestamp TIMESTAMP(3) NOT NULL,
+ oi_metadata CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
+ oi_media_type VARCHAR(255),
+ oi_major_mime VARCHAR(255) NOT NULL DEFAULT 'unknown',
+ oi_minor_mime VARCHAR(255) NOT NULL DEFAULT 'unknown',
+ oi_deleted SMALLINT NOT NULL DEFAULT 0,
+ oi_sha1 VARCHAR(255) NOT NULL DEFAULT ''
--FOREIGN KEY (oi_name) REFERENCES image(img_name) ON DELETE CASCADE
);
-CREATE INDEX oi_name_timestamp ON oldimage (oi_name,oi_timestamp);
-CREATE INDEX oi_name_archive_name ON oldimage (oi_name,oi_archive_name);
-CREATE INDEX oi_sha1 ON oldimage (oi_sha1);
+CREATE INDEX oi_name_timestamp
+ ON oldimage (oi_name, oi_timestamp);
+CREATE INDEX oi_name_archive_name
+ ON oldimage (oi_name, oi_archive_name);
+CREATE INDEX oi_sha1
+ ON oldimage (oi_sha1);
CREATE TABLE filearchive (
- fa_id INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- --PRIMARY KEY DEFAULT nextval('filearchive_fa_id_seq'),
- fa_name VARCHAR(255) NOT NULL,
+ fa_id INTEGER NOT NULL
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ fa_name VARCHAR(255) NOT NULL,
fa_archive_name VARCHAR(255),
fa_storage_group VARCHAR(255),
- fa_storage_key VARCHAR(64) DEFAULT '',
- fa_deleted_user BIGINT NOT NULL DEFAULT 0,
+ fa_storage_key VARCHAR(64) DEFAULT '',
+ fa_deleted_user BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE SET NULL,
- fa_deleted_timestamp TIMESTAMP(3) NOT NULL,
+ fa_deleted_timestamp TIMESTAMP(3) NOT NULL,
fa_deleted_reason VARCHAR(255),
- fa_size BIGINT NOT NULL,
- fa_width INTEGER NOT NULL,
- fa_height INTEGER NOT NULL,
- fa_metadata CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
+ fa_size BIGINT NOT NULL,
+ fa_width INTEGER NOT NULL,
+ fa_height INTEGER NOT NULL,
+ fa_metadata CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
fa_bits SMALLINT,
fa_media_type VARCHAR(255),
- fa_major_mime VARCHAR(255) DEFAULT 'unknown',
- fa_minor_mime VARCHAR(255) DEFAULT 'unknown',
- fa_description VARCHAR(1024) NOT NULL,
+ fa_major_mime VARCHAR(255) DEFAULT 'unknown',
+ fa_minor_mime VARCHAR(255) DEFAULT 'unknown',
+ fa_description VARCHAR(1024) NOT NULL,
fa_user BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE SET NULL,
- fa_user_text VARCHAR(255) NOT NULL,
+ fa_user_text VARCHAR(255) NOT NULL,
fa_timestamp TIMESTAMP(3),
- fa_deleted SMALLINT NOT NULL DEFAULT 0
+ fa_deleted SMALLINT NOT NULL DEFAULT 0
);
-CREATE INDEX fa_name_time ON filearchive (fa_name, fa_timestamp);
-CREATE INDEX fa_dupe ON filearchive (fa_storage_group, fa_storage_key);
-CREATE INDEX fa_notime ON filearchive (fa_deleted_timestamp);
-CREATE INDEX fa_nouser ON filearchive (fa_deleted_user);
+CREATE INDEX fa_name_time
+ ON filearchive (fa_name, fa_timestamp);
+CREATE INDEX fa_dupe
+ ON filearchive (fa_storage_group, fa_storage_key);
+CREATE INDEX fa_notime
+ ON filearchive (fa_deleted_timestamp);
+CREATE INDEX fa_nouser
+ ON filearchive (fa_deleted_user);
+
CREATE TABLE recentchanges (
- rc_id INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- --PRIMARY KEY DEFAULT nextval('rc_rc_id_seq'),
- rc_timestamp TIMESTAMP(3) NOT NULL,
- rc_cur_time TIMESTAMP(3) NOT NULL,
+ rc_id INTEGER NOT NULL
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ rc_timestamp TIMESTAMP(3) NOT NULL,
+ rc_cur_time TIMESTAMP(3) NOT NULL,
rc_user BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE SET NULL,
- rc_user_text VARCHAR(255) NOT NULL,
- rc_namespace SMALLINT NOT NULL,
- rc_title VARCHAR(255) NOT NULL,
+ rc_user_text VARCHAR(255) NOT NULL,
+ rc_namespace SMALLINT NOT NULL,
+ rc_title VARCHAR(255) NOT NULL,
rc_comment VARCHAR(255),
- rc_minor SMALLINT NOT NULL DEFAULT 0,
- rc_bot SMALLINT NOT NULL DEFAULT 0,
- rc_new SMALLINT NOT NULL DEFAULT 0,
+ rc_minor SMALLINT NOT NULL DEFAULT 0,
+ rc_bot SMALLINT NOT NULL DEFAULT 0,
+ rc_new SMALLINT NOT NULL DEFAULT 0,
rc_cur_id BIGINT NOT NULL DEFAULT 0,
-- REFERENCES page(page_id) ON DELETE SET NULL,
- rc_this_oldid BIGINT NOT NULL,
- rc_last_oldid BIGINT NOT NULL,
- rc_type SMALLINT NOT NULL DEFAULT 0,
+ rc_this_oldid BIGINT NOT NULL,
+ rc_last_oldid BIGINT NOT NULL,
+ rc_type SMALLINT NOT NULL DEFAULT 0,
rc_moved_to_ns SMALLINT,
rc_moved_to_title VARCHAR(255),
- rc_patrolled SMALLINT NOT NULL DEFAULT 0,
- rc_ip VARCHAR(40), -- was CIDR type
+ rc_patrolled SMALLINT NOT NULL DEFAULT 0,
+ rc_ip VARCHAR(40), -- was CIDR type
rc_old_len INTEGER,
rc_new_len INTEGER,
- rc_deleted SMALLINT NOT NULL DEFAULT 0,
- rc_logid BIGINT NOT NULL DEFAULT 0,
+ rc_deleted SMALLINT NOT NULL DEFAULT 0,
+ rc_logid BIGINT NOT NULL DEFAULT 0,
rc_log_type VARCHAR(255),
rc_log_action VARCHAR(255),
rc_params CLOB(64K) INLINE LENGTH 4096
);
-CREATE INDEX rc_timestamp ON recentchanges (rc_timestamp);
-CREATE INDEX rc_namespace_title ON recentchanges (rc_namespace, rc_title);
-CREATE INDEX rc_cur_id ON recentchanges (rc_cur_id);
-CREATE INDEX new_name_timestamp ON recentchanges (rc_new, rc_namespace, rc_timestamp);
-CREATE INDEX rc_ip ON recentchanges (rc_ip);
+CREATE INDEX rc_timestamp
+ ON recentchanges (rc_timestamp);
+CREATE INDEX rc_namespace_title
+ ON recentchanges (rc_namespace, rc_title);
+CREATE INDEX rc_cur_id
+ ON recentchanges (rc_cur_id);
+CREATE INDEX new_name_timestamp
+ ON recentchanges (rc_new, rc_namespace, rc_timestamp);
+CREATE INDEX rc_ip
+ ON recentchanges (rc_ip);
CREATE TABLE watchlist (
- wl_user BIGINT NOT NULL DEFAULT 0,
+ wl_user BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE CASCADE,
- wl_namespace SMALLINT NOT NULL DEFAULT 0,
- wl_title VARCHAR(255) NOT NULL,
+ wl_namespace SMALLINT NOT NULL DEFAULT 0,
+ wl_title VARCHAR(255) NOT NULL,
wl_notificationtimestamp TIMESTAMP(3)
);
-CREATE UNIQUE INDEX wl_user_namespace_title ON watchlist (wl_namespace, wl_title, wl_user);
+CREATE UNIQUE INDEX wl_user_namespace_title
+ ON watchlist (wl_namespace, wl_title, wl_user);
+
CREATE TABLE interwiki (
- iw_prefix VARCHAR(32) NOT NULL UNIQUE,
- iw_url CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- iw_api CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- iw_wikiid varchar(64) NOT NULL,
- iw_local SMALLINT NOT NULL,
- iw_trans SMALLINT NOT NULL DEFAULT 0
+ iw_prefix VARCHAR(32) NOT NULL UNIQUE,
+ iw_url CLOB(64K) INLINE LENGTH 4096 NOT NULL,
+ iw_api CLOB(64K) INLINE LENGTH 4096 NOT NULL,
+ iw_wikiid VARCHAR(64) NOT NULL,
+ iw_local SMALLINT NOT NULL,
+ iw_trans SMALLINT NOT NULL DEFAULT 0
);
+
CREATE TABLE querycache (
- qc_type VARCHAR(255) NOT NULL,
- qc_value BIGINT NOT NULL,
- qc_namespace INTEGER NOT NULL,
- qc_title VARCHAR(255) NOT NULL
+ qc_type VARCHAR(255) NOT NULL,
+ qc_value BIGINT NOT NULL,
+ qc_namespace INTEGER NOT NULL,
+ qc_title VARCHAR(255) NOT NULL
);
-CREATE INDEX querycache_type_value ON querycache (qc_type, qc_value);
+CREATE INDEX querycache_type_value
+ ON querycache (qc_type, qc_value);
-CREATE TABLE querycache_info (
- qci_type VARCHAR(255) UNIQUE NOT NULL,
- qci_timestamp TIMESTAMP(3)
+CREATE TABLE querycache_info (
+ qci_type VARCHAR(255) UNIQUE NOT NULL,
+ qci_timestamp TIMESTAMP(3)
);
+
CREATE TABLE querycachetwo (
- qcc_type VARCHAR(255) NOT NULL,
- qcc_value BIGINT NOT NULL DEFAULT 0,
- qcc_namespace INTEGER NOT NULL DEFAULT 0,
- qcc_title VARCHAR(255) NOT NULL DEFAULT '',
- qcc_namespacetwo INTEGER NOT NULL DEFAULT 0,
- qcc_titletwo VARCHAR(255) NOT NULL DEFAULT ''
+ qcc_type VARCHAR(255) NOT NULL,
+ qcc_value BIGINT NOT NULL DEFAULT 0,
+ qcc_namespace INTEGER NOT NULL DEFAULT 0,
+ qcc_title VARCHAR(255) NOT NULL DEFAULT '',
+ qcc_namespacetwo INTEGER NOT NULL DEFAULT 0,
+ qcc_titletwo VARCHAR(255) 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 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 VARCHAR(255) NOT NULL UNIQUE, -- was nullable
- value CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
- exptime TIMESTAMP(3) NOT NULL
+ keyname VARCHAR(255) NOT NULL UNIQUE, -- was nullable
+ value CLOB(16M) INLINE LENGTH 4096 NOT NULL DEFAULT '',
+ exptime TIMESTAMP(3) NOT NULL
);
-CREATE INDEX objectcacache_exptime ON objectcache (exptime);
+CREATE INDEX objectcacache_exptime
+ ON objectcache (exptime);
CREATE TABLE transcache (
- tc_url VARCHAR(255) NOT NULL UNIQUE,
- tc_contents CLOB(64K) INLINE LENGTH 4096 NOT NULL,
- tc_time TIMESTAMP(3) NOT NULL
+ tc_url VARCHAR(255) NOT NULL UNIQUE,
+ tc_contents CLOB(64K) INLINE LENGTH 4096 NOT NULL,
+ tc_time TIMESTAMP(3) NOT NULL
);
+
CREATE TABLE logging (
- log_id BIGINT NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- --PRIMARY KEY DEFAULT nextval('log_log_id_seq'),
- log_type VARCHAR(32) NOT NULL,
- log_action VARCHAR(32) NOT NULL,
- log_timestamp TIMESTAMP(3) NOT NULL,
- log_user BIGINT NOT NULL DEFAULT 0,
+ log_id BIGINT NOT NULL
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ log_type VARCHAR(32) NOT NULL,
+ log_action VARCHAR(32) NOT NULL,
+ log_timestamp TIMESTAMP(3) NOT NULL,
+ log_user BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE SET NULL,
-- Name of the user who performed this action
- log_user_text VARCHAR(255) NOT NULL default '',
- log_namespace SMALLINT NOT NULL,
- log_title VARCHAR(255) NOT NULL,
- log_page BIGINT,
- log_comment VARCHAR(255),
- log_params CLOB(64K) INLINE LENGTH 4096,
- log_deleted SMALLINT NOT NULL DEFAULT 0
-);
-CREATE INDEX logging_type_name ON logging (log_type, log_timestamp);
-CREATE INDEX logging_user_time ON logging (log_timestamp, log_user);
-CREATE INDEX logging_page_time ON logging (log_namespace, log_title, log_timestamp);
-CREATE INDEX log_user_type_time ON logging (log_user, log_type, log_timestamp);
-CREATE INDEX log_page_id_time ON logging (log_page,log_timestamp);
+ log_user_text VARCHAR(255) NOT NULL DEFAULT '',
+ log_namespace SMALLINT NOT NULL,
+ log_title VARCHAR(255) NOT NULL,
+ log_page BIGINT,
+ log_comment VARCHAR(255),
+ log_params CLOB(64K) INLINE LENGTH 4096,
+ log_deleted SMALLINT NOT NULL DEFAULT 0
+);
+CREATE INDEX logging_type_name
+ ON logging (log_type, log_timestamp);
+CREATE INDEX logging_user_time
+ ON logging (log_timestamp, log_user);
+CREATE INDEX logging_page_time
+ ON logging (log_namespace, log_title, log_timestamp);
+CREATE INDEX log_user_type_time
+ ON logging (log_user, log_type, log_timestamp);
+CREATE INDEX log_page_id_time
+ ON logging (log_page, log_timestamp);
+CREATE UNIQUE INDEX type_action
+ ON logging (log_type, log_action, log_timestamp);
CREATE TABLE trackbacks (
- tb_id INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- --PRIMARY KEY DEFAULT nextval('trackbacks_tb_id_seq'),
+ tb_id INTEGER NOT NULL
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
-- foreign key also in MySQL
tb_page INTEGER,
-- REFERENCES page(page_id) ON DELETE CASCADE,
- tb_title VARCHAR(255) NOT NULL,
- tb_url CLOB(64K) INLINE LENGTH 4096 NOT NULL,
+ tb_title VARCHAR(255) NOT NULL,
+ tb_url CLOB(64K) INLINE LENGTH 4096 NOT NULL,
tb_ex CLOB(64K) INLINE LENGTH 4096,
tb_name VARCHAR(255)
);
-CREATE INDEX trackback_page ON trackbacks (tb_page);
+CREATE INDEX trackback_page
+ ON trackbacks (tb_page);
CREATE TABLE job (
- job_id BIGINT NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- --PRIMARY KEY DEFAULT nextval('job_job_id_seq'),
- job_cmd VARCHAR(255) NOT NULL,
- job_namespace SMALLINT NOT NULL,
- job_title VARCHAR(255) NOT NULL,
- job_params CLOB(64K) INLINE LENGTH 4096 NOT NULL
+ job_id BIGINT NOT NULL
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ job_cmd VARCHAR(255) NOT NULL,
+ job_namespace SMALLINT NOT NULL,
+ job_title VARCHAR(255) NOT NULL,
+ job_params CLOB(64K) INLINE LENGTH 4096 NOT NULL
);
-CREATE INDEX job_cmd_namespace_title ON job (job_cmd, job_namespace, job_title);
+CREATE INDEX job_cmd_namespace_title
+ ON job (job_cmd, job_namespace, job_title);
+
--TODO
---CREATE FUNCTION add_interwiki (TEXT,INT,SMALLINT) RETURNS INT LANGUAGE SQL AS
+--CREATE FUNCTION add_interwiki (TEXT, INT, SMALLINT) RETURNS INT LANGUAGE SQL AS
--$mw$
-- INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES ($1,$2,$3);
-- SELECT 1;
--$mw$;
+
+
-- hack implementation
-- should be replaced with OmniFind, Contains(), etc
CREATE TABLE searchindex (
- si_page BIGINT NOT NULL,
- si_title varchar(255) NOT NULL default '',
- si_text clob NOT NULL
+ si_page BIGINT NOT NULL,
+ si_title VARCHAR(255) NOT NULL DEFAULT '',
+ si_text CLOB NOT NULL
);
+
+
-- This table is not used unless profiling is turned on
CREATE TABLE profiling (
- pf_count INTEGER NOT NULL DEFAULT 0,
- pf_time NUMERIC(18,10) NOT NULL DEFAULT 0,
- pf_memory NUMERIC(18,10) NOT NULL DEFAULT 0,
- pf_name VARCHAR(255) NOT NULL,
- pf_server VARCHAR(255)
+ pf_count INTEGER NOT NULL DEFAULT 0,
+ pf_time NUMERIC(18,10) NOT NULL DEFAULT 0,
+ pf_memory NUMERIC(18,10) NOT NULL DEFAULT 0,
+ pf_name VARCHAR(255) NOT NULL,
+ pf_server VARCHAR(255)
);
-CREATE UNIQUE INDEX pf_name_server ON profiling (pf_name, pf_server);
+CREATE UNIQUE INDEX pf_name_server
+ ON profiling (pf_name, pf_server);
+
+
CREATE TABLE protected_titles (
- pt_namespace INTEGER NOT NULL,
- pt_title VARCHAR(255) NOT NULL,
+ pt_namespace INTEGER NOT NULL,
+ pt_title VARCHAR(255) NOT NULL,
pt_user BIGINT NOT NULL DEFAULT 0,
-- REFERENCES user(user_id) ON DELETE SET NULL,
pt_reason VARCHAR(1024),
pt_timestamp TIMESTAMP(3) NOT NULL,
- pt_expiry TIMESTAMP(3) ,
- pt_create_perm VARCHAR(60) NOT NULL DEFAULT ''
+ pt_expiry TIMESTAMP(3),
+ pt_create_perm VARCHAR(60) NOT NULL DEFAULT ''
);
-CREATE UNIQUE INDEX protected_titles_unique ON protected_titles(pt_namespace, pt_title);
+CREATE UNIQUE INDEX protected_titles_unique
+ ON protected_titles (pt_namespace, pt_title);
CREATE TABLE updatelog (
- ul_key VARCHAR(255) NOT NULL PRIMARY KEY
+ ul_key VARCHAR(255) NOT NULL
+ PRIMARY KEY
);
+
CREATE TABLE category (
- cat_id INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
- --PRIMARY KEY DEFAULT nextval('category_id_seq'),
- cat_title VARCHAR(255) NOT NULL,
- cat_pages INTEGER NOT NULL DEFAULT 0,
- cat_subcats INTEGER NOT NULL DEFAULT 0,
- cat_files INTEGER NOT NULL DEFAULT 0,
- cat_hidden SMALLINT NOT NULL DEFAULT 0
+ cat_id INTEGER NOT NULL
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ cat_title VARCHAR(255) NOT NULL,
+ cat_pages INTEGER NOT NULL DEFAULT 0,
+ cat_subcats INTEGER NOT NULL DEFAULT 0,
+ cat_files INTEGER NOT NULL DEFAULT 0,
+ cat_hidden SMALLINT NOT NULL DEFAULT 0
);
-CREATE UNIQUE INDEX category_title ON category(cat_title);
-CREATE INDEX category_pages ON category(cat_pages);
+CREATE UNIQUE INDEX category_title
+ ON category (cat_title);
+CREATE INDEX category_pages
+ ON category (cat_pages);
+
--- added for 1.15
-- A table to track tags for revisions, logs and recent changes.
CREATE TABLE change_tag (
- ct_rc_id INTEGER,
- ct_log_id INTEGER,
- ct_rev_id INTEGER,
- ct_tag varchar(255) NOT NULL,
- ct_params CLOB(64K) INLINE LENGTH 4096
-);
-CREATE UNIQUE INDEX change_tag_rc_tag ON change_tag (ct_rc_id,ct_tag);
-CREATE UNIQUE INDEX change_tag_log_tag ON change_tag (ct_log_id,ct_tag);
-CREATE UNIQUE INDEX change_tag_rev_tag ON change_tag (ct_rev_id,ct_tag);
+ ct_rc_id INTEGER,
+ ct_log_id INTEGER,
+ ct_rev_id INTEGER,
+ ct_tag VARCHAR(255) NOT NULL,
+ ct_params CLOB(64K) INLINE LENGTH 4096
+);
+CREATE UNIQUE INDEX change_tag_rc_tag
+ ON change_tag (ct_rc_id, ct_tag);
+CREATE UNIQUE INDEX change_tag_log_tag
+ ON change_tag (ct_log_id, ct_tag);
+CREATE UNIQUE INDEX change_tag_rev_tag
+ ON change_tag (ct_rev_id, ct_tag);
-- Covering index, so we can pull all the info only out of the index.
-CREATE INDEX change_tag_tag_id ON change_tag (ct_tag,ct_rc_id,ct_rev_id,ct_log_id);
+CREATE INDEX change_tag_tag_id
+ ON change_tag (ct_tag, ct_rc_id, ct_rev_id, ct_log_id);
+
-- Rollup table to pull a LIST of tags simply
CREATE TABLE tag_summary (
- ts_rc_id INTEGER,
+ ts_rc_id INTEGER,
ts_log_id INTEGER,
ts_rev_id INTEGER,
- ts_tags CLOB(64K) INLINE LENGTH 4096 NOT NULL
+ ts_tags CLOB(64K) INLINE LENGTH 4096 NOT NULL
);
-CREATE UNIQUE INDEX tag_summary_rc_id ON tag_summary (ts_rc_id);
-CREATE UNIQUE INDEX tag_summary_log_id ON tag_summary (ts_log_id);
-CREATE UNIQUE INDEX tag_summary_rev_id ON tag_summary (ts_rev_id);
+CREATE UNIQUE INDEX tag_summary_rc_id
+ ON tag_summary (ts_rc_id);
+CREATE UNIQUE INDEX tag_summary_log_id
+ ON tag_summary (ts_log_id);
+CREATE UNIQUE INDEX tag_summary_rev_id
+ ON tag_summary (ts_rev_id);
+
CREATE TABLE valid_tag (
- vt_tag varchar(255) NOT NULL PRIMARY KEY
+ vt_tag VARCHAR(255) NOT NULL
+ PRIMARY KEY
);
+
+
--
-- User preferences and perhaps other fun stuff. :)
-- Replaces the old user.user_options blob, with a couple nice properties:
--
--- 1) We only store non-default settings, so changes to the defaults
+-- 1) We only store non-default settings, so changes to the DEFAULTs
-- are now reflected for everybody, not just new accounts.
-- 2) We can more easily do bulk lookups, statistics, or modifications of
-- saved options since it's a sane table structure.
--
CREATE TABLE user_properties (
-- Foreign key to user.user_id
- up_user BIGINT NOT NULL,
-
+ up_user BIGINT NOT NULL,
-- Name of the option being saved. This is indexed for bulk lookup.
- up_property VARCHAR(32) FOR BIT DATA NOT NULL,
-
+ up_property VARCHAR(255) FOR BIT DATA NOT NULL,
-- Property value as a string.
- up_value CLOB(64K) INLINE LENGTH 4096
+ up_value CLOB(64K) INLINE LENGTH 4096
);
-CREATE UNIQUE INDEX user_properties_user_property ON user_properties (up_user,up_property);
-CREATE INDEX user_properties_property ON user_properties (up_property);
+CREATE UNIQUE INDEX user_properties_user_property
+ ON user_properties (up_user, up_property);
+CREATE INDEX user_properties_property
+ ON user_properties (up_property);
CREATE TABLE log_search (
-- The type of ID (rev ID, log ID, rev TIMESTAMP(3), username)
- ls_field VARCHAR(32) FOR BIT DATA NOT NULL,
+ ls_field VARCHAR(32) FOR BIT DATA NOT NULL,
-- The value of the ID
- ls_value varchar(255) NOT NULL,
+ ls_value VARCHAR(255) NOT NULL,
-- Key to log_id
- ls_log_id BIGINT NOT NULL default 0
+ ls_log_id BIGINT NOT NULL DEFAULT 0
);
-CREATE UNIQUE INDEX ls_field_val ON log_search (ls_field,ls_value,ls_log_id);
-CREATE INDEX ls_log_id ON log_search (ls_log_id);
+CREATE UNIQUE INDEX ls_field_val
+ ON log_search (ls_field, ls_value, ls_log_id);
+CREATE INDEX ls_log_id
+ ON log_search (ls_log_id);
+
+
-- Table for storing localisation data
CREATE TABLE l10n_cache (
-- Language code
- lc_lang VARCHAR(32) NOT NULL,
+ lc_lang VARCHAR(32) NOT NULL,
-- Cache key
- lc_key VARCHAR(255) NOT NULL,
+ lc_key VARCHAR(255) NOT NULL,
-- Value
- lc_value CLOB(16M) INLINE LENGTH 4096 NOT NULL
+ lc_value CLOB(16M) INLINE LENGTH 4096 NOT NULL
);
-CREATE INDEX lc_lang_key ON l10n_cache (lc_lang, lc_key);
+CREATE INDEX lc_lang_key
+ ON l10n_cache (lc_lang, lc_key);
-CREATE TABLE "MSG_RESOURCE_LINKS"
-(
-"MRL_RESOURCE" VARCHAR(255) FOR BIT DATA NOT NULL ,
-"MRL_MESSAGE" VARCHAR(255) FOR BIT DATA NOT NULL
-)
-;
-CREATE UNIQUE INDEX "UQ61_MSG_RESOURCE_LINKS" ON "MSG_RESOURCE_LINKS"
+CREATE TABLE msg_resource_links
(
-"MRL_MESSAGE",
-"MRL_RESOURCE"
-)
-ALLOW REVERSE SCANS
-;
+ mrl_resource VARCHAR(255) FOR BIT DATA NOT NULL,
+ mrl_message VARCHAR(255) FOR BIT DATA NOT NULL
+);
+CREATE UNIQUE INDEX uq61_msg_resource_links
+ ON msg_resource_links (mrl_message, mrl_resource);
+-- All DB2 indexes DEFAULT to allowing reverse scans
-CREATE TABLE "MSG_RESOURCE"
-(
-"MR_RESOURCE" VARCHAR(255) FOR BIT DATA NOT NULL ,
-"MR_LANG" VARCHAR(32) FOR BIT DATA NOT NULL ,
-"MR_BLOB" BLOB NOT NULL ,
-"MR_TIMESTAMP" TIMESTAMP(3) NOT NULL
-)
-;
-CREATE UNIQUE INDEX "UQ81_MSG_RESOURCE" ON "MSG_RESOURCE"
+
+CREATE TABLE msg_resource
(
-"MR_RESOURCE"
-,"MR_LANG"
-)
-ALLOW REVERSE SCANS
-;
+ mr_resource VARCHAR(255) FOR BIT DATA NOT NULL,
+ mr_lang VARCHAR(32) FOR BIT DATA NOT NULL,
+ mr_blob CLOB(64K) INLINE LENGTH 4096 NOT NULL,
+ mr_timestamp TIMESTAMP(3) NOT NULL
+);
+CREATE UNIQUE INDEX uq81_msg_resource
+ ON msg_resource (mr_resource, mr_lang);
+-- All DB2 indexes DEFAULT to allowing reverse scans
+
+
+
+CREATE TABLE module_deps (
+ md_module VARCHAR(255) FOR BIT DATA NOT NULL,
+ md_skin VARCHAR(32) FOR BIT DATA NOT NULL,
+ md_deps CLOB(16M) INLINE LENGTH 4096 NOT NULL
+);
+CREATE UNIQUE INDEX uq96_module_deps
+ ON module_deps (md_module, md_skin);
+-- All DB2 indexes DEFAULT to allowing reverse scans
-CREATE TABLE "MODULE_DEPS" (
-"MD_MODULE" VARCHAR(255) FOR BIT DATA NOT NULL ,
-"MD_SKIN" VARCHAR(32) FOR BIT DATA NOT NULL ,
-"MD_DEPS" CLOB(16M) INLINE LENGTH 4096 NOT NULL
-)
-;
-CREATE UNIQUE INDEX "UQ96_MODULE_DEPS" ON "MODULE_DEPS"
-(
-"MD_MODULE"
-,"MD_SKIN"
-)
-ALLOW REVERSE SCANS
-;
-CREATE TABLE "IWLINKS"
+CREATE TABLE iwlinks
(
-"IWL_FROM" INT NOT NULL ,
-"IWL_PREFIX" VARCHAR(20) FOR BIT DATA NOT NULL ,
-"IWL_TITLE" VARCHAR(255) FOR BIT DATA NOT NULL
-)
-;
+ iwl_from INTEGER NOT NULL,
+ iwl_prefix VARCHAR(20) FOR BIT DATA NOT NULL,
+ iwl_title VARCHAR(255) FOR BIT DATA NOT NULL
+);
+
+
+
+--
+-- Store information about newly uploaded files before they're
+-- moved into the actual filestore
+--
+CREATE TABLE uploadstash (
+ us_id BIGINT NOT NULL
+ PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (START WITH 1),
+ -- the user who uploaded the file.
+ us_user BIGINT NOT NULL,
+ -- file key. this is how applications actually search for the file.
+ -- this might go away, or become the primary key.
+ us_key VARCHAR(255) NOT NULL,
+ -- the original path
+ us_orig_path VARCHAR(255) NOT NULL,
+ -- the temporary path at which the file is actually stored
+ us_path VARCHAR(255) NOT NULL,
+ -- which type of upload the file came from (sometimes)
+ us_source_type VARCHAR(50),
+ -- the date/time on which the file was added
+ us_timestamp TIMESTAMP(3) NOT NULL,
+ us_status VARCHAR(50) NOT NULL,
+ -- file properties from File::getPropsFromPath. these may prove unnecessary.
+ --
+ us_size BIGINT NOT NULL,
+ -- this hash comes from File::sha1Base36(), and is 31 characters
+ us_sha1 VARCHAR(31) NOT NULL,
+ us_mime VARCHAR(255),
+ -- Media type as defined by the MEDIATYPE_xxx constants, should duplicate definition in the image table
+ us_media_type VARCHAR(30)
+ CONSTRAINT my_constraint
+ CHECK (
+ us_media_type in (
+ 'UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA',
+ 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'
+ )
+ ) DEFAULT NULL,
+ -- image-specific properties
+ us_image_width BIGINT,
+ us_image_height BIGINT,
+ us_image_bits INTEGER
+);
+-- sometimes there's a delete for all of a user's stuff.
+CREATE INDEX us_user
+ ON uploadstash (us_user);
+-- pick out files by key, enforce key UNIQUEness
+CREATE UNIQUE INDEX us_key
+ ON uploadstash (us_key);
+-- the abandoned upload cleanup script needs this
+CREATE INDEX us_timestamp
+ ON uploadstash (us_timestamp);
+
+
+
+-- Stores the groups the user has once belonged to.
+-- The user may still belong these groups. Check user_groups.
+CREATE TABLE user_former_groups (
+ ufg_user BIGINT NOT NULL DEFAULT 0,
+ ufg_group VARCHAR(16) FOR BIT DATA NOT NULL
+);
+CREATE UNIQUE INDEX ufg_user_group
+ ON user_former_groups (ufg_user, ufg_group);
+
+
+
+-- Table for holding configuration changes
+CREATE TABLE config (
+ cf_name VARCHAR(255) NOT NULL
+ PRIMARY KEY,
+ cf_value CLOB(64K) INLINE LENGTH 4096 NOT NULL
+);
+
diff --git a/maintenance/importDump.php b/maintenance/importDump.php
index 099b7895..2ad0872f 100644
--- a/maintenance/importDump.php
+++ b/maintenance/importDump.php
@@ -57,12 +57,13 @@ TEXT;
$this->stderr = fopen( "php://stderr", "wt" );
$this->addOption( 'report',
'Report position and speed after every n pages processed', false, true );
- $this->addOption( 'namespaces',
+ $this->addOption( 'namespaces',
'Import only the pages from namespaces belonging to the list of ' .
'pipe-separated namespace names or namespace indexes', false, true );
$this->addOption( 'dry-run', 'Parse dump without actually importing pages' );
$this->addOption( 'debug', 'Output extra verbose debug information' );
$this->addOption( 'uploads', 'Process file upload data if included (experimental)' );
+ $this->addOption( 'no-updates', 'Disable link table updates. Is faster but leaves the wiki in an inconsistent state' );
$this->addOption( 'image-base-path', 'Import files from a specified path', false, true );
$this->addArg( 'file', 'Dump file to import [else use stdin]', false );
}
@@ -73,6 +74,10 @@ TEXT;
}
$this->reportingInterval = intval( $this->getOption( 'report', 100 ) );
+ if ( !$this->reportingInterval ) {
+ $this->reportingInterval = 100; // avoid division by zero
+ }
+
$this->dryRun = $this->hasOption( 'dry-run' );
$this->uploads = $this->hasOption( 'uploads' ); // experimental!
if ( $this->hasOption( 'image-base-path' ) ) {
@@ -112,6 +117,10 @@ TEXT;
$this->error( "Unknown namespace text / index specified: $namespace", true );
}
+ /**
+ * @param $obj Title|Revision
+ * @return bool
+ */
private function skippedNamespace( $obj ) {
if ( $obj instanceof Title ) {
$ns = $obj->getNamespace();
@@ -130,6 +139,10 @@ TEXT;
$this->pageCount++;
}
+ /**
+ * @param $rev Revision
+ * @return mixed
+ */
function handleRevision( $rev ) {
$title = $rev->getTitle();
if ( !$title ) {
@@ -149,6 +162,10 @@ TEXT;
}
}
+ /**
+ * @param $revision Revision
+ * @return bool
+ */
function handleUpload( $revision ) {
if ( $this->uploads ) {
if ( $this->skippedNamespace( $revision ) ) {
@@ -186,7 +203,7 @@ TEXT;
}
function showReport() {
- if ( $this->mQuiet ) {
+ if ( !$this->mQuiet ) {
$delta = wfTime() - $this->startTime;
if ( $delta ) {
$rate = sprintf( "%.2f", $this->pageCount / $delta );
@@ -204,7 +221,7 @@ TEXT;
}
wfWaitForSlaves();
// XXX: Don't let deferred jobs array get absurdly large (bug 24375)
- wfDoUpdates( 'commit' );
+ DeferredUpdates::doUpdates( 'commit' );
}
function progress( $string ) {
@@ -214,11 +231,9 @@ TEXT;
function importFromFile( $filename ) {
if ( preg_match( '/\.gz$/', $filename ) ) {
$filename = 'compress.zlib://' . $filename;
- }
- elseif ( preg_match( '/\.bz2$/', $filename ) ) {
+ } elseif ( preg_match( '/\.bz2$/', $filename ) ) {
$filename = 'compress.bzip2://' . $filename;
- }
- elseif ( preg_match( '/\.7z$/', $filename ) ) {
+ } elseif ( preg_match( '/\.7z$/', $filename ) ) {
$filename = 'mediawiki.compress.7z://' . $filename;
}
@@ -243,6 +258,9 @@ TEXT;
if( $this->hasOption( 'debug' ) ) {
$importer->setDebug( true );
}
+ if ( $this->hasOption( 'no-updates' ) ) {
+ $importer->setNoUpdates( true );
+ }
$importer->setPageCallback( array( &$this, 'reportPage' ) );
$this->importCallback = $importer->setRevisionCallback(
array( &$this, 'handleRevision' ) );
diff --git a/maintenance/importImages.php b/maintenance/importImages.php
index f3b10ea9..bd077ff9 100644
--- a/maintenance/importImages.php
+++ b/maintenance/importImages.php
@@ -40,255 +40,265 @@ $processed = $added = $ignored = $skipped = $overwritten = $failed = 0;
echo( "Import Images\n\n" );
# Need a path
-if ( count( $args ) > 0 ) {
-
- $dir = $args[0];
-
- # Check Protection
- if ( isset( $options['protect'] ) && isset( $options['unprotect'] ) )
- die( "Cannot specify both protect and unprotect. Only 1 is allowed.\n" );
-
- if ( isset( $options['protect'] ) && $options['protect'] == 1 )
- die( "You must specify a protection option.\n" );
-
- # Prepare the list of allowed extensions
- global $wgFileExtensions;
- $extensions = isset( $options['extensions'] )
- ? explode( ',', strtolower( $options['extensions'] ) )
- : $wgFileExtensions;
-
- # Search the path provided for candidates for import
- $files = findFiles( $dir, $extensions );
-
- # Initialise the user for this operation
- $user = isset( $options['user'] )
- ? User::newFromName( $options['user'] )
- : User::newFromName( 'Maintenance script' );
- if ( !$user instanceof User )
- $user = User::newFromName( 'Maintenance script' );
- $wgUser = $user;
-
- # Get block check. If a value is given, this specified how often the check is performed
- if ( isset( $options['check-userblock'] ) ) {
- if ( !$options['check-userblock'] ) $checkUserBlock = 1;
- else $checkUserBlock = (int)$options['check-userblock'];
+if ( count( $args ) == 0 ) {
+ showUsage();
+}
+
+$dir = $args[0];
+
+# Check Protection
+if ( isset( $options['protect'] ) && isset( $options['unprotect'] ) ) {
+ die( "Cannot specify both protect and unprotect. Only 1 is allowed.\n" );
+}
+
+if ( isset( $options['protect'] ) && $options['protect'] == 1 ) {
+ die( "You must specify a protection option.\n" );
+}
+
+# Prepare the list of allowed extensions
+global $wgFileExtensions;
+$extensions = isset( $options['extensions'] )
+ ? explode( ',', strtolower( $options['extensions'] ) )
+ : $wgFileExtensions;
+
+# Search the path provided for candidates for import
+$files = findFiles( $dir, $extensions );
+
+# Initialise the user for this operation
+$user = isset( $options['user'] )
+ ? User::newFromName( $options['user'] )
+ : User::newFromName( 'Maintenance script' );
+if ( !$user instanceof User ) {
+ $user = User::newFromName( 'Maintenance script' );
+}
+$wgUser = $user;
+
+# Get block check. If a value is given, this specified how often the check is performed
+if ( isset( $options['check-userblock'] ) ) {
+ if ( !$options['check-userblock'] ) {
+ $checkUserBlock = 1;
} else {
- $checkUserBlock = false;
+ $checkUserBlock = (int)$options['check-userblock'];
}
+} else {
+ $checkUserBlock = false;
+}
- # Get --from
- $from = @$options['from'];
+# Get --from
+$from = @$options['from'];
- # Get sleep time.
- $sleep = @$options['sleep'];
- if ( $sleep ) $sleep = (int)$sleep;
+# Get sleep time.
+$sleep = @$options['sleep'];
+if ( $sleep ) {
+ $sleep = (int)$sleep;
+}
- # Get limit number
- $limit = @$options['limit'];
- if ( $limit ) $limit = (int)$limit;
+# Get limit number
+$limit = @$options['limit'];
+if ( $limit ) {
+ $limit = (int)$limit;
+}
- # Get the upload comment. Provide a default one in case there's no comment given.
- $comment = 'Importing image file';
+# Get the upload comment. Provide a default one in case there's no comment given.
+$comment = 'Importing image file';
- if ( isset( $options['comment-file'] ) ) {
- $comment = file_get_contents( $options['comment-file'] );
- if ( $comment === false || $comment === NULL ) {
- die( "failed to read comment file: {$options['comment-file']}\n" );
- }
- }
- elseif ( isset( $options['comment'] ) ) {
- $comment = $options['comment'];
+if ( isset( $options['comment-file'] ) ) {
+ $comment = file_get_contents( $options['comment-file'] );
+ if ( $comment === false || $comment === null ) {
+ die( "failed to read comment file: {$options['comment-file']}\n" );
}
+} elseif ( isset( $options['comment'] ) ) {
+ $comment = $options['comment'];
+}
+
+$commentExt = isset( $options['comment-ext'] ) ? $options['comment-ext'] : false;
- $commentExt = isset( $options['comment-ext'] ) ? $options['comment-ext'] : false;
+# Get the license specifier
+$license = isset( $options['license'] ) ? $options['license'] : '';
- # Get the license specifier
- $license = isset( $options['license'] ) ? $options['license'] : '';
+# Batch "upload" operation
+$count = count( $files );
+if ( $count > 0 ) {
- # Batch "upload" operation
- if ( ( $count = count( $files ) ) > 0 ) {
+ foreach ( $files as $file ) {
+ $base = wfBaseName( $file );
- foreach ( $files as $file ) {
- $base = wfBaseName( $file );
+ # Validate a title
+ $title = Title::makeTitleSafe( NS_FILE, $base );
+ if ( !is_object( $title ) ) {
+ echo( "{$base} could not be imported; a valid title cannot be produced\n" );
+ continue;
+ }
- # Validate a title
- $title = Title::makeTitleSafe( NS_FILE, $base );
- if ( !is_object( $title ) ) {
- echo( "{$base} could not be imported; a valid title cannot be produced\n" );
+ if ( $from ) {
+ if ( $from == $title->getDBkey() ) {
+ $from = null;
+ } else {
+ $ignored++;
continue;
}
+ }
- if ( $from ) {
- if ( $from == $title->getDBkey() ) {
- $from = NULL;
- } else {
- $ignored++;
- continue;
- }
+ if ( $checkUserBlock && ( ( $processed % $checkUserBlock ) == 0 ) ) {
+ $user->clearInstanceCache( 'name' ); // reload from DB!
+ if ( $user->isBlocked() ) {
+ echo( $user->getName() . " was blocked! Aborting.\n" );
+ break;
}
+ }
- if ( $checkUserBlock && ( ( $processed % $checkUserBlock ) == 0 ) ) {
- $user->clearInstanceCache( 'name' ); // reload from DB!
- if ( $user->isBlocked() ) {
- echo( $user->getName() . " was blocked! Aborting.\n" );
- break;
- }
+ # Check existence
+ $image = wfLocalFile( $title );
+ if ( $image->exists() ) {
+ if ( isset( $options['overwrite'] ) ) {
+ echo( "{$base} exists, overwriting..." );
+ $svar = 'overwritten';
+ } else {
+ echo( "{$base} exists, skipping\n" );
+ $skipped++;
+ continue;
}
+ } else {
+ if ( isset( $options['skip-dupes'] ) ) {
+ $repo = $image->getRepo();
+ $sha1 = File::sha1Base36( $file ); # XXX: we end up calculating this again when actually uploading. that sucks.
- # Check existence
- $image = wfLocalFile( $title );
- if ( $image->exists() ) {
- if ( isset( $options['overwrite'] ) ) {
- echo( "{$base} exists, overwriting..." );
- $svar = 'overwritten';
- } else {
- echo( "{$base} exists, skipping\n" );
+ $dupes = $repo->findBySha1( $sha1 );
+
+ if ( $dupes ) {
+ echo( "{$base} already exists as " . $dupes[0]->getName() . ", skipping\n" );
$skipped++;
continue;
}
- } else {
- if ( isset( $options['skip-dupes'] ) ) {
- $repo = $image->getRepo();
- $sha1 = File::sha1Base36( $file ); # XXX: we end up calculating this again when actually uploading. that sucks.
+ }
- $dupes = $repo->findBySha1( $sha1 );
+ echo( "Importing {$base}..." );
+ $svar = 'added';
+ }
- if ( $dupes ) {
- echo( "{$base} already exists as " . $dupes[0]->getName() . ", skipping\n" );
- $skipped++;
- continue;
- }
+ if ( isset( $options['source-wiki-url'] ) ) {
+ /* find comment text directly from source wiki, through MW's API */
+ $real_comment = getFileCommentFromSourceWiki( $options['source-wiki-url'], $base );
+ if ( $real_comment === false )
+ $commentText = $comment;
+ else
+ $commentText = $real_comment;
+
+ /* find user directly from source wiki, through MW's API */
+ $real_user = getFileUserFromSourceWiki( $options['source-wiki-url'], $base );
+ if ( $real_user === false ) {
+ $wgUser = $user;
+ } else {
+ $wgUser = User::newFromName( $real_user );
+ if ( $wgUser === false ) {
+ # user does not exist in target wiki
+ echo ( "failed: user '$real_user' does not exist in target wiki." );
+ continue;
}
-
- echo( "Importing {$base}..." );
- $svar = 'added';
}
-
- if ( isset( $options['source-wiki-url'] ) ) {
- /* find comment text directly from source wiki, through MW's API */
- $real_comment = getFileCommentFromSourceWiki( $options['source-wiki-url'], $base );
- if ( $real_comment === false )
- $commentText = $comment;
- else
- $commentText = $real_comment;
-
- /* find user directly from source wiki, through MW's API */
- $real_user = getFileUserFromSourceWiki( $options['source-wiki-url'], $base );
- if ( $real_user === false ) {
- $wgUser = $user;
+ } else {
+ # Find comment text
+ $commentText = false;
+
+ if ( $commentExt ) {
+ $f = findAuxFile( $file, $commentExt );
+ if ( !$f ) {
+ echo( " No comment file with extension {$commentExt} found for {$file}, using default comment. " );
} else {
- $wgUser = User::newFromName( $real_user );
- if ( $wgUser === false ) {
- # user does not exist in target wiki
- echo ( "failed: user '$real_user' does not exist in target wiki." );
- continue;
+ $commentText = file_get_contents( $f );
+ if ( !$commentText ) {
+ echo( " Failed to load comment file {$f}, using default comment. " );
}
}
- } else {
- # Find comment text
- $commentText = false;
-
- if ( $commentExt ) {
- $f = findAuxFile( $file, $commentExt );
- if ( !$f ) {
- echo( " No comment file with extension {$commentExt} found for {$file}, using default comment. " );
- } else {
- $commentText = file_get_contents( $f );
- if ( !$f ) {
- echo( " Failed to load comment file {$f}, using default comment. " );
- }
- }
- }
-
- if ( !$commentText ) {
- $commentText = $comment;
- }
}
+ if ( !$commentText ) {
+ $commentText = $comment;
+ }
+ }
- # Import the file
- if ( isset( $options['dry'] ) ) {
- echo( " publishing {$file} by '" . $wgUser->getName() . "', comment '$commentText'... " );
- } else {
- $archive = $image->publish( $file );
- if ( !$archive->isGood() ) {
- echo( "failed. (" .
- $archive->getWikiText() .
- ")\n" );
- $failed++;
- continue;
- }
+ # Import the file
+ if ( isset( $options['dry'] ) ) {
+ echo( " publishing {$file} by '" . $wgUser->getName() . "', comment '$commentText'... " );
+ } else {
+ $archive = $image->publish( $file );
+ if ( !$archive->isGood() ) {
+ echo( "failed. (" .
+ $archive->getWikiText() .
+ ")\n" );
+ $failed++;
+ continue;
}
+ }
+
+ if ( isset( $options['dry'] ) ) {
+ echo( "done.\n" );
+ } elseif ( $image->recordUpload( $archive->value, $commentText, $license ) ) {
+ # We're done!
+ echo( "done.\n" );
$doProtect = false;
- $restrictions = array();
global $wgRestrictionLevels;
$protectLevel = isset( $options['protect'] ) ? $options['protect'] : null;
if ( $protectLevel && in_array( $protectLevel, $wgRestrictionLevels ) ) {
- $restrictions['move'] = $protectLevel;
- $restrictions['edit'] = $protectLevel;
- $doProtect = true;
+ $doProtect = true;
}
if ( isset( $options['unprotect'] ) ) {
- $restrictions['move'] = '';
- $restrictions['edit'] = '';
- $doProtect = true;
+ $protectLevel = '';
+ $doProtect = true;
}
+ if ( $doProtect ) {
+ # Protect the file
+ echo "\nWaiting for slaves...\n";
+ // Wait for slaves.
+ sleep( 2.0 ); # Why this sleep?
+ wfWaitForSlaves();
- if ( isset( $options['dry'] ) ) {
- echo( "done.\n" );
- } elseif ( $image->recordUpload( $archive->value, $commentText, $license ) ) {
- # We're done!
- echo( "done.\n" );
- if ( $doProtect ) {
- # Protect the file
- $article = new Article( $title );
- echo "\nWaiting for slaves...\n";
- // Wait for slaves.
- sleep( 2.0 ); # Why this sleep?
- wfWaitForSlaves();
-
- echo( "\nSetting image restrictions ... " );
- if ( $article->updateRestrictions( $restrictions ) )
- echo( "done.\n" );
- else
- echo( "failed.\n" );
- }
+ echo( "\nSetting image restrictions ... " );
- } else {
- echo( "failed. (at recordUpload stage)\n" );
- $svar = 'failed';
+ $cascade = false;
+ $restrictions = array();
+ foreach( $title->getRestrictionTypes() as $type ) {
+ $restrictions[$type] = $protectLevel;
+ }
+
+ $page = WikiPage::factory( $title );
+ $status = $page->doUpdateRestrictions( $restrictions, array(), $cascade, '', $user );
+ echo( ( $status->isOK() ? 'done' : 'failed' ) . "\n" );
}
- $$svar++;
- $processed++;
+ } else {
+ echo( "failed. (at recordUpload stage)\n" );
+ $svar = 'failed';
+ }
- if ( $limit && $processed >= $limit )
- break;
+ $$svar++;
+ $processed++;
- if ( $sleep )
- sleep( $sleep );
+ if ( $limit && $processed >= $limit ) {
+ break;
}
- # Print out some statistics
- echo( "\n" );
- foreach ( array( 'count' => 'Found', 'limit' => 'Limit', 'ignored' => 'Ignored',
- 'added' => 'Added', 'skipped' => 'Skipped', 'overwritten' => 'Overwritten',
- 'failed' => 'Failed' ) as $var => $desc ) {
- if ( $$var > 0 )
- echo( "{$desc}: {$$var}\n" );
+ if ( $sleep ) {
+ sleep( $sleep );
}
+ }
- } else {
- echo( "No suitable files could be found for import.\n" );
+ # Print out some statistics
+ echo( "\n" );
+ foreach ( array( 'count' => 'Found', 'limit' => 'Limit', 'ignored' => 'Ignored',
+ 'added' => 'Added', 'skipped' => 'Skipped', 'overwritten' => 'Overwritten',
+ 'failed' => 'Failed' ) as $var => $desc ) {
+ if ( $$var > 0 )
+ echo( "{$desc}: {$$var}\n" );
}
} else {
- showUsage();
+ echo( "No suitable files could be found for import.\n" );
}
exit( 0 );
diff --git a/maintenance/importSiteScripts.php b/maintenance/importSiteScripts.php
index 849c7b1b..0dc200ec 100644
--- a/maintenance/importSiteScripts.php
+++ b/maintenance/importSiteScripts.php
@@ -1,8 +1,11 @@
<?php
/**
- * Maintenance script to import all scripts in the MediaWiki namespace from a
+ * Maintenance script to import all scripts in the MediaWiki namespace from a
* local site.
+ * @file
+ * @ingroup Maintenance
*/
+
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
class ImportSiteScripts extends Maintenance {
@@ -16,22 +19,29 @@ class ImportSiteScripts extends Maintenance {
public function execute() {
global $wgUser;
- $wgUser = User::newFromName( $this->getOption( 'username', 'ScriptImporter' ) );
+
+ $user = User::newFromName( $this->getOption( 'username', 'ScriptImporter' ) );
+ $wgUser = $user;
$baseUrl = $this->getArg( 1 );
$pageList = $this->fetchScriptList();
$this->output( 'Importing ' . count( $pageList ) . " pages\n" );
foreach ( $pageList as $page ) {
+ $title = Title::makeTitleSafe( NS_MEDIAWIKI, $page );
+ if ( !$title ) {
+ $this->error( "$page is an invalid title; it will not be imported\n" );
+ continue;
+ }
+
$this->output( "Importing $page\n" );
$url = wfAppendQuery( $baseUrl, array(
'action' => 'raw',
'title' => "MediaWiki:{$page}" ) );
$text = Http::get( $url );
-
- $title = Title::makeTitleSafe( NS_MEDIAWIKI, $page );
- $article = new Article( $title );
- $article->doEdit( $text, "Importing from $url", 0 );
+
+ $wikiPage = WikiPage::factory( $title );
+ $wikiPage->doEdit( $text, "Importing from $url", 0, false, $user );
}
}
diff --git a/maintenance/importTextFile.php b/maintenance/importTextFile.php
index b78ae039..ec9ff001 100644
--- a/maintenance/importTextFile.php
+++ b/maintenance/importTextFile.php
@@ -57,8 +57,8 @@ if ( count( $args ) < 1 || isset( $options['help'] ) ) {
$flags = 0 | ( isset( $options['norc'] ) ? EDIT_SUPPRESS_RC : 0 );
echo( "\nPerforming edit..." );
- $article = new Article( $title );
- $article->doEdit( $text, $comment, $flags );
+ $page = WikiPage::factory( $title );
+ $page->doEdit( $text, $comment, $flags, false, $user );
echo( "done.\n" );
} else {
diff --git a/maintenance/importUseModWiki.php b/maintenance/importUseModWiki.php
deleted file mode 100644
index a28d57a5..00000000
--- a/maintenance/importUseModWiki.php
+++ /dev/null
@@ -1,375 +0,0 @@
-<?php
-/**
- * Import data from a UseModWiki into a MediaWiki wiki
- * 2003-02-09 Brion VIBBER <brion@pobox.com>
- * Based loosely on Magnus's code from 2001-2002
- *
- * Updated limited version to get something working temporarily
- * 2003-10-09
- * Be sure to run the link & index rebuilding scripts!
- *
- * Some more munging for charsets etc
- * 2003-11-28
- *
- * Partial fix for pages starting with lowercase letters (??)
- * and CamelCase and /Subpage link conversion
- * 2004-11-17
- *
- * Rewrite output to create Special:Export format for import
- * instead of raw SQL. Should be 'future-proof' against future
- * schema changes.
- * 2005-03-14
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @todo document
- * @file
- * @ingroup Maintenance
- */
-
-require_once( "Maintenance.php" );
-
-class ImportUseModWiki extends Maintenance {
-
- private $encoding, $rootDirectory = '';
-
- /**
- * Field separators
- * @var String
- */
- private $FS1, $FS2, $FS3 = '';
-
- /**
- * @var Array
- */
- private $usercache, $nowiki = array();
-
- public function __construct() {
- parent::__construct();
- $this->mDescription = "Import pages from UseMod wikis";
- $this->addOption( 'encoding', 'Encoding of the imported text, default CP1252', false, true );
- /**
- * If UseModWiki's New File System is used:
- * $NewFS = 1; # 1 = new multibyte $FS, 0 = old $FS
- * Use "\xb3"; for the Old File System
- * Changed with UTF-8 UseModWiki
- * http://www.usemod.com/cgi-bin/wiki.pl?SupportForUtf8
- * http://www.usemod.com/cgi-bin/wiki.pl?WikiBugs/NewFieldSeparatorWronglyTreated
- * http://www.meatballwiki.org/wiki/WikiEngine#Q_amp_A
- */
- $this->addOption( 'separator', 'Field separator to use, default \x1E\xFF\xFE\x1E', false, true );
- $this->addArg( 'path', 'Path to your UseMod wiki' );
- }
-
- public function execute() {
- $this->rootDirectory = $this->getArg();
- $this->encoding = $this->getOption( 'encoding', 'CP1252' );
- $sep = $this->getOption( 'separator', "\x1E\xFF\xFE\x1E" );
- $this->FS1 = "{$sep}1";
- $this->FS2 = "{$sep}2";
- $this->FS3 = "{$sep}3";
-
- echo <<<XML
-<?xml version="1.0" encoding="UTF-8" ?>
-<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.1/"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.1/
- http://www.mediawiki.org/xml/export-0.1.xsd"
- version="0.1"
- xml:lang="en">
-<!-- generated by importUseModWiki.php -->
-
-XML;
- $letters = array(
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
- 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
- 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'other' );
- foreach ( $letters as $letter ) {
- $dir = "{$this->rootDirectory}/page/$letter";
- if ( is_dir( $dir ) )
- $this->importPageDirectory( $dir );
- }
- echo <<<XML
-</mediawiki>
-
-XML;
- }
-
- private function importPageDirectory( $dir, $prefix = "" ) {
- echo "\n<!-- Checking page directory " . $this->xmlCommentSafe( $dir ) . " -->\n";
- $mydir = opendir( $dir );
- while ( $entry = readdir( $mydir ) ) {
- $m = array();
- if ( preg_match( '/^(.+)\.db$/', $entry, $m ) ) {
- echo $this->importPage( $prefix . $m[1] );
- } else {
- if ( is_dir( "$dir/$entry" ) ) {
- if ( $entry != '.' && $entry != '..' ) {
- $this->importPageDirectory( "$dir/$entry", "$entry/" );
- }
- } else {
- echo "<!-- File '" . $this->xmlCommentSafe( $entry ) . "' doesn't seem to contain an article. Skipping. -->\n";
- }
- }
- }
- }
-
- private function useModFilename( $title ) {
- $c = substr( $title, 0, 1 );
- if ( preg_match( '/[A-Z]/i', $c ) ) {
- return strtoupper( $c ) . "/$title";
- }
- return "other/$title";
- }
-
- private function fetchPage( $title ) {
- $fname = $this->rootDirectory . "/page/" . $this->useModFilename( $title ) . ".db";
- if ( !file_exists( $fname ) ) {
- echo "Couldn't open file '$fname' for page '$title'.\n";
- die( -1 );
- }
-
- $page = $this->splitHash( $this->FS1, file_get_contents( $fname ) );
- $section = $this->splitHash( $this->FS2, $page["text_default"] );
- $text = $this->splitHash( $this->FS3, $section["data"] );
-
- return $this->array2object( array( "text" => $text["text"] , "summary" => $text["summary"] ,
- "minor" => $text["minor"] , "ts" => $section["ts"] ,
- "username" => $section["username"] , "host" => $section["host"] ) );
- }
-
- private function fetchKeptPages( $title ) {
- $fname = $this->rootDirectory . "/keep/" . $this->useModFilename( $title ) . ".kp";
- if ( !file_exists( $fname ) ) return array();
-
- $keptlist = explode( $this->FS1, file_get_contents( $fname ) );
- array_shift( $keptlist ); # Drop the junk at beginning of file
-
- $revisions = array();
- foreach ( $keptlist as $rev ) {
- $section = $this->splitHash( $this->FS2, $rev );
- $text = $this->splitHash( $this->FS3, $section["data"] );
- if ( $text["text"] && $text["minor"] != "" && ( $section["ts"] * 1 > 0 ) ) {
- array_push( $revisions, $this->array2object( array ( "text" => $text["text"] , "summary" => $text["summary"] ,
- "minor" => $text["minor"] , "ts" => $section["ts"] ,
- "username" => $section["username"] , "host" => $section["host"] ) ) );
- } else {
- echo "<!-- skipped a bad old revision -->\n";
- }
- }
- return $revisions;
- }
-
- private function splitHash( $sep , $str ) {
- $temp = explode ( $sep , $str ) ;
- $ret = array () ;
- for ( $i = 0; $i + 1 < count ( $temp ) ; $i++ ) {
- $ret[$temp[$i]] = $temp[++$i] ;
- }
- return $ret ;
- }
-
- private function checkUserCache( $name, $host ) {
- if ( $name ) {
- if ( in_array( $name, $this->usercache ) ) {
- $userid = $this->usercache[$name];
- } else {
- # If we haven't imported user accounts
- $userid = 0;
- }
- $username = str_replace( '_', ' ', $name );
- } else {
- $userid = 0;
- $username = $host;
- }
- return array( $userid, $username );
- }
-
- private function importPage( $title ) {
- echo "\n<!-- Importing page " . $this->xmlCommentSafe( $title ) . " -->\n";
- $page = $this->fetchPage( $title );
-
- $newtitle = $this->xmlsafe( str_replace( '_', ' ', $this->recodeText( $title ) ) );
-
- $munged = $this->mungeFormat( $page->text );
- if ( $munged != $page->text ) {
- /**
- * Save a *new* revision with the conversion, and put the
- * previous last version into the history.
- */
- $next = $this->array2object( array(
- 'text' => $munged,
- 'minor' => 1,
- 'username' => 'Conversion script',
- 'host' => '127.0.0.1',
- 'ts' => time(),
- 'summary' => 'link fix',
- ) );
- $revisions = array( $page, $next );
- } else {
- /**
- * Current revision:
- */
- $revisions = array( $page );
- }
- $xml = <<<XML
- <page>
- <title>$newtitle</title>
-
-XML;
-
- # History
- $revisions = array_merge( $revisions, $this->fetchKeptPages( $title ) );
- if ( count( $revisions ) == 0 ) {
- return NULL; // Was "$sql", which does not appear to be defined.
- }
-
- foreach ( $revisions as $rev ) {
- $text = $this->xmlsafe( $this->recodeText( $rev->text ) );
- $minor = ( $rev->minor ? '<minor/>' : '' );
- list( /* $userid */ , $username ) = $this->checkUserCache( $rev->username, $rev->host );
- $username = $this->xmlsafe( $this->recodeText( $username ) );
- $timestamp = $this->xmlsafe( $this->timestamp2ISO8601( $rev->ts ) );
- $comment = $this->xmlsafe( $this->recodeText( $rev->summary ) );
-
- $xml .= <<<XML
- <revision>
- <timestamp>$timestamp</timestamp>
- <contributor><username>$username</username></contributor>
- $minor
- <comment>$comment</comment>
- <text>$text</text>
- </revision>
-
-XML;
- }
- $xml .= "</page>\n\n";
- return $xml;
- }
-
- private function recodeText( $string ) {
- # For currently latin-1 wikis
- $string = str_replace( "\r\n", "\n", $string );
- $string = @iconv( $this->encoding, "UTF-8", $string );
- $string = $this->mungeToUtf8( $string ); # Any old &#1234; stuff
- return $string;
- }
-
- /**
- * @todo FIXME: Don't use /e
- */
- private function mungeToUtf8( $string ) {
- $string = preg_replace ( '/&#([0-9]+);/e', 'wfUtf8Sequence($1)', $string );
- $string = preg_replace ( '/&#x([0-9a-f]+);/ie', 'wfUtf8Sequence(0x$1)', $string );
- # Should also do named entities here
- return $string;
- }
-
- private function timestamp2ISO8601( $ts ) {
- # 2003-08-05T18:30:02Z
- return gmdate( 'Y-m-d', $ts ) . 'T' . gmdate( 'H:i:s', $ts ) . 'Z';
- }
-
- /**
- * The page may contain old data which has not been properly normalized.
- * Invalid UTF-8 sequences or forbidden control characters will make our
- * XML output invalid, so be sure to strip them out.
- * @param String $string Text to clean up
- * @return String
- */
- private function xmlsafe( $string ) {
- $string = UtfNormal::cleanUp( $string );
- $string = htmlspecialchars( $string );
- return $string;
- }
-
- private function xmlCommentSafe( $text ) {
- return str_replace( '--', '\\-\\-', $this->xmlsafe( $this->recodeText( $text ) ) );
- }
-
- private function array2object( $arr ) {
- $o = (object)0;
- foreach ( $arr as $x => $y ) {
- $o->$x = $y;
- }
- return $o;
- }
-
- /**
- * Make CamelCase and /Talk links work
- */
- private function mungeFormat( $text ) {
- $this->nowiki = array();
- $staged = preg_replace_callback(
- '/(<nowiki>.*?<\\/nowiki>|(?:http|https|ftp):\\S+|\[\[[^]\\n]+]])/s',
- array( $this, 'nowikiPlaceholder' ), $text );
-
- # This is probably not 100% correct, I'm just
- # glancing at the UseModWiki code.
- $upper = "[A-Z]";
- $lower = "[a-z_0-9]";
- $any = "[A-Za-z_0-9]";
- $camel = "(?:$upper+$lower+$upper+$any*)";
- $subpage = "(?:\\/$any+)";
- $substart = "(?:\\/$upper$any*)";
-
- $munged = preg_replace( "/(?!\\[\\[)($camel$subpage*|$substart$subpage*)\\b(?!\\]\\]|>)/",
- '[[$1]]', $staged );
-
- $final = preg_replace( '/' . preg_quote( $this->placeholder() ) . '/s',
- array( $this, 'nowikiShift' ), $munged );
- return $final;
- }
-
- private function placeholder( $x = null ) {
- return '\xffplaceholder\xff';
- }
-
- public function nowikiPlaceholder( $matches ) {
- $this->nowiki[] = $matches[1];
- return $this->placeholder();
- }
-
- public function nowikiShift() {
- return array_shift( $this->nowiki );
- }
-}
-
-function wfUtf8Sequence( $codepoint ) {
- if ( $codepoint < 0x80 ) {
- return chr( $codepoint );
- }
- if ( $codepoint < 0x800 ) {
- return chr( $codepoint >> 6 & 0x3f | 0xc0 ) .
- chr( $codepoint & 0x3f | 0x80 );
- }
- if ( $codepoint < 0x10000 ) {
- return chr( $codepoint >> 12 & 0x0f | 0xe0 ) .
- chr( $codepoint >> 6 & 0x3f | 0x80 ) .
- chr( $codepoint & 0x3f | 0x80 );
- }
- if ( $codepoint < 0x100000 ) {
- return chr( $codepoint >> 18 & 0x07 | 0xf0 ) . # Double-check this
- chr( $codepoint >> 12 & 0x3f | 0x80 ) .
- chr( $codepoint >> 6 & 0x3f | 0x80 ) .
- chr( $codepoint & 0x3f | 0x80 );
- }
- # Doesn't yet handle outside the BMP
- return "&#$codepoint;";
-}
-
-$maintClass = 'ImportUseModWiki';
-require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/importUseModWikipedia.php b/maintenance/importUseModWikipedia.php
deleted file mode 100644
index c4b8112f..00000000
--- a/maintenance/importUseModWikipedia.php
+++ /dev/null
@@ -1,892 +0,0 @@
-<?php
-
-/**
- * A script to read a dump of the English Wikipedia from the UseModWiki period, and to
- * generate an XML dump in MediaWiki format.
- *
- * Some relevant code was ported from UseModWiki 0.92.
- *
- */
-
-require_once( dirname( __FILE__ ) . '/Maintenance.php' );
-require_once( dirname( __FILE__ ) .'/../includes/normal/UtfNormalUtil.php' );
-
-
-class ImportUseModWikipedia extends Maintenance {
- var $encodeMap, $decodeMap;
-
- var $deepRenames = array(
- 'JimboWales' => 983862286,
- 'TexaS' => 983918410,
- 'HistoryOfUnitedStatesTalk' => 984795423,
- 'MetallicA' => 985128533,
- 'PythagoreanTheorem' => 985225545,
- 'TheCanonofScripture' => 985368223,
- 'TaoTehChing' => 985368222,
- //'TheMostRemarkableFormulaInTheWorld' => 985368221,
- 'TheRecorder' => 985368220,
- 'GladstoneOregon' => 985368219,
- 'PacificBeach' => '?',
- 'AaRiver' => '?',
- );
-
- var $replacements = array();
-
- var $renameTextLinksOps = array(
- 983846265 => array(
- 'TestIgnore' => 'IgnoreTest',
- ),
- 983848080 => array(
- 'UnitedLocomotiveWorks' => 'Atlas Shrugged/United Locomotive Works'
- ),
- 983856376 => array(
- 'WikiPedia' => 'Wikipedia',
- ),
- 983896152 => array(
- 'John_F_Kennedy' => 'John_F._Kennedy',
- ),
- 983905871 => array(
- 'LarrySanger' => 'Larry_Sanger'
- ),
- 984697068 => array(
- 'UnitedStates' => 'United States',
- ),
- 984792748 => array(
- 'LibertarianisM' => 'Libertarianism'
- ),
- 985327832 => array(
- 'AnarchisM' => 'Anarchism',
- ),
- 985290063 => array(
- 'HistoryOfUnitedStatesDiscussion' => 'History_Of_United_States_Discussion'
- ),
- 985290091 => array(
- 'BritishEmpire' => 'British Empire'
- ),
- /*
- 985468958 => array(
- 'ScienceFiction' => 'Science fiction',
- ),*/
- );
-
- /**
- * Hack for observed substitution issues
- */
- var $skipSelfSubstitution = array(
- 'Pythagorean_Theorem',
- 'The_Most_Remarkable_Formula_In_The_World',
- 'Wine',
- );
-
- var $unixLineEndingsOps = array(
- 987743732 => 'Wikipedia_FAQ'
- );
-
- var $replacementsDone = array();
-
- var $moveLog = array();
- var $moveDests = array();
- var $revId;
-
- var $rc = array();
- var $textCache = array();
- var $blacklist = array();
-
- var $FS, $FS1, $FS2, $FS3;
- var $FreeLinkPattern, $UrlPattern, $LinkPattern, $InterLinkPattern;
-
- var $cp1252Table = array(
-0x80 => 0x20ac,
-0x81 => 0x0081,
-0x82 => 0x201a,
-0x83 => 0x0192,
-0x84 => 0x201e,
-0x85 => 0x2026,
-0x86 => 0x2020,
-0x87 => 0x2021,
-0x88 => 0x02c6,
-0x89 => 0x2030,
-0x8a => 0x0160,
-0x8b => 0x2039,
-0x8c => 0x0152,
-0x8d => 0x008d,
-0x8e => 0x017d,
-0x8f => 0x008f,
-0x90 => 0x0090,
-0x91 => 0x2018,
-0x92 => 0x2019,
-0x93 => 0x201c,
-0x94 => 0x201d,
-0x95 => 0x2022,
-0x96 => 0x2013,
-0x97 => 0x2014,
-0x98 => 0x02dc,
-0x99 => 0x2122,
-0x9a => 0x0161,
-0x9b => 0x203a,
-0x9c => 0x0153,
-0x9d => 0x009d,
-0x9e => 0x017e,
-0x9f => 0x0178);
-
- public function __construct() {
- parent::__construct();
- $this->addOption( 'datadir', 'the value of $DataDir from wiki.cgi', true, true );
- $this->addOption( 'outfile', 'the name of the output XML file', true, true );
- $this->initLinkPatterns();
-
- $this->encodeMap = $this->decodeMap = array();
-
- for ($source = 0; $source <= 0xff; $source++) {
- if ( isset( $this->cp1252Table[$source] ) ) {
- $dest = $this->cp1252Table[$source];
- } else {
- $dest = $source;
- }
- $sourceChar = chr( $source );
- $destChar = codepointToUtf8( $dest );
- $this->encodeMap[$sourceChar] = $destChar;
- $this->decodeMap[$destChar] = $sourceChar;
- }
- }
-
- function initLinkPatterns() {
- # Field separators are used in the URL-style patterns below.
- $this->FS = "\xb3"; # The FS character is a superscript "3"
- $this->FS1 = $this->FS . "1"; # The FS values are used to separate fields
- $this->FS2 = $this->FS . "2"; # in stored hashtables and other data structures.
- $this->FS3 = $this->FS . "3"; # The FS character is not allowed in user data.
-
- $UpperLetter = "[A-Z";
- $LowerLetter = "[a-z";
- $AnyLetter = "[A-Za-z";
- $AnyLetter .= "_0-9";
- $UpperLetter .= "]"; $LowerLetter .= "]"; $AnyLetter .= "]";
-
- # Main link pattern: lowercase between uppercase, then anything
- $LpA = $UpperLetter . "+" . $LowerLetter . "+" . $UpperLetter
- . $AnyLetter . "*";
- # Optional subpage link pattern: uppercase, lowercase, then anything
- $LpB = $UpperLetter . "+" . $LowerLetter . "+" . $AnyLetter . "*";
-
- # Loose pattern: If subpage is used, subpage may be simple name
- $this->LinkPattern = "((?:(?:$LpA)?\\/$LpB)|$LpA)";
- $QDelim = '(?:"")?'; # Optional quote delimiter (not in output)
- $this->LinkPattern .= $QDelim;
-
- # Inter-site convention: sites must start with uppercase letter
- # (Uppercase letter avoids confusion with URLs)
- $InterSitePattern = $UpperLetter . $AnyLetter . "+";
- $this->InterLinkPattern = "((?:$InterSitePattern:[^\\]\\s\"<>{$this->FS}]+)$QDelim)";
-
- $AnyLetter = "[-,. _0-9A-Za-z]";
- $this->FreeLinkPattern = "($AnyLetter+)";
- $this->FreeLinkPattern = "((?:(?:$AnyLetter+)?\\/)?$AnyLetter+)";
- $this->FreeLinkPattern .= $QDelim;
-
- # Url-style links are delimited by one of:
- # 1. Whitespace (kept in output)
- # 2. Left or right angle-bracket (< or >) (kept in output)
- # 3. Right square-bracket (]) (kept in output)
- # 4. A single double-quote (") (kept in output)
- # 5. A $FS (field separator) character (kept in output)
- # 6. A double double-quote ("") (removed from output)
-
- $UrlProtocols = "http|https|ftp|afs|news|nntp|mid|cid|mailto|wais|"
- . "prospero|telnet|gopher";
- $UrlProtocols .= '|file';
- $this->UrlPattern = "((?:(?:$UrlProtocols):[^\\]\\s\"<>{$this->FS}]+)$QDelim)";
- $ImageExtensions = "(gif|jpg|png|bmp|jpeg)";
- $RFCPattern = "RFC\\s?(\\d+)";
- $ISBNPattern = "ISBN:?([0-9- xX]{10,})";
- }
-
- function execute() {
- $this->articleFileName = '/tmp/importUseMod.' . mt_rand( 0, 0x7ffffff ) . '.tmp';
- $this->patchFileName = '/tmp/importUseMod.' . mt_rand( 0, 0x7ffffff ) . '.tmp';
- $this->dataDir = $this->getOption( 'datadir' );
- $this->outFile = fopen( $this->getOption( 'outfile' ), 'w' );
- if ( !$this->outFile ) {
- echo "Unable to open output file\n";
- return 1;
- }
- $this->writeXmlHeader();
- $this->readRclog();
- $this->writeMoveLog();
- $this->writeRevisions();
- $this->reconcileCurrentRevs();
- $this->writeXmlFooter();
- unlink( $this->articleFileName );
- unlink( $this->patchFileName );
- return 0;
- }
-
- function writeXmlHeader() {
- fwrite( $this->outFile, <<<EOT
-<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.3/ http://www.mediawiki.org/xml/export-0.3.xsd" version="0.3" xml:lang="en">
- <siteinfo>
- <sitename>Wikipedia</sitename>
- <base>http://www.wikipedia.com/</base>
- <generator>MediaWiki 1.18alpha importUseModWikipedia.php</generator>
- <case>case-sensitive</case>
- <namespaces>
- <namespace key="0" />
- </namespaces>
- </siteinfo>
-
-EOT
- );
- }
-
- function writeXmlFooter() {
- fwrite( $this->outFile, "</mediawiki>\n" );
- }
-
- function readRclog() {
- $rcFile = fopen( "{$this->dataDir}/rclog", 'r' );
- while ( $line = fgets( $rcFile ) ) {
- $bits = explode( $this->FS3, $line );
- if ( count( $bits ) !== 7 ) {
- echo "Error reading rclog\n";
- return;
- }
- $params = array(
- 'timestamp' => $bits[0],
- 'rctitle' => $bits[1],
- 'summary' => $bits[2],
- 'minor' => $bits[3],
- 'host' => $bits[4],
- 'kind' => $bits[5],
- 'extra' => array()
- );
- $extraList = explode( $this->FS2, $bits[6] );
-
- for ( $i = 0; $i < count( $extraList ); $i += 2 ) {
- $params['extra'][$extraList[$i]] = $extraList[$i + 1];
- }
- $this->rc[$params['timestamp']][] = $params;
- }
- }
-
- function writeMoveLog() {
- $this->moveLog = array();
- $deepRenames = $this->deepRenames;
- echo "Calculating move log...\n";
- $this->processDiffFile( array( $this, 'moveLogCallback' ) );
-
- // We have the timestamp intervals, now make a guess at the actual timestamp
- foreach ( $this->moveLog as $newTitle => $params ) {
- // Is there a time specified?
- $drTime = false;
- if ( isset( $deepRenames[$params['old']] ) ) {
- $drTime = $deepRenames[$params['old']];
- if ( $drTime !== '?' ) {
- if ( ( !isset( $params['endTime'] ) || $drTime < $params['endTime'] )
- && $drTime > $params['startTime'] )
- {
- $this->moveLog[$newTitle]['timestamp'] = $drTime;
- $this->moveLog[$newTitle]['deep'] = true;
-
- echo "{$params['old']} -> $newTitle at $drTime\n";
- unset( $deepRenames[$params['old']] );
- continue;
- } else {
- echo "WARNING: deep rename time invalid: {$params['old']}\n";
- unset( $deepRenames[$params['old']] );
- }
- }
- }
-
- // Guess that it is one second after the last edit to the page before it was moved
- $this->moveLog[$newTitle]['timestamp'] = $params['startTime'] + 1;
- if ( $drTime === '?' ) {
- $this->moveLog[$newTitle]['deep'] = true;
- unset( $deepRenames[$params['old']] );
- }
- if ( isset( $params['endTime'] ) ) {
- $this->printLatin1( "{$params['old']} -> $newTitle between " .
- "{$params['startTime']} and {$params['endTime']}\n" );
- } else {
- $this->printLatin1( "{$params['old']} -> $newTitle after " .
- "{$params['startTime']}\n" );
- }
- }
-
- // Write the move log to the XML file
- $id = 1;
- foreach ( $this->moveLog as $newTitle => $params ) {
- $out = "<logitem>\n" .
- $this->element( 'id', $id++ ) .
- $this->element( 'timestamp', wfTimestamp( TS_ISO_8601, $params['timestamp'] ) ) .
- "<contributor>\n" .
- $this->element( 'username', 'UseModWiki admin' ) .
- "</contributor>" .
- $this->element( 'type', 'move' ) .
- $this->element( 'action', 'move' ) .
- $this->element( 'logtitle', $params['old'] ) .
- "<params xml:space=\"preserve\">" .
- htmlspecialchars( $this->encode( "{$newTitle}\n1" ) ) .
- "</params>\n" .
- "</logitem>\n";
- fwrite( $this->outFile, $out );
- }
-
- // Check for remaining deep rename entries
- if ( $deepRenames ) {
- echo "WARNING: the following entries in \$this->deepRenames are " .
- "invalid, since no such move exists:\n" .
- implode( "\n", array_keys( $deepRenames ) ) .
- "\n\n";
- }
-
- }
-
- function element( $name, $value ) {
- return "<$name>" . htmlspecialchars( $this->encode( $value ) ) . "</$name>\n";
- }
-
- function moveLogCallback( $entry ) {
- $rctitle = $entry['rctitle'];
- $title = $entry['title'];
- $this->moveDests[$rctitle] = $title;
-
- if ( $rctitle === $title ) {
- if ( isset( $this->moveLog[$rctitle] )
- && !isset( $this->moveLog[$rctitle]['endTime'] ) )
- {
- // This is the latest time that the page could have been moved
- $this->moveLog[$rctitle]['endTime'] = $entry['timestamp'];
- }
- } else {
- if ( !isset( $this->moveLog[$rctitle] ) ) {
- // Initialise the move log entry
- $this->moveLog[$rctitle] = array(
- 'old' => $title
- );
- }
- // Update the earliest time the page could have been moved
- $this->moveLog[$rctitle]['startTime'] = $entry['timestamp'];
- }
- }
-
- function writeRevisions() {
- $this->numGoodRevs = 0;
- $this->revId = 1;
- $this->processDiffFile( array( $this, 'revisionCallback' ) );
- echo "\n\nImported {$this->numGoodRevs} out of {$this->numRevs}\n";
- }
-
- function revisionCallback( $params ) {
- $title = $params['rctitle'];
- $editTime = $params['timestamp'];
-
- if ( isset( $this->blacklist[$title] ) ) {
- return;
- }
- $this->doPendingOps( $editTime );
-
- $origText = $this->getText( $title );
- $text = $this->patch( $origText, $params['diff'] );
- if ( $text === false ) {
- echo "$editTime $title attempting resolution...\n";
- $linkSubstitutes = $this->resolveFailedDiff( $origText, $params['diff'] );
- if ( !$linkSubstitutes ) {
- $this->printLatin1( "$editTime $title DIFF FAILED\n" );
- $this->blacklist[$title] = true;
- return;
- }
- $this->printLatin1( "$editTime $title requires substitutions:\n" );
- $time = $editTime - 1;
- foreach ( $linkSubstitutes as $old => $new ) {
- $this->printLatin1( "SUBSTITUTE $old -> $new\n" );
- $this->renameTextLinks( $old, $new, $time-- );
- }
- $origText = $this->getText( $title );
- $text = $this->patch( $origText, $params['diff'] );
- if ( $text === false ) {
- $this->printLatin1( "$editTime $title STILL FAILS!\n" );
- $this->blacklist[$title] = true;
- return;
- }
-
- echo "\n";
- }
-
- $params['text'] = $text;
- $this->saveRevision( $params );
- $this->numGoodRevs++;
- #$this->printLatin1( "$editTime $title\n" );
- }
-
- function doPendingOps( $editTime ) {
- foreach ( $this->moveLog as $newTitle => $entry ) {
- if ( $entry['timestamp'] <= $editTime ) {
- unset( $this->moveLog[$newTitle] );
- if ( isset( $entry['deep'] ) ) {
- $this->renameTextLinks( $entry['old'], $newTitle, $entry['timestamp'] );
- }
- }
- }
-
- foreach ( $this->renameTextLinksOps as $renameTime => $replacements ) {
- if ( $editTime >= $renameTime ) {
- foreach ( $replacements as $old => $new ) {
- $this->printLatin1( "SUBSTITUTE $old -> $new\n" );
- $this->renameTextLinks( $old, $new, $renameTime );
- }
- unset( $this->renameTextLinksOps[$renameTime] );
- }
- }
-
- foreach ( $this->unixLineEndingsOps as $fixTime => $title ) {
- if ( $editTime >= $fixTime ) {
- $this->printLatin1( "$fixTime $title FIXING LINE ENDINGS\n" );
- $text = $this->getText( $title );
- $text = str_replace( "\r", '', $text );
- $this->saveRevision( array(
- 'rctitle' => $title,
- 'timestamp' => $fixTime,
- 'extra' => array( 'name' => 'UseModWiki admin' ),
- 'text' => $text,
- 'summary' => 'Fixing line endings',
- ) );
- unset( $this->unixLineEndingsOps[$fixTime] );
- }
- }
- }
-
- function patch( $source, $diff ) {
- file_put_contents( $this->articleFileName, $source );
- file_put_contents( $this->patchFileName, $diff );
- $error = wfShellExec(
- wfEscapeShellArg(
- 'patch',
- '-n',
- '-r', '-',
- '--no-backup-if-mismatch',
- '--binary',
- $this->articleFileName,
- $this->patchFileName
- ) . ' 2>&1',
- $status
- );
- $text = file_get_contents( $this->articleFileName );
- if ( $status || $text === false ) {
- return false;
- } else {
- return $text;
- }
- }
-
- function resolveFailedDiff( $origText, $diff ) {
- $context = array();
- $diffLines = explode( "\n", $diff );
- for ( $i = 0; $i < count( $diffLines ); $i++ ) {
- $diffLine = $diffLines[$i];
- if ( !preg_match( '/^(\d+)(?:,\d+)?[acd]\d+(?:,\d+)?$/', $diffLine, $m ) ) {
- continue;
- }
-
- $sourceIndex = intval( $m[1] );
- $i++;
- while ( $i < count( $diffLines ) && substr( $diffLines[$i], 0, 1 ) === '<' ) {
- $context[$sourceIndex - 1] = substr( $diffLines[$i], 2 );
- $sourceIndex++;
- $i++;
- }
- $i--;
- }
-
- $changedLinks = array();
- $origLines = explode( "\n", $origText );
- foreach ( $context as $i => $contextLine ) {
- $origLine = isset( $origLines[$i] ) ? $origLines[$i] : '';
- if ( $contextLine === $origLine ) {
- continue;
- }
- $newChanges = $this->resolveTextChange( $origLine, $contextLine );
- if ( is_array( $newChanges ) ) {
- $changedLinks += $newChanges;
- } else {
- echo "Resolution failure on line " . ( $i + 1 ) . "\n";
- $this->printLatin1( $newChanges );
- }
- }
-
- return $changedLinks;
- }
-
- function resolveTextChange( $source, $dest ) {
- $changedLinks = array();
- $sourceLinks = $this->getLinkList( $source );
- $destLinks = $this->getLinkList( $dest );
- $newLinks = array_diff( $destLinks, $sourceLinks );
- $removedLinks = array_diff( $sourceLinks, $destLinks );
-
- // Match up the removed links with the new links
- foreach ( $newLinks as $newLink ) {
- $minDistance = 100000000;
- $bestRemovedLink = false;
- foreach ( $removedLinks as $removedLink ) {
- $editDistance = levenshtein( $newLink, $removedLink );
- if ( $editDistance < $minDistance ) {
- $minDistance = $editDistance;
- $bestRemovedLink = $removedLink;
- }
- }
- if ( $bestRemovedLink !== false ) {
- $changedLinks[$bestRemovedLink] = $newLink;
- $newLinks = array_diff( $newLinks, array( $newLink ) );
- $removedLinks = array_diff( $removedLinks, array( $bestRemovedLink ) );
- }
- }
-
- $proposal = $source;
- foreach ( $changedLinks as $removedLink => $newLink ) {
- $proposal = $this->substituteTextLinks( $removedLink, $newLink, $proposal );
- }
- if ( $proposal !== $dest ) {
- // Resolution failed
- $msg = "Source line: $source\n" .
- "Source links: " . implode( ', ', $sourceLinks ) . "\n" .
- "Context line: $dest\n" .
- "Context links: " . implode( ', ', $destLinks ) . "\n" .
- "Proposal: $proposal\n";
- return $msg;
- }
- return $changedLinks;
- }
-
- function processDiffFile( $callback ) {
- $diffFile = fopen( "{$this->dataDir}/diff_log", 'r' );
-
- $delimiter = "------\n";
- file_put_contents( $this->articleFileName, "Describe the new page here.\n" );
-
- $line = fgets( $diffFile );
- $lineNum = 1;
- if ( $line !== $delimiter ) {
- echo "Invalid diff file\n";
- return false;
- }
- $lastReportLine = 0;
- $this->numRevs = 0;
-
- while ( true ) {
- $line = fgets( $diffFile );
- $lineNum++;
- if ( $line === false ) {
- break;
- }
- if ( $lineNum > $lastReportLine + 1000 ) {
- $lastReportLine = $lineNum;
- fwrite( STDERR, "$lineNum \r" );
- fflush( STDERR );
- }
- $line = trim( $line );
- if ( !preg_match( '/^([^|]+)\|(\d+)$/', $line, $matches ) ) {
- echo "Invalid header on line $lineNum\n";
- return true;
- }
- list( , $title, $editTime ) = $matches;
-
- $diff = '';
- $diffStartLine = $lineNum;
- while ( true ) {
- $line = fgets( $diffFile );
- $lineNum++;
- if ( $line === $delimiter ) {
- break;
- }
- if ( $line === false ) {
- break 2;
- }
- $diff .= $line;
- }
-
- $this->numRevs++;
-
- if ( !isset( $this->rc[$editTime] ) ) {
- $this->printLatin1( "$editTime $title DELETED, skipping\n" );
- continue;
- }
-
- if ( count( $this->rc[$editTime] ) == 1 ) {
- $params = $this->rc[$editTime][0];
- } else {
- $params = false;
- $candidates = '';
- foreach ( $this->rc[$editTime] as $rc ) {
- if ( $rc['rctitle'] === $title ) {
- $params = $rc;
- break;
- }
- if ( $candidates === '' ) {
- $candidates = $rc['rctitle'];
- } else {
- $candidates .= ', ' . $rc['rctitle'];
- }
- }
- if ( !$params ) {
- $this->printLatin1( "$editTime $title ERROR cannot resolve rclog\n" );
- $this->printLatin1( "$editTime $title CANDIDATES: $candidates\n" );
- continue;
- }
- }
- $params['diff'] = $diff;
- $params['title'] = $title;
- $params['diffStartLine'] = $diffStartLine;
- call_user_func( $callback, $params );
- }
- echo "\n";
-
- if ( !feof( $diffFile ) ) {
- echo "Stopped at line $lineNum\n";
- }
- return true;
- }
-
- function reconcileCurrentRevs() {
- foreach ( $this->textCache as $title => $text ) {
- $fileName = "{$this->dataDir}/page/";
- if ( preg_match( '/^[A-Z]/', $title, $m ) ) {
- $fileName .= $m[0];
- } else {
- $fileName .= 'other';
- }
- $fileName .= "/$title.db";
-
- if ( !file_exists( $fileName ) ) {
- $this->printLatin1( "ERROR: Cannot find page file for {$title}\n" );
- continue;
- }
-
- $fileContents = file_get_contents( $fileName );
- $page = $this->unserializeUseMod( $fileContents, $this->FS1 );
- $section = $this->unserializeUseMod( $page['text_default'], $this->FS2 );
- $data = $this->unserializeUseMod( $section['data'], $this->FS3 );
- $pageText = $data['text'];
- if ( $text !== $pageText ) {
- $substs = $this->resolveTextChange( $text, $pageText );
- if ( is_array( $substs ) ) {
- foreach ( $substs as $source => $dest ) {
- if ( isset( $this->moveLog[$dest] ) ) {
- $this->printLatin1( "ERROR: need deep rename: $source\n" );
- } else {
- $this->printLatin1( "ERROR: need substitute: $source -> $dest\n" );
- }
- }
- } else {
- $this->printLatin1( "ERROR: unresolved diff in $title:\n" );
- wfSuppressWarnings();
- $diff = xdiff_string_diff( $text, $pageText ) . '';
- wfRestoreWarnings();
- $this->printLatin1( "$diff\n" );
- }
- }
- }
- }
-
- function makeTitle( $titleText ) {
- return Title::newFromText( $this->encode( $titleText ) );
- }
-
- function getText( $titleText ) {
- if ( !isset( $this->textCache[$titleText] ) ) {
- return "Describe the new page here.\n";
- } else {
- return $this->textCache[$titleText];
- }
- }
-
- function saveRevision( $params ) {
- $this->textCache[$params['rctitle']] = $params['text'];
-
- $out = "<page>\n" .
- $this->element( 'title', $params['rctitle'] ) .
- "<revision>\n" .
- $this->element( 'id', $this->revId ++ ) .
- $this->element( 'timestamp', wfTimestamp( TS_ISO_8601, $params['timestamp'] ) ) .
- "<contributor>\n";
- if ( isset( $params['extra']['name'] ) ) {
- $out .= $this->element( 'username', $params['extra']['name'] );
- }
- if ( isset( $params['extra']['id'] ) ) {
- $out .= $this->element( 'id', $params['extra']['id'] );
- }
- if ( isset( $params['host'] ) ) {
- $out .= $this->element( 'ip', $params['host'] );
- }
- $out .=
- "</contributor>\n" .
- $this->element( 'comment', $params['summary'] ) .
- "<text xml:space=\"preserve\">" .
- htmlspecialchars( $this->encode( $params['text'] ) ) .
- "</text>\n" .
- "</revision>\n" .
- "</page>\n";
- fwrite( $this->outFile, $out );
- }
-
- function renameTextLinks( $old, $new, $timestamp ) {
- $newWithUnderscores = $new;
- $old = str_replace( '_', ' ', $old );
- $new = str_replace( '_', ' ', $new );
-
- foreach ( $this->textCache as $title => $oldText ) {
- if ( $newWithUnderscores === $title
- && in_array( $title, $this->skipSelfSubstitution ) )
- {
- // Hack to make Pythagorean_Theorem etc. work
- continue;
- }
-
- $newText = $this->substituteTextLinks( $old, $new, $oldText );
- if ( $oldText !== $newText ) {
- $this->saveRevision( array(
- 'rctitle' => $title,
- 'timestamp' => $timestamp,
- 'text' => $newText,
- 'extra' => array( 'name' => 'Page move link fixup script' ),
- 'summary' => '',
- 'minor' => true
- ) );
- }
- }
- }
-
- function substituteTextLinks( $old, $new, $text ) {
- $this->saveUrl = array();
- $this->old = $old;
- $this->new = $new;
-
- $text = str_replace( $this->FS, '', $text ); # Remove separators (paranoia)
- $text = preg_replace_callback( '/(<pre>(.*?)<\/pre>)/is',
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( '/(<code>(.*?)<\/code>)/is',
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( '/(<nowiki>(.*?)<\/nowiki>)/s',
- array( $this, 'storeRaw' ), $text );
-
- $text = preg_replace_callback( "/\[\[{$this->FreeLinkPattern}\|([^\]]+)\]\]/",
- array( $this, 'subFreeLink' ), $text );
- $text = preg_replace_callback( "/\[\[{$this->FreeLinkPattern}\]\]/",
- array( $this, 'subFreeLink' ), $text );
- $text = preg_replace_callback( "/(\[{$this->UrlPattern}\s+([^\]]+?)\])/",
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( "/(\[{$this->InterLinkPattern}\s+([^\]]+?)\])/",
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( "/(\[?{$this->UrlPattern}\]?)/",
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( "/(\[?{$this->InterLinkPattern}\]?)/",
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( "/{$this->LinkPattern}/",
- array( $this, 'subWikiLink' ), $text );
-
- $text = preg_replace_callback( "/{$this->FS}(\d+){$this->FS}/",
- array( $this, 'restoreRaw' ), $text ); # Restore saved text
- return $text;
- }
-
- function getLinkList( $text ) {
- $this->saveUrl = array();
- $this->linkList = array();
-
- $text = str_replace( $this->FS, '', $text ); # Remove separators (paranoia)
- $text = preg_replace_callback( '/(<pre>(.*?)<\/pre>)/is',
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( '/(<code>(.*?)<\/code>)/is',
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( '/(<nowiki>(.*?)<\/nowiki>)/s',
- array( $this, 'storeRaw' ), $text );
-
- $text = preg_replace_callback( "/\[\[{$this->FreeLinkPattern}\|([^\]]+)\]\]/",
- array( $this, 'storeLink' ), $text );
- $text = preg_replace_callback( "/\[\[{$this->FreeLinkPattern}\]\]/",
- array( $this, 'storeLink' ), $text );
- $text = preg_replace_callback( "/(\[{$this->UrlPattern}\s+([^\]]+?)\])/",
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( "/(\[{$this->InterLinkPattern}\s+([^\]]+?)\])/",
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( "/(\[?{$this->UrlPattern}\]?)/",
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( "/(\[?{$this->InterLinkPattern}\]?)/",
- array( $this, 'storeRaw' ), $text );
- $text = preg_replace_callback( "/{$this->LinkPattern}/",
- array( $this, 'storeLink' ), $text );
-
- return $this->linkList;
- }
-
- function storeRaw( $m ) {
- $this->saveUrl[] = $m[1];
- return $this->FS . (count( $this->saveUrl ) - 1) . $this->FS;
- }
-
- function subFreeLink( $m ) {
- $link = $m[1];
- if ( isset( $m[2] ) ) {
- $name = $m[2];
- } else {
- $name = '';
- }
- $oldlink = $link;
- $link = preg_replace( '/^\s+/', '', $link );
- $link = preg_replace( '/\s+$/', '', $link );
- if ( $link == $this->old ) {
- $link = $this->new;
- } else {
- $link = $oldlink; # Preserve spaces if no match
- }
- $link = "[[$link";
- if ( $name !== "" ) {
- $link .= "|$name";
- }
- $link .= "]]";
- return $this->storeRaw( array( 1 => $link ) );
- }
-
- function subWikiLink( $m ) {
- $link = $m[1];
- if ( $link == $this->old ) {
- $link = $this->new;
- if ( !preg_match( "/^{$this->LinkPattern}$/", $this->new ) ) {
- $link = "[[$link]]";
- }
- }
- return $this->storeRaw( array( 1 => $link ) );
- }
-
- function restoreRaw( $m ) {
- return $this->saveUrl[$m[1]];
- }
-
- function storeLink( $m ) {
- $this->linkList[] = $m[1];
- return $this->storeRaw( $m );
- }
-
- function encode( $s ) {
- return strtr( $s, $this->encodeMap );
- }
-
- function decode( $s ) {
- return strtr( $s, $this->decodeMap );
- }
-
- function printLatin1( $s ) {
- echo $this->encode( $s );
- }
-
- function unserializeUseMod( $s, $sep ) {
- $parts = explode( $sep, $s );
- $result = array();
- for ( $i = 0; $i < count( $parts ); $i += 2 ) {
- $result[$parts[$i]] = $parts[$i+1];
- }
- return $result;
- }
-}
-
-$maintClass = 'ImportUseModWikipedia';
-require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/install.php b/maintenance/install.php
index dba43400..9a408aa6 100644
--- a/maintenance/install.php
+++ b/maintenance/install.php
@@ -51,6 +51,7 @@ class CommandLineInstaller extends Maintenance {
$this->addOption( 'dbport', 'The database port; only for PostgreSQL (5432)', false, true );
$this->addOption( 'dbname', 'The database name (my_wiki)', false, true );
$this->addOption( 'dbpath', 'The path for the SQLite DB (/var/data)', false, true );
+ $this->addOption( 'dbprefix', 'Optional database table name prefix', false, true );
$this->addOption( 'installdbuser', 'The user to use for installing (root)', false, true );
$this->addOption( 'installdbpass', 'The pasword for the DB user to install as.', false, true );
$this->addOption( 'dbuser', 'The user to use for normal operations (wikiuser)', false, true );
diff --git a/maintenance/jsparse.php b/maintenance/jsparse.php
index ae6f1f1d..da6798e1 100644
--- a/maintenance/jsparse.php
+++ b/maintenance/jsparse.php
@@ -32,7 +32,6 @@ class JSParseHelper extends Maintenance {
}
public function execute() {
- $iterations = $this->getOption( 'i', 100 );
if ( $this->hasArg() ) {
$files = $this->mArgs;
} else {
diff --git a/maintenance/language/StatOutputs.php b/maintenance/language/StatOutputs.php
index c6d03641..befd0d72 100644
--- a/maintenance/language/StatOutputs.php
+++ b/maintenance/language/StatOutputs.php
@@ -21,7 +21,7 @@ if ( !defined( 'MEDIAWIKI' ) ) die();
* @file
* @ingroup MaintenanceLanguage
* @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @author Ashar Voultoiz <hashar at free dot fr>
+ * @author Antoine Musso <hashar at free dot fr>
*/
/** A general output object. Need to be overriden */
@@ -54,7 +54,7 @@ class wikiStatsOutput extends statsOutput {
echo 'English (en) is excluded because it is the default localization';
if( is_array( $wgDummyLanguageCodes ) ) {
$dummyCodes = array();
- foreach( $wgDummyLanguageCodes as $dummyCode ) {
+ foreach( $wgDummyLanguageCodes as $dummyCode => $correctCode ) {
$dummyCodes[] = $wgContLang->getLanguageName( $dummyCode ) . ' (' . $dummyCode . ')';
}
echo ', as well as the following languages that are not intended for system message translations, usually because they redirect to other language codes: ' . implode( ', ', $dummyCodes );
diff --git a/maintenance/language/checkLanguage.inc b/maintenance/language/checkLanguage.inc
index 1e4b94a2..8ab6125b 100644
--- a/maintenance/language/checkLanguage.inc
+++ b/maintenance/language/checkLanguage.inc
@@ -304,17 +304,17 @@ ENDS;
/**
* Check a language.
- * @param $code The language code.
- * @return The results.
+ * @param $code string The language code.
+ * @return array The results.
*/
protected function checkLanguage( $code ) {
# Syntax check only
+ $results = array();
if ( $this->level === 0 ) {
$this->L->getMessages( $code );
- return;
+ return $results;
}
- $results = array();
$checkFunctions = $this->getChecks();
$checkBlacklist = $this->getCheckBlacklist();
foreach ( $this->checks as $check ) {
@@ -643,7 +643,7 @@ ENDS;
/**
* Check a language and show the results.
- * @param $code The language code.
+ * @param $code string The language code.
*/
protected function checkLanguage( $code ) {
foreach( $this->extensions as $extension ) {
diff --git a/maintenance/language/function-list.php b/maintenance/language/function-list.php
deleted file mode 100644
index 7b0e57c2..00000000
--- a/maintenance/language/function-list.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup MaintenanceLanguage
- */
-
-define( 'MEDIAWIKI', 1 );
-define( 'NOT_REALLY_MEDIAWIKI', 1 );
-
-class Language { }
-foreach ( glob( 'Language*.php' ) as $file ) {
- if ( $file != 'Language.php' ) {
- require_once( $file );
- }
-}
-
-$removedFunctions = array( 'date', 'time', 'timeanddate', 'formatMonth', 'formatDay',
- 'getMonthName', 'getMonthNameGen', 'getMonthAbbreviation', 'getWeekdayName',
- 'userAdjust', 'dateFormat', 'timeSeparator', 'timeDateSeparator', 'timeBeforeDate',
- 'monthByLatinNumber', 'getSpecialMonthName',
-
- 'commafy'
-);
-
-$numRemoved = 0;
-$total = 0;
-$classes = get_declared_classes();
-ksort( $classes );
-foreach ( $classes as $class ) {
- if ( !preg_match( '/^Language/', $class ) || $class == 'Language' || $class == 'LanguageConverter' ) {
- continue;
- }
-
- print "$class\n";
- $methods = get_class_methods( $class );
- print_r( $methods );
-
- if ( !count( array_diff( $methods, $removedFunctions ) ) ) {
- print "removed\n";
- $numRemoved++;
- }
- $total++;
- print "\n";
-}
-
-print "$numRemoved will be removed out of $total\n";
-
-
diff --git a/maintenance/language/generateCollationData.php b/maintenance/language/generateCollationData.php
index 2c3ffedc..e5ce5c87 100644
--- a/maintenance/language/generateCollationData.php
+++ b/maintenance/language/generateCollationData.php
@@ -1,4 +1,8 @@
<?php
+/**
+ * @ingroup Maintenance
+ * @file
+ */
require_once( dirname( __FILE__ ) .'/../Maintenance.php' );
@@ -12,7 +16,7 @@ class GenerateCollationData extends Maintenance {
/** The primary weights, indexed by codepoint */
var $weights;
- /**
+ /**
* A hashtable keyed by codepoint, where presence indicates that a character
* has a decomposition mapping. This makes it non-preferred for group header
* selection.
@@ -30,7 +34,7 @@ class GenerateCollationData extends Maintenance {
public function __construct() {
parent::__construct();
$this->addOption( 'data-dir', 'A directory on the local filesystem ' .
- 'containing allkeys.txt and ucd.all.grouped.xml from unicode.org',
+ 'containing allkeys.txt and ucd.all.grouped.xml from unicode.org',
false, true );
$this->addOption( 'debug-output', 'Filename for sending debug output to',
false, true );
@@ -72,7 +76,7 @@ class GenerateCollationData extends Maintenance {
// but do not skip a normal space (U+0020) since
// people like to use that as a fake no header symbol.
$category = substr( $data['gc'], 0, 1 );
- if ( strpos( 'LNPS', $category ) === false
+ if ( strpos( 'LNPS', $category ) === false
&& $data['cp'] !== '0020' ) {
return;
}
@@ -84,7 +88,7 @@ class GenerateCollationData extends Maintenance {
return;
}
- // Skip the composed Hangul syllables, we will use the bare Jamo
+ // Skip the composed Hangul syllables, we will use the bare Jamo
// as first letters
if ( $data['block'] == 'Hangul Syllables' ) {
return;
@@ -163,7 +167,7 @@ class GenerateCollationData extends Maintenance {
}
$this->weights[$cp] = $primary;
if ( $tertiary === '.0008'
- || $tertiary === '.000E' )
+ || $tertiary === '.000E' )
{
$goodTertiaryChars[$cp] = true;
}
@@ -192,8 +196,8 @@ class GenerateCollationData extends Maintenance {
}
// If one character has a given primary weight sequence, and a second
- // character has a longer primary weight sequence with an initial
- // portion equal to the first character, then remove the second
+ // character has a longer primary weight sequence with an initial
+ // portion equal to the first character, then remove the second
// character. This avoids having characters like U+A732 (double A)
// polluting the basic latin sort area.
@@ -306,11 +310,12 @@ class UcdXmlReader {
while ( $this->xml->name !== 'ucd' && $this->xml->read() );
$this->xml->read();
return $this->xml;
- }
+ }
/**
- * Read the attributes of the current element node and return them
+ * Read the attributes of the current element node and return them
* as an array
+ * @return array
*/
protected function readAttributes() {
$attrs = array();
diff --git a/maintenance/language/languages.inc b/maintenance/language/languages.inc
index 60b1112f..06102ac1 100644
--- a/maintenance/language/languages.inc
+++ b/maintenance/language/languages.inc
@@ -61,7 +61,7 @@ class languages {
/**
* Get the language list.
*
- * @return The language list.
+ * @return array The language list.
*/
public function getLanguages() {
return $this->mLanguages;
@@ -70,7 +70,7 @@ class languages {
/**
* Get the ignored messages list.
*
- * @return The ignored messages list.
+ * @return array The ignored messages list.
*/
public function getIgnoredMessages() {
return $this->mIgnoredMessages;
@@ -79,7 +79,7 @@ class languages {
/**
* Get the optional messages list.
*
- * @return The optional messages list.
+ * @return array The optional messages list.
*/
public function getOptionalMessages() {
return $this->mOptionalMessages;
@@ -137,7 +137,7 @@ class languages {
* obsolete - messages which should not be translated, either because they do not exist, or they are ignored messages.
* translated - messages which are either required or optional, but translated from English and needed.
*
- * @param $code The language code.
+ * @param $code string The language code.
*/
private function loadMessages( $code ) {
if ( isset( $this->mMessages[$code] ) ) {
@@ -203,7 +203,7 @@ class languages {
* obsolete - messages which should not be translated, either because they do not exist, or they are ignored messages.
* translated - messages which are either required or optional, but translated from English and needed.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
* @return string The messages in this language.
*/
@@ -220,7 +220,7 @@ class languages {
* ignored - messages which should not be translated to other languages.
* translatable - messages which are either required or optional, but can be translated from English.
*
- * @return The general English messages.
+ * @return array The general English messages.
*/
public function getGeneralMessages() {
$this->loadGeneralMessages();
@@ -230,9 +230,9 @@ class languages {
/**
* Get fallback language code for a specific language.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return Fallback code.
+ * @return string Fallback code.
*/
public function getFallback( $code ) {
$this->loadFile( $code );
@@ -242,7 +242,7 @@ class languages {
/**
* Get namespace names for a specific language.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
* @return Namespace names.
*/
@@ -254,7 +254,7 @@ class languages {
/**
* Get namespace aliases for a specific language.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
* @return Namespace aliases.
*/
@@ -266,7 +266,7 @@ class languages {
/**
* Get magic words for a specific language.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
* @return Magic words.
*/
@@ -278,7 +278,7 @@ class languages {
/**
* Get special page aliases for a specific language.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
* @return Special page aliases.
*/
@@ -290,9 +290,9 @@ class languages {
/**
* Get the untranslated messages for a specific language.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The untranslated messages for this language.
+ * @return array The untranslated messages for this language.
*/
public function getUntranslatedMessages( $code ) {
$this->loadGeneralMessages();
@@ -303,9 +303,9 @@ class languages {
/**
* Get the duplicate messages for a specific language.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The duplicate messages for this language.
+ * @return array The duplicate messages for this language.
*/
public function getDuplicateMessages( $code ) {
$this->loadGeneralMessages();
@@ -322,9 +322,9 @@ class languages {
/**
* Get the obsolete messages for a specific language.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The obsolete messages for this language.
+ * @return array The obsolete messages for this language.
*/
public function getObsoleteMessages( $code ) {
$this->loadGeneralMessages();
@@ -335,9 +335,9 @@ class languages {
/**
* Get the messages whose variables do not match the original ones.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The messages whose variables do not match the original ones.
+ * @return array The messages whose variables do not match the original ones.
*/
public function getMessagesWithMismatchVariables( $code ) {
$this->loadGeneralMessages();
@@ -366,9 +366,9 @@ class languages {
/**
* Get the messages which do not use plural.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The messages which do not use plural in this language.
+ * @return array The messages which do not use plural in this language.
*/
public function getMessagesWithoutPlural( $code ) {
$this->loadGeneralMessages();
@@ -385,9 +385,9 @@ class languages {
/**
* Get the empty messages.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The empty messages for this language.
+ * @return array The empty messages for this language.
*/
public function getEmptyMessages( $code ) {
$this->loadGeneralMessages();
@@ -404,9 +404,9 @@ class languages {
/**
* Get the messages with trailing whitespace.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The messages with trailing whitespace in this language.
+ * @return array The messages with trailing whitespace in this language.
*/
public function getMessagesWithWhitespace( $code ) {
$this->loadGeneralMessages();
@@ -423,9 +423,9 @@ class languages {
/**
* Get the non-XHTML messages.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The non-XHTML messages for this language.
+ * @return array The non-XHTML messages for this language.
*/
public function getNonXHTMLMessages( $code ) {
$this->loadGeneralMessages();
@@ -451,9 +451,9 @@ class languages {
/**
* Get the messages which include wrong characters.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The messages which include wrong characters in this language.
+ * @return array The messages which include wrong characters in this language.
*/
public function getMessagesWithWrongChars( $code ) {
$this->loadGeneralMessages();
@@ -488,9 +488,9 @@ class languages {
/**
* Get the messages which include dubious links.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The messages which include dubious links in this language.
+ * @return array The messages which include dubious links in this language.
*/
public function getMessagesWithDubiousLinks( $code ) {
$this->loadGeneralMessages();
@@ -517,9 +517,9 @@ class languages {
/**
* Get the messages which include unbalanced brackets.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The messages which include unbalanced brackets in this language.
+ * @return array The messages which include unbalanced brackets in this language.
*/
public function getMessagesWithUnbalanced( $code ) {
$this->loadGeneralMessages();
@@ -547,7 +547,7 @@ class languages {
if ( $a !== $b || $c !== $d ) {
$messages[$key] = "$a, $b, $c, $d";
}
-
+
}
return $messages;
}
@@ -555,9 +555,9 @@ class languages {
/**
* Get the untranslated namespace names.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The untranslated namespace names in this language.
+ * @return array The untranslated namespace names in this language.
*/
public function getUntranslatedNamespaces( $code ) {
$this->loadFile( 'en' );
@@ -570,9 +570,9 @@ class languages {
/**
* Get the project talk namespace names with no $1.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The problematic project talk namespaces in this language.
+ * @return array The problematic project talk namespaces in this language.
*/
public function getProblematicProjectTalks( $code ) {
$this->loadFile( $code );
@@ -599,9 +599,9 @@ class languages {
/**
* Get the untranslated magic words.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The untranslated magic words in this language.
+ * @return array The untranslated magic words in this language.
*/
public function getUntranslatedMagicWords( $code ) {
$this->loadFile( 'en' );
@@ -618,9 +618,9 @@ class languages {
/**
* Get the obsolete magic words.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The obsolete magic words in this language.
+ * @return array The obsolete magic words in this language.
*/
public function getObsoleteMagicWords( $code ) {
$this->loadFile( 'en' );
@@ -637,9 +637,9 @@ class languages {
/**
* Get the magic words that override the original English magic word.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The overriding magic words in this language.
+ * @return array The overriding magic words in this language.
*/
public function getOverridingMagicWords( $code ) {
$this->loadFile( 'en' );
@@ -666,9 +666,9 @@ class languages {
/**
* Get the magic words which do not match the case-sensitivity of the original words.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The magic words whose case does not match in this language.
+ * @return array The magic words whose case does not match in this language.
*/
public function getCaseMismatchMagicWords( $code ) {
$this->loadFile( 'en' );
@@ -689,9 +689,9 @@ class languages {
/**
* Get the untranslated special page names.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The untranslated special page names in this language.
+ * @return array The untranslated special page names in this language.
*/
public function getUntraslatedSpecialPages( $code ) {
$this->loadFile( 'en' );
@@ -708,9 +708,9 @@ class languages {
/**
* Get the obsolete special page names.
*
- * @param $code The language code.
+ * @param $code string The language code.
*
- * @return The obsolete special page names in this language.
+ * @return array The obsolete special page names in this language.
*/
public function getObsoleteSpecialPages( $code ) {
$this->loadFile( 'en' );
@@ -726,7 +726,11 @@ class languages {
}
class extensionLanguages extends languages {
- private $mMessageGroup; # The message group
+
+ /**
+ * @var MessageGroup
+ */
+ private $mMessageGroup;
/**
* Load the messages group.
@@ -743,7 +747,7 @@ class extensionLanguages extends languages {
/**
* Get the extension name.
*
- * @return The extension name.
+ * @return string The extension name.
*/
public function name() {
return $this->mMessageGroup->getLabel();
@@ -752,7 +756,7 @@ class extensionLanguages extends languages {
/**
* Load the language file.
*
- * @param $code The language code.
+ * @param $code string The language code.
*/
protected function loadFile( $code ) {
if( !isset( $this->mRawMessages[$code] ) ) {
diff --git a/maintenance/language/messageTypes.inc b/maintenance/language/messageTypes.inc
index 62374500..1c33667a 100644
--- a/maintenance/language/messageTypes.inc
+++ b/maintenance/language/messageTypes.inc
@@ -90,6 +90,8 @@ $wgIgnoredMessages = array(
'accesskey-blockip-block',
'accesskey-export',
'accesskey-import',
+ 'accesskey-watchlistedit-normal-submit',
+ 'accesskey-watchlistedit-raw-submit',
'addsection',
'talkpageheader',
'anonnotice',
@@ -125,7 +127,6 @@ $wgIgnoredMessages = array(
'revision-nav',
'rfcurl',
'shareddescriptionfollows',
- 'signature',
'signature-anon',
'signupstart',
'signupend',
@@ -181,7 +182,6 @@ $wgIgnoredMessages = array(
'unusedtemplates-summary',
'fewestrevisions-summary',
'upload-summary',
- 'newuserlogentry',
'wantedtemplates-summary',
'activeusers-summary',
'search-summary',
@@ -189,6 +189,8 @@ $wgIgnoredMessages = array(
'addsection-preload',
'addsection-editintro',
'longpage-hint',
+ 'javascripttest-backlink',
+ 'javascripttest-qunit-name',
);
/** Optional messages, which may be translated only if changed in the target language. */
@@ -197,7 +199,6 @@ $wgOptionalMessages = array(
'editsection-brackets',
'feed-atom',
'feed-rss',
- 'sectionlink',
'unit-pixel',
'userrights-irreversible-marker',
'tog-nolangconversion',
@@ -233,6 +234,9 @@ $wgOptionalMessages = array(
'variantname-ike-cans',
'variantname-ike-latn',
'variantname-iu',
+ 'variantname-shi-tfng',
+ 'variantname-shi-latn',
+ 'variantname-shi',
'rc-change-size',
'resetpass_text',
'image_sample',
@@ -314,10 +318,6 @@ $wgOptionalMessages = array(
'minutes-abbrev',
'hours-abbrev',
'days-abbrev',
- 'filerevert-backlink',
- 'filedelete-backlink',
- 'delete-backlink',
- 'protect-backlink',
'pagetitle',
'filename-prefix-blacklist',
'edittools',
@@ -326,6 +326,20 @@ $wgOptionalMessages = array(
'size-kilobytes',
'size-megabytes',
'size-gigabytes',
+ 'size-terabytes',
+ 'size-petabytes',
+ 'size-exabytes',
+ 'size-zetabytes',
+ 'size-yottabytes',
+ 'bitrate-bits',
+ 'bitrate-kilobits',
+ 'bitrate-megabits',
+ 'bitrate-gigabits',
+ 'bitrate-terabits',
+ 'bitrate-petabits',
+ 'bitrate-exabits',
+ 'bitrate-zetabits',
+ 'bitrate-yottabits',
'iranian-calendar-m1',
'iranian-calendar-m2',
'iranian-calendar-m3',
@@ -392,13 +406,10 @@ $wgOptionalMessages = array(
'listgrouprights-right-display',
'listgrouprights-right-revoked',
'timezone-utc',
- 'whatlinkshere-backlink',
- 'recentchangeslinked-backlink',
'unpatrolledletter',
'diff-with-additional',
'pagetitle-view-mainpage',
- 'trackback',
- 'trackbackexcerpt',
+ 'backlinksubtitle',
'prefs-registration-date-time',
'prefs-memberingroups-type',
'shared-repo-name-wikimediacommons',
diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc
index d707cf5d..bdd4d397 100644
--- a/maintenance/language/messages.inc
+++ b/maintenance/language/messages.inc
@@ -301,6 +301,7 @@ $wgMessageStructure = array(
'ok',
'pagetitle',
'pagetitle-view-mainpage',
+ 'backlinksubtitle',
'retrievedfrom',
'youhavenewmessages',
'newmessageslink',
@@ -385,6 +386,7 @@ $wgMessageStructure = array(
'formerror',
'badarticleerror',
'cannotdelete',
+ 'cannotdelete-title',
'badtitle',
'badtitletext',
'perfcached',
@@ -392,11 +394,12 @@ $wgMessageStructure = array(
'querypage-no-updates',
'wrong_wfQuery_params',
'viewsource',
- 'viewsourcefor',
+ 'viewsource-title',
'actionthrottled',
'actionthrottledtext',
'protectedpagetext',
'viewsourcetext',
+ 'viewyourtext',
'protectedinterface',
'editinginterface',
'sqlhidden',
@@ -480,6 +483,7 @@ $wgMessageStructure = array(
'noemailprefs',
'emailconfirmlink',
'invalidemailaddress',
+ 'cannotchangeemail',
'accountcreated',
'accountcreatedtext',
'createaccount-title',
@@ -495,6 +499,7 @@ $wgMessageStructure = array(
'pear-mail-error',
'php-mail-error',
'php-mail-error-unknown',
+ 'user-mail-no-addy',
),
'resetpass' => array(
'resetpass',
@@ -521,12 +526,27 @@ $wgMessageStructure = array(
'passwordreset-pretext',
'passwordreset-username',
'passwordreset-domain',
+ 'passwordreset-capture',
+ 'passwordreset-capture-help',
'passwordreset-email',
'passwordreset-emailtitle',
'passwordreset-emailtext-ip',
'passwordreset-emailtext-user',
'passwordreset-emailelement',
'passwordreset-emailsent',
+ 'passwordreset-emailsent-capture',
+ 'passwordreset-emailerror-capture',
+ ),
+ 'changeemail' => array(
+ 'changeemail',
+ 'changeemail-header',
+ 'changeemail-text',
+ 'changeemail-no-info',
+ 'changeemail-oldemail',
+ 'changeemail-newemail',
+ 'changeemail-none',
+ 'changeemail-submit',
+ 'changeemail-cancel',
),
'toolbar' => array(
'bold_sample',
@@ -569,9 +589,6 @@ $wgMessageStructure = array(
'blockedtext',
'autoblockedtext',
'blockednoreason',
- 'blockedoriginalsource',
- 'blockededitsource',
- 'whitelistedittitle',
'whitelistedittext',
'confirmedittext',
'nosuchsectiontitle',
@@ -755,10 +772,6 @@ $wgMessageStructure = array(
'revdelete-unsuppress',
'revdelete-log',
'revdelete-submit',
- 'revdelete-logentry',
- 'logdelete-logentry',
- 'revdelete-logaction',
- 'logdelete-logaction',
'revdelete-success',
'revdelete-failure',
'logdelete-success',
@@ -768,15 +781,6 @@ $wgMessageStructure = array(
'revdel-restore-visible',
'pagehist',
'deletedhist',
- 'revdelete-content',
- 'revdelete-summary',
- 'revdelete-uname',
- 'revdelete-restricted',
- 'revdelete-unrestricted',
- 'revdelete-hid',
- 'revdelete-unhid',
- 'revdelete-log-message',
- 'logdelete-log-message',
'revdelete-hide-current',
'revdelete-show-no-access',
'revdelete-modify-no-access',
@@ -938,6 +942,8 @@ $wgMessageStructure = array(
'prefs-watchlist-token',
'prefs-misc', // continue checking if used from here on (r49916)
'prefs-resetpass',
+ 'prefs-changeemail',
+ 'prefs-setemail',
'prefs-email',
'prefs-rendering',
'saveprefs',
@@ -997,6 +1003,7 @@ $wgMessageStructure = array(
'yourrealname',
'yourlanguage',
'yourvariant',
+ 'prefs-help-variant',
'yournick',
'prefs-help-signature',
'badsig',
@@ -1009,7 +1016,7 @@ $wgMessageStructure = array(
'email',
'prefs-help-realname',
- # 3 messages depending upon wgEmailConfirmToEdit and $wgEnableUserEmail
+ # 3 messages depending upon $wgEmailConfirmToEdit and $wgEnableUserEmail
'prefs-help-email',
'prefs-help-email-others',
'prefs-help-email-required',
@@ -1133,13 +1140,13 @@ $wgMessageStructure = array(
'right-autopatrol',
'right-patrolmarks',
'right-unwatchedpages',
- 'right-trackback',
'right-mergehistory',
'right-userrights',
'right-userrights-interwiki',
'right-siteadmin',
'right-override-export-depth',
'right-sendemail',
+ 'right-passwordreset',
),
'rightslog' => array(
'rightslog',
@@ -1173,16 +1180,17 @@ $wgMessageStructure = array(
'action-suppressionlog',
'action-block',
'action-protect',
+ 'action-rollback',
'action-import',
'action-importupload',
'action-patrol',
'action-autopatrol',
'action-unwatchedpages',
- 'action-trackback',
'action-mergehistory',
'action-userrights',
'action-userrights-interwiki',
'action-siteadmin',
+ 'action-sendemail',
),
'recentchanges' => array(
'nchanges',
@@ -1213,12 +1221,12 @@ $wgMessageStructure = array(
'newpageletter',
'boteditletter',
'unpatrolledletter',
- 'sectionlink',
'number_of_watching_users_RCview',
'number_of_watching_users_pageview',
'rc_categories',
'rc_categories_any',
'rc-change-size',
+ 'rc-change-size-new',
'newsectionsummary',
'rc-enhanced-expand',
'rc-enhanced-hide',
@@ -1228,7 +1236,6 @@ $wgMessageStructure = array(
'recentchangeslinked-feed',
'recentchangeslinked-toolbox',
'recentchangeslinked-title',
- 'recentchangeslinked-backlink',
'recentchangeslinked-noresult',
'recentchangeslinked-summary',
'recentchangeslinked-page',
@@ -1265,6 +1272,7 @@ $wgMessageStructure = array(
'ignorewarnings',
'minlength1',
'illegalfilename',
+ 'filename-toolong',
'badfilename',
'filetype-mime-mismatch',
'filetype-badmime',
@@ -1339,6 +1347,43 @@ $wgMessageStructure = array(
'upload-http-error',
),
+ 'filebackend-errors' => array(
+ 'backend-fail-stream',
+ 'backend-fail-backup',
+ 'backend-fail-notexists',
+ 'backend-fail-hashes',
+ 'backend-fail-notsame',
+ 'backend-fail-invalidpath',
+ 'backend-fail-delete',
+ 'backend-fail-alreadyexists',
+ 'backend-fail-store',
+ 'backend-fail-copy',
+ 'backend-fail-move',
+ 'backend-fail-opentemp',
+ 'backend-fail-writetemp',
+ 'backend-fail-closetemp',
+ 'backend-fail-read',
+ 'backend-fail-create',
+ 'backend-fail-readonly',
+ 'backend-fail-synced',
+ 'backend-fail-connect',
+ 'backend-fail-internal',
+ 'backend-fail-contenttype',
+ 'backend-fail-batchsize'
+ ),
+
+ 'lockmanager-errors' => array(
+ 'lockmanager-notlocked',
+ 'lockmanager-fail-closelock',
+ 'lockmanager-fail-deletelock',
+ 'lockmanager-fail-acquirelock',
+ 'lockmanager-fail-openlock',
+ 'lockmanager-fail-releaselock',
+ 'lockmanager-fail-db-bucket',
+ 'lockmanager-fail-db-release',
+ 'lockmanager-fail-svr-release'
+ ),
+
'zip' => array(
'zip-file-open-error',
'zip-wrong-format',
@@ -1354,6 +1399,7 @@ $wgMessageStructure = array(
'uploadstash-badtoken',
'uploadstash-errclear',
'uploadstash-refresh',
+ 'invalid-chunk-offset',
),
'img-auth' => array(
@@ -1448,7 +1494,6 @@ $wgMessageStructure = array(
),
'filerevert' => array(
'filerevert',
- 'filerevert-backlink',
'filerevert-legend',
'filerevert-intro',
'filerevert-comment',
@@ -1459,7 +1504,6 @@ $wgMessageStructure = array(
),
'filedelete' => array(
'filedelete',
- 'filedelete-backlink',
'filedelete-legend',
'filedelete-intro',
'filedelete-intro-old',
@@ -1474,6 +1518,7 @@ $wgMessageStructure = array(
'filedelete-reason-dropdown',
'filedelete-edit-reasonlist',
'filedelete-maintenance',
+ 'filedelete-maintenance-title',
),
'mimesearch' => array(
'mimesearch',
@@ -1591,6 +1636,8 @@ $wgMessageStructure = array(
'wantedpages-badtitle',
'wantedfiles',
'wantedfiles-summary',
+ 'wantedfiletext-cat',
+ 'wantedfiletext-nocat',
'wantedtemplates',
'wantedtemplates-summary',
'mostlinked',
@@ -1606,6 +1653,7 @@ $wgMessageStructure = array(
'mostrevisions',
'mostrevisions-summary',
'prefixindex',
+ 'prefixindex-namespace',
'prefixindex-summary',
'shortpages',
'shortpages-summary',
@@ -1730,11 +1778,6 @@ $wgMessageStructure = array(
'newuserlog' => array(
'newuserlogpage',
'newuserlogpagetext',
- 'newuserlogentry',
- 'newuserlog-byemail',
- 'newuserlog-create-entry',
- 'newuserlog-create2-entry',
- 'newuserlog-autocreate-entry',
),
'listgrouprights' => array(
'listgrouprights',
@@ -1847,15 +1890,12 @@ $wgMessageStructure = array(
'exbeforeblank',
'exblank',
'delete-confirm',
- 'delete-backlink',
'delete-legend',
'historywarning',
'confirmdeletetext',
'actioncomplete',
'actionfailed',
'deletedtext',
- 'deletedarticle',
- 'suppressedarticle',
'dellogpage',
'dellogpagetext',
'deletionlog',
@@ -1892,8 +1932,10 @@ $wgMessageStructure = array(
'unprotectedarticle',
'movedarticleprotection',
'protect-title',
+ 'protect-title-notallowed',
'prot_1movedto2',
- 'protect-backlink',
+ 'protect-badnamespace-title',
+ 'protect-badnamespace-text',
'protect-legend',
'protectcomment',
'protectexpiry',
@@ -1911,6 +1953,7 @@ $wgMessageStructure = array(
'protect-level-sysop',
'protect-summary-cascade',
'protect-expiring',
+ 'protect-expiring-local',
'protect-expiry-indefinite',
'protect-cascade',
'protect-cantedit',
@@ -1960,13 +2003,13 @@ $wgMessageStructure = array(
'undeletereset',
'undeleteinvert',
'undeletecomment',
- 'undeletedarticle',
'undeletedrevisions',
'undeletedrevisions-files',
'undeletedfiles',
'cannotundelete',
'undeletedpage',
'undelete-header',
+ 'undelete-search-title',
'undelete-search-box',
'undelete-search-prefix',
'undelete-search-submit',
@@ -1975,6 +2018,7 @@ $wgMessageStructure = array(
'undelete-bad-store-key',
'undelete-cleanup-error',
'undelete-missing-filearchive',
+ 'undelete-error',
'undelete-error-short',
'undelete-error-long',
'undelete-show-file-confirm',
@@ -2023,7 +2067,6 @@ $wgMessageStructure = array(
'whatlinkshere-title',
'whatlinkshere-summary',
'whatlinkshere-page',
- 'whatlinkshere-backlink',
'linkshere',
'nolinkshere',
'nolinkshere-ns',
@@ -2088,6 +2131,7 @@ $wgMessageStructure = array(
'blocklist-userblocks',
'blocklist-tempblocks',
'blocklist-addressblocks',
+ 'blocklist-rangeblocks',
'blocklist-timestamp',
'blocklist-target',
'blocklist-expiry',
@@ -2112,6 +2156,7 @@ $wgMessageStructure = array(
'unblocklink',
'change-blocklink',
'contribslink',
+ 'emaillink',
'autoblocker',
'blocklogpage',
'blocklog-showlog',
@@ -2202,9 +2247,6 @@ $wgMessageStructure = array(
'movepage-page-moved',
'movepage-page-unmoved',
'movepage-max-pages',
- '1movedto2',
- '1movedto2_redir',
- 'move-redirect-suppressed',
'movelogpage',
'movelogpagetext',
'movesubpage',
@@ -2237,8 +2279,10 @@ $wgMessageStructure = array(
'export' => array(
'export',
'exporttext',
+ 'exportall',
'exportcuronly',
'exportnohistory',
+ 'exportlistauthors',
'export-submit',
'export-addcattext',
'export-addcat',
@@ -2270,6 +2314,8 @@ $wgMessageStructure = array(
'thumbnail_error',
'djvu_page_error',
'djvu_no_xml',
+ 'thumbnail-temp-create',
+ 'thumbnail-dest-create',
'thumbnail_invalid_params',
'thumbnail_dest_directory',
'thumbnail_image-type',
@@ -2311,6 +2357,11 @@ $wgMessageStructure = array(
'import-upload',
'import-token-mismatch',
'import-invalid-interwiki',
+ 'import-error-edit',
+ 'import-error-create',
+ 'import-error-interwiki',
+ 'import-error-special',
+ 'import-error-invalid',
),
'importlog' => array(
'importlogpage',
@@ -2320,6 +2371,19 @@ $wgMessageStructure = array(
'import-logentry-interwiki',
'import-logentry-interwiki-detail',
),
+ 'javaccripttest' => array(
+ 'javascripttest',
+ 'javascripttest-backlink',
+ 'javascripttest-disabled',
+ 'javascripttest-title',
+ 'javascripttest-pagetext-noframework',
+ 'javascripttest-pagetext-unknownframework',
+ 'javascripttest-pagetext-frameworks',
+ 'javascripttest-pagetext-skins' ,
+ 'javascripttest-qunit-name',
+ 'javascripttest-qunit-intro',
+ 'javascripttest-qunit-heading',
+ ),
'accesskeys' => array(
'accesskey-pt-userpage',
'accesskey-pt-anonuserpage',
@@ -2388,6 +2452,8 @@ $wgMessageStructure = array(
'accesskey-blockip-block',
'accesskey-export',
'accesskey-import',
+ 'accesskey-watchlistedit-normal-submit',
+ 'accesskey-watchlistedit-raw-submit',
),
'tooltips' => array(
'tooltip-pt-userpage',
@@ -2450,6 +2516,8 @@ $wgMessageStructure = array(
'tooltip-diff',
'tooltip-compareselectedversions',
'tooltip-watch',
+ 'tooltip-watchlistedit-normal-submit',
+ 'tooltip-watchlistedit-raw-submit',
'tooltip-recreate',
'tooltip-upload',
'tooltip-rollback',
@@ -2554,9 +2622,6 @@ $wgMessageStructure = array(
'patrol-log' => array(
'patrol-log-page',
'patrol-log-header',
- 'patrol-log-line',
- 'patrol-log-auto',
- 'patrol-log-diff',
'log-show-hide-patrol',
),
'imagedeletion' => array(
@@ -2611,6 +2676,11 @@ $wgMessageStructure = array(
'minutes-abbrev',
'hours-abbrev',
'days-abbrev',
+ 'seconds',
+ 'minutes',
+ 'hours',
+ 'days',
+ 'ago',
),
'badimagelist' => array(
'bad_image_list',
@@ -2660,6 +2730,11 @@ $wgMessageStructure = array(
'variantname-ike-latn',
'variantname-iu',
),
+ 'variantname-shi' => array(
+ 'variantname-shi-tfng',
+ 'variantname-shi-latn',
+ 'variantname-shi',
+ ),
'metadata' => array(
'metadata',
'metadata-help',
@@ -3168,14 +3243,6 @@ $wgMessageStructure = array(
'scarytranscludefailed',
'scarytranscludetoolong',
),
- 'trackbacks' => array(
- 'trackbackbox',
- 'trackback',
- 'trackbackexcerpt',
- 'trackbackremove',
- 'trackbacklink',
- 'trackbackdeleteok',
- ),
'deleteconflict' => array(
'deletedwhileediting',
'confirmrecreate',
@@ -3239,6 +3306,22 @@ $wgMessageStructure = array(
'size-kilobytes',
'size-megabytes',
'size-gigabytes',
+ 'size-terabytes',
+ 'size-petabytes',
+ 'size-exabytes',
+ 'size-zetabytes',
+ 'size-yottabytes',
+ ),
+ 'bitrateunits' => array(
+ 'bitrate-bits',
+ 'bitrate-kilobits',
+ 'bitrate-megabits',
+ 'bitrate-gigabits',
+ 'bitrate-terabits',
+ 'bitrate-petabits',
+ 'bitrate-exabits',
+ 'bitrate-zetabits',
+ 'bitrate-yottabits',
),
'livepreview' => array(
'livepreview-loading',
@@ -3431,6 +3514,9 @@ $wgMessageStructure = array(
'compare-rev1',
'compare-rev2',
'compare-submit',
+ 'compare-invalid-title',
+ 'compare-title-not-exists',
+ 'compare-revision-not-exists',
),
'db-error-messages' => array(
'dberr-header',
@@ -3460,6 +3546,91 @@ $wgMessageStructure = array(
'unwatch' => array(
'confirm-unwatch-button',
),
+ 'logging' => array(
+ 'logentry-delete-delete',
+ 'logentry-delete-restore',
+ 'logentry-delete-event',
+ 'logentry-delete-revision',
+ 'logentry-delete-event-legacy',
+ 'logentry-delete-revision-legacy',
+ 'logentry-suppress-delete',
+ 'logentry-suppress-event',
+ 'logentry-suppress-revision',
+ 'logentry-suppress-event-legacy',
+ 'logentry-suppress-revision-legacy',
+ 'revdelete-content-hid',
+ 'revdelete-summary-hid',
+ 'revdelete-uname-hid',
+ 'revdelete-content-unhid',
+ 'revdelete-summary-unhid',
+ 'revdelete-uname-unhid',
+ 'revdelete-restricted',
+ 'revdelete-unrestricted',
+ 'logentry-move-move',
+ 'logentry-move-move-noredirect',
+ 'logentry-move-move_redir',
+ 'logentry-move-move_redir-noredirect',
+ 'logentry-patrol-patrol',
+ 'logentry-patrol-patrol-auto',
+ 'logentry-newusers-newusers',
+ 'logentry-newusers-create',
+ 'logentry-newusers-create2',
+ 'logentry-newusers-autocreate',
+ 'newuserlog-byemail',
+ ),
+ 'feedback' => array(
+ 'feedback-bugornote',
+ 'feedback-subject',
+ 'feedback-message',
+ 'feedback-cancel',
+ 'feedback-submit',
+ 'feedback-adding',
+ 'feedback-error1',
+ 'feedback-error2',
+ 'feedback-error3',
+ 'feedback-thanks',
+ 'feedback-close',
+ 'feedback-bugcheck',
+ 'feedback-bugnew',
+ ),
+ 'apierrors' => array(
+ 'api-error-badaccess-groups',
+ 'api-error-badtoken',
+ 'api-error-copyuploaddisabled',
+ 'api-error-duplicate',
+ 'api-error-duplicate-archive',
+ 'api-error-duplicate-archive-popup-title',
+ 'api-error-duplicate-popup-title',
+ 'api-error-empty-file',
+ 'api-error-emptypage',
+ 'api-error-fetchfileerror',
+ 'api-error-file-too-large',
+ 'api-error-filename-tooshort',
+ 'api-error-filetype-banned',
+ 'api-error-filetype-missing',
+ 'api-error-hookaborted',
+ 'api-error-http',
+ 'api-error-illegal-filename',
+ 'api-error-internal-error',
+ 'api-error-invalid-file-key',
+ 'api-error-missingparam',
+ 'api-error-missingresult',
+ 'api-error-mustbeloggedin',
+ 'api-error-mustbeposted',
+ 'api-error-noimageinfo',
+ 'api-error-nomodule',
+ 'api-error-ok-but-empty',
+ 'api-error-overwrite',
+ 'api-error-stashfailed',
+ 'api-error-timeout',
+ 'api-error-unclassified',
+ 'api-error-unknown-code',
+ 'api-error-unknown-error',
+ 'api-error-unknown-warning',
+ 'api-error-unknownerror',
+ 'api-error-uploaddisabled',
+ 'api-error-verification-error',
+ ),
);
/** Comments for each block */
@@ -3493,6 +3664,7 @@ XHTML id names.",
'passwordstrength' => 'JavaScript password checks',
'resetpass' => 'Change password dialog',
'passwordreset' => 'Special:PasswordReset',
+ 'changeemail' => 'Special:ChangeEmail',
'toolbar' => 'Edit page toolbar',
'edit' => 'Edit pages',
'parserwarnings' => 'Parser/template warnings',
@@ -3522,6 +3694,8 @@ XHTML id names.",
'upload' => 'Upload',
'zip' => 'ZipDirectoryReader',
'upload-errors' => '',
+ 'filebackend-errors' => 'File backend',
+ 'lockmanager-errors' => 'Lock manager',
'uploadstash' => 'Special:UploadStash',
'img-auth' => 'img_auth script messages',
'http-errors' => 'HTTP errors',
@@ -3579,6 +3753,7 @@ XHTML id names.",
'thumbnails' => 'Thumbnails',
'import' => 'Special:Import',
'importlog' => 'Import log',
+ 'javaccripttest' => 'JavaScriptTest',
'accesskeys' => 'Keyboard access keys for power users',
'tooltips' => 'Tooltip help for the actions',
'stylesheets' => 'Stylesheets',
@@ -3605,6 +3780,7 @@ Variants for Chinese language",
'variantname-ku' => 'Variants for Kurdish language',
'variantname-tg' => 'Variants for Tajiki language',
'variantname-iu' => 'Variants for Inuktitut language',
+ 'variantname-shi' => 'Variants for Tachelhit language',
'media-info' => 'Media information',
'metadata' => 'Metadata',
'exif' => 'EXIF tags',
@@ -3657,7 +3833,6 @@ Variants for Chinese language",
'all' => "'all' in various places, this might be different for inflected languages",
'confirmemail' => 'E-mail address confirmation',
'scarytransclusion' => 'Scary transclusion',
- 'trackbacks' => 'Trackbacks',
'deleteconflict' => 'Delete conflict',
'unit-pixel' => '',
'purge' => 'action=purge',
@@ -3668,6 +3843,7 @@ Variants for Chinese language",
'autosumm' => 'Auto-summaries',
'autoblock_whitelist' => 'Autoblock whitelist',
'sizeunits' => 'Size units',
+ 'bitrateunits' => 'Bitrate units',
'livepreview' => 'Live preview',
'lagwarning' => 'Friendlier slave lag warnings',
'watchlisteditor' => 'Watchlist editor',
@@ -3688,5 +3864,7 @@ Variants for Chinese language",
'db-error-messages' => 'Database error messages',
'html-forms' => 'HTML forms',
'sqlite' => 'SQLite database support',
- 'ajax-category' => 'Add categories per AJAX',
+ 'logging' => 'New logging system',
+ 'feedback' => 'Feedback',
+ 'apierrors' => 'API errors',
);
diff --git a/maintenance/language/transstat.php b/maintenance/language/transstat.php
index a3213266..fb08b7d0 100644
--- a/maintenance/language/transstat.php
+++ b/maintenance/language/transstat.php
@@ -21,7 +21,7 @@
* @ingroup MaintenanceLanguage
*
* @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @author Ashar Voultoiz <hashar at free dot fr>
+ * @author Antoine Musso <hashar at free dot fr>
*
* Output is posted from time to time on:
* http://www.mediawiki.org/wiki/Localisation_statistics
@@ -97,7 +97,7 @@ $wgRequiredMessagesNumber = count( $wgGeneralMessages['required'] );
foreach ( $wgLanguages->getLanguages() as $code ) {
# Don't check English, RTL English or dummy language codes
if ( $code == 'en' || $code == 'enRTL' || (is_array( $wgDummyLanguageCodes ) &&
- in_array( $code, $wgDummyLanguageCodes ) ) ) {
+ isset( $wgDummyLanguageCodes[$code] ) ) ) {
continue;
}
diff --git a/maintenance/language/writeMessagesArray.inc b/maintenance/language/writeMessagesArray.inc
index 093359ca..524c2ba6 100644
--- a/maintenance/language/writeMessagesArray.inc
+++ b/maintenance/language/writeMessagesArray.inc
@@ -106,6 +106,9 @@ class MessageWriter {
# Sort messages to blocks
$sortedMessages['unknown'] = $messages;
foreach( self::$messageStructure as $blockName => $block ) {
+ /**
+ * @var $block array
+ */
foreach( $block as $key ) {
if( array_key_exists( $key, $sortedMessages['unknown'] ) ) {
$sortedMessages[$blockName][$key] = $sortedMessages['unknown'][$key];
diff --git a/maintenance/locking/LockServerDaemon.php b/maintenance/locking/LockServerDaemon.php
new file mode 100644
index 00000000..1a4a928e
--- /dev/null
+++ b/maintenance/locking/LockServerDaemon.php
@@ -0,0 +1,617 @@
+<?php
+/**
+ * @file
+ * @ingroup LockManager Maintenance
+ */
+
+/**
+ * This code should not require MediaWiki setup or PHP files.
+ */
+if ( php_sapi_name() !== 'cli' ) {
+ die( "This is not a valid entry point.\n" );
+}
+error_reporting( E_ALL );
+
+// Run the server...
+set_time_limit( 0 );
+LockServerDaemon::init(
+ getopt( '', array(
+ 'address:', 'port:', 'authKey:',
+ 'lockTimeout::', 'maxClients::', 'maxBacklog::', 'maxLocks::',
+ ) )
+)->main();
+
+/**
+ * Simple lock server daemon that accepts lock/unlock requests
+ */
+class LockServerDaemon {
+ /** @var resource */
+ protected $sock; // socket to listen/accept on
+ /** @var Array */
+ protected $sessions = array(); // (session => resource)
+ /** @var Array */
+ protected $deadSessions = array(); // (session => UNIX timestamp)
+
+ /** @var LockHolder */
+ protected $lockHolder;
+
+ protected $address; // string IP address
+ protected $port; // integer
+ protected $authKey; // string key
+ protected $lockTimeout; // integer number of seconds
+ protected $maxBacklog; // integer
+ protected $maxClients; // integer
+
+ protected $startTime; // integer UNIX timestamp
+ protected $ticks = 0; // integer counter
+
+ /* @var LockServerDaemon */
+ protected static $instance = null;
+
+ /**
+ * @params $config Array
+ * @return LockServerDaemon
+ */
+ public static function init( array $config ) {
+ if ( self::$instance ) {
+ throw new Exception( 'LockServer already initialized.' );
+ }
+ foreach ( array( 'address', 'port', 'authKey' ) as $par ) {
+ if ( !isset( $config[$par] ) ) {
+ die( "Usage: php LockServerDaemon.php " .
+ "--address <address> --port <port> --authkey <key> " .
+ "[--lockTimeout <seconds>] " .
+ "[--maxLocks <integer>] [--maxClients <integer>] [--maxBacklog <integer>]"
+ );
+ }
+ }
+ self::$instance = new self( $config );
+ return self::$instance;
+ }
+
+ /**
+ * @params $config Array
+ */
+ protected function __construct( array $config ) {
+ // Required parameters...
+ $this->address = $config['address'];
+ $this->port = $config['port'];
+ $this->authKey = $config['authKey'];
+ // Parameters with defaults...
+ $this->lockTimeout = isset( $config['lockTimeout'] )
+ ? (int)$config['lockTimeout']
+ : 60;
+ $this->maxClients = isset( $config['maxClients'] )
+ ? (int)$config['maxClients']
+ : 1000; // less than default FD_SETSIZE
+ $this->maxBacklog = isset( $config['maxBacklog'] )
+ ? (int)$config['maxBacklog']
+ : 100;
+ $maxLocks = isset( $config['maxLocks'] )
+ ? (int)$config['maxLocks']
+ : 10000;
+
+ $this->lockHolder = new LockHolder( $maxLocks );
+ }
+
+ /**
+ * @return void
+ */
+ protected function setupServerSocket() {
+ if ( !function_exists( 'socket_create' ) ) {
+ throw new Exception( "PHP sockets extension missing from PHP CLI mode." );
+ }
+ $sock = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
+ if ( $sock === false ) {
+ throw new Exception( "socket_create(): " . socket_strerror( socket_last_error() ) );
+ }
+ socket_set_option( $sock, SOL_SOCKET, SO_REUSEADDR, 1 ); // bypass 2MLS
+ socket_set_nonblock( $sock ); // don't block on accept()
+ if ( socket_bind( $sock, $this->address, $this->port ) === false ) {
+ throw new Exception( "socket_bind(): " .
+ socket_strerror( socket_last_error( $sock ) ) );
+ } elseif ( socket_listen( $sock, $this->maxBacklog ) === false ) {
+ throw new Exception( "socket_listen(): " .
+ socket_strerror( socket_last_error( $sock ) ) );
+ }
+ $this->sock = $sock;
+ $this->startTime = time();
+ }
+
+ /**
+ * Entry-point function that listens to the server socket, accepts
+ * new clients, and recieves/responds to requests to lock resources.
+ */
+ public function main() {
+ $this->setupServerSocket(); // setup listening socket
+ $socketArray = new SocketArray(); // sockets being serviced
+ $socketArray->addSocket( $this->sock ); // add listening socket
+ do {
+ list( $read, $write ) = $socketArray->socketsForSelect();
+ if ( socket_select( $read, $write, $except = NULL, NULL ) < 1 ) {
+ continue; // wait
+ }
+ // Check if there is a client trying to connect...
+ if ( in_array( $this->sock, $read ) && $socketArray->size() < $this->maxClients ) {
+ $newSock = socket_accept( $this->sock );
+ if ( $newSock ) {
+ socket_set_option( $newSock, SOL_SOCKET, SO_KEEPALIVE, 1 );
+ socket_set_nonblock( $newSock ); // don't block on read()/write()
+ $socketArray->addSocket( $newSock );
+ }
+ }
+ // Loop through all the clients that have data to read...
+ foreach ( $read as $read_sock ) {
+ if ( $read_sock === $this->sock ) {
+ continue; // skip listening socket
+ }
+ // Avoids PHP_NORMAL_READ per https://bugs.php.net/bug.php?id=33471
+ $data = socket_read( $read_sock, 65535 );
+ // Check if the client is disconnected
+ if ( $data === false || $data === '' ) {
+ $socketArray->closeSocket( $read_sock );
+ $this->recordDeadSocket( $read_sock ); // remove session
+ // Check if we reached the end of a message
+ } elseif ( substr( $data, -1 ) === "\n" ) {
+ // Newline is the last char (given ping-pong message usage)
+ $cmd = $socketArray->readRcvBuffer( $read_sock ) . $data;
+ // Perform the requested command...
+ $response = $this->doCommand( rtrim( $cmd ), $read_sock );
+ // Send the response to the client...
+ $socketArray->appendSndBuffer( $read_sock, $response . "\n" );
+ // Otherwise, we just have more message data to append
+ } elseif ( !$socketArray->appendRcvBuffer( $read_sock, $data ) ) {
+ $socketArray->closeSocket( $read_sock ); // too big
+ $this->recordDeadSocket( $read_sock ); // remove session
+ }
+ }
+ // Loop through all the clients that have data to write...
+ foreach ( $write as $write_sock ) {
+ $bytes = socket_write( $write_sock, $socketArray->readSndBuffer( $write_sock ) );
+ // Check if the client is disconnected
+ if ( $bytes === false ) {
+ $socketArray->closeSocket( $write_sock );
+ $this->recordDeadSocket( $write_sock ); // remove session
+ // Otherwise, truncate these bytes from the start of the write buffer
+ } else {
+ $socketArray->consumeSndBuffer( $write_sock, $bytes );
+ }
+ }
+ // Prune dead locks every few socket events...
+ if ( ++$this->ticks >= 9 ) {
+ $this->ticks = 0;
+ $this->purgeExpiredLocks();
+ }
+ } while ( true );
+ }
+
+ /**
+ * @param $data string
+ * @param $sourceSock resource
+ * @return string
+ */
+ protected function doCommand( $data, $sourceSock ) {
+ $cmdArr = $this->getCommand( $data );
+ if ( is_string( $cmdArr ) ) {
+ return $cmdArr; // error
+ }
+ list( $function, $session, $type, $resources ) = $cmdArr;
+ // On first command, track the session => sock correspondence
+ if ( !isset( $this->sessions[$session] ) ) {
+ $this->sessions[$session] = $sourceSock;
+ unset( $this->deadSessions[$session] ); // renew if dead
+ }
+ if ( $function === 'ACQUIRE' ) {
+ return $this->lockHolder->lock( $session, $type, $resources );
+ } elseif ( $function === 'RELEASE' ) {
+ return $this->lockHolder->unlock( $session, $type, $resources );
+ } elseif ( $function === 'RELEASE_ALL' ) {
+ return $this->lockHolder->release( $session );
+ } elseif ( $function === 'STAT' ) {
+ return $this->stat();
+ }
+ return 'INTERNAL_ERROR';
+ }
+
+ /**
+ * @param $data string
+ * @return Array
+ */
+ protected function getCommand( $data ) {
+ $m = explode( ':', $data ); // <session, key, command, type, values>
+ if ( count( $m ) == 5 ) {
+ list( $session, $key, $command, $type, $values ) = $m;
+ if ( sha1( $session . $command . $type . $values . $this->authKey ) !== $key ) {
+ return 'BAD_KEY';
+ } elseif ( strlen( $session ) !== 31 ) {
+ return 'BAD_SESSION';
+ }
+ $values = explode( '|', $values );
+ if ( $command === 'ACQUIRE' ) {
+ $needsLockArgs = true;
+ } elseif ( $command === 'RELEASE' ) {
+ $needsLockArgs = true;
+ } elseif ( $command === 'RELEASE_ALL' ) {
+ $needsLockArgs = false;
+ } elseif ( $command === 'STAT' ) {
+ $needsLockArgs = false;
+ } else {
+ return 'BAD_COMMAND';
+ }
+ if ( $needsLockArgs ) {
+ if ( $type !== 'SH' && $type !== 'EX' ) {
+ return 'BAD_TYPE';
+ }
+ foreach ( $values as $value ) {
+ if ( strlen( $value ) !== 31 ) {
+ return 'BAD_FORMAT';
+ }
+ }
+ }
+ return array( $command, $session, $type, $values );
+ }
+ return 'BAD_FORMAT';
+ }
+
+ /**
+ * Remove a socket's corresponding session from tracking and
+ * store it in the dead session tracking if it still has locks.
+ *
+ * @param $socket resource
+ * @return book
+ */
+ protected function recordDeadSocket( $socket ) {
+ $session = array_search( $socket, $this->sessions );
+ if ( $session !== false ) {
+ unset( $this->sessions[$session] );
+ // Record recently killed sessions that still have locks
+ if ( $this->lockHolder->sessionHasLocks( $session ) ) {
+ $this->deadSessions[$session] = time();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Clear locks for sessions that have been dead for a while
+ *
+ * @return integer Number of sessions purged
+ */
+ protected function purgeExpiredLocks() {
+ $count = 0;
+ $now = time();
+ foreach ( $this->deadSessions as $session => $timestamp ) {
+ if ( ( $now - $timestamp ) > $this->lockTimeout ) {
+ $this->lockHolder->release( $session );
+ unset( $this->deadSessions[$session] );
+ ++$count;
+ }
+ }
+ return $count;
+ }
+
+ /**
+ * Get the current timestamp and memory usage
+ *
+ * @return string
+ */
+ protected function stat() {
+ return ( time() - $this->startTime ) . ':' . memory_get_usage();
+ }
+}
+
+/**
+ * LockServerDaemon helper class that keeps track socket states
+ */
+class SocketArray {
+ /* @var Array */
+ protected $clients = array(); // array of client sockets
+ /* @var Array */
+ protected $rBuffers = array(); // corresponding socket read buffers
+ /* @var Array */
+ protected $wBuffers = array(); // corresponding socket write buffers
+
+ const BUFFER_SIZE = 65535;
+
+ /**
+ * @return Array (list of sockets to read, list of sockets to write)
+ */
+ public function socketsForSelect() {
+ $rSockets = array();
+ $wSockets = array();
+ foreach ( $this->clients as $key => $socket ) {
+ if ( $this->wBuffers[$key] !== '' ) {
+ $wSockets[] = $socket; // wait for writing to unblock
+ } else {
+ $rSockets[] = $socket; // wait for reading to unblock
+ }
+ }
+ return array( $rSockets, $wSockets );
+ }
+
+ /**
+ * @return integer Number of client sockets
+ */
+ public function size() {
+ return count( $this->clients );
+ }
+
+ /**
+ * @param $sock resource
+ * @return bool
+ */
+ public function addSocket( $sock ) {
+ $this->clients[] = $sock;
+ $this->rBuffers[] = '';
+ $this->wBuffers[] = '';
+ return true;
+ }
+
+ /**
+ * @param $sock resource
+ * @return bool
+ */
+ public function closeSocket( $sock ) {
+ $key = array_search( $sock, $this->clients );
+ if ( $key === false ) {
+ return false;
+ }
+ socket_close( $sock );
+ unset( $this->clients[$key] );
+ unset( $this->rBuffers[$key] );
+ unset( $this->wBuffers[$key] );
+ return true;
+ }
+
+ /**
+ * @param $sock resource
+ * @param $data string
+ * @return bool
+ */
+ public function appendRcvBuffer( $sock, $data ) {
+ $key = array_search( $sock, $this->clients );
+ if ( $key === false ) {
+ return false;
+ } elseif ( ( strlen( $this->rBuffers[$key] ) + strlen( $data ) ) > self::BUFFER_SIZE ) {
+ return false;
+ }
+ $this->rBuffers[$key] .= $data;
+ return true;
+ }
+
+ /**
+ * @param $sock resource
+ * @return string|false
+ */
+ public function readRcvBuffer( $sock ) {
+ $key = array_search( $sock, $this->clients );
+ if ( $key === false ) {
+ return false;
+ }
+ $data = $this->rBuffers[$key];
+ $this->rBuffers[$key] = ''; // consume data
+ return $data;
+ }
+
+ /**
+ * @param $sock resource
+ * @param $data string
+ * @return bool
+ */
+ public function appendSndBuffer( $sock, $data ) {
+ $key = array_search( $sock, $this->clients );
+ if ( $key === false ) {
+ return false;
+ } elseif ( ( strlen( $this->wBuffers[$key] ) + strlen( $data ) ) > self::BUFFER_SIZE ) {
+ return false;
+ }
+ $this->wBuffers[$key] .= $data;
+ return true;
+ }
+
+ /**
+ * @param $sock resource
+ * @return bool
+ */
+ public function readSndBuffer( $sock ) {
+ $key = array_search( $sock, $this->clients );
+ if ( $key === false ) {
+ return false;
+ }
+ return $this->wBuffers[$key];
+ }
+
+ /**
+ * @param $sock resource
+ * @param $bytes integer
+ * @return bool
+ */
+ public function consumeSndBuffer( $sock, $bytes ) {
+ $key = array_search( $sock, $this->clients );
+ if ( $key === false ) {
+ return false;
+ }
+ $this->wBuffers[$key] = (string)substr( $this->wBuffers[$key], $bytes );
+ return true;
+ }
+}
+
+/**
+ * LockServerDaemon helper class that keeps track of the locks
+ */
+class LockHolder {
+ /** @var Array */
+ protected $shLocks = array(); // (key => session => 1)
+ /** @var Array */
+ protected $exLocks = array(); // (key => session)
+
+ /** @var Array */
+ protected $sessionIndexSh = array(); // (session => key => 1)
+ /** @var Array */
+ protected $sessionIndexEx = array(); // (session => key => 1)
+ protected $lockCount = 0; // integer
+
+ protected $maxLocks; // integer
+
+ /**
+ * @params $maxLocks integer Maximum number of locks to allow
+ */
+ public function __construct( $maxLocks ) {
+ $this->maxLocks = $maxLocks;
+ }
+
+ /**
+ * @param $session string
+ * @return bool
+ */
+ public function sessionHasLocks( $session ) {
+ return isset( $this->sessionIndexSh[$session] )
+ || isset( $this->sessionIndexEx[$session] );
+ }
+
+ /**
+ * @param $session string
+ * @param $type string
+ * @param $keys Array
+ * @return string
+ */
+ public function lock( $session, $type, array $keys ) {
+ if ( ( $this->lockCount + count( $keys ) ) > $this->maxLocks ) {
+ return 'TOO_MANY_LOCKS';
+ }
+ if ( $type === 'SH' ) {
+ // Check if any keys are already write-locked...
+ foreach ( $keys as $key ) {
+ if ( isset( $this->exLocks[$key] ) && $this->exLocks[$key] !== $session ) {
+ return 'CANT_ACQUIRE';
+ }
+ }
+ // Acquire the read-locks...
+ foreach ( $keys as $key ) {
+ $this->set_sh_lock( $key, $session );
+ }
+ return 'ACQUIRED';
+ } elseif ( $type === 'EX' ) {
+ // Check if any keys are already read-locked or write-locked...
+ foreach ( $keys as $key ) {
+ if ( isset( $this->exLocks[$key] ) && $this->exLocks[$key] !== $session ) {
+ return 'CANT_ACQUIRE';
+ }
+ if ( isset( $this->shLocks[$key] ) ) {
+ foreach ( $this->shLocks[$key] as $otherSession => $x ) {
+ if ( $otherSession !== $session ) {
+ return 'CANT_ACQUIRE';
+ }
+ }
+ }
+ }
+ // Acquire the write-locks...
+ foreach ( $keys as $key ) {
+ $this->set_ex_lock( $key, $session );
+ }
+ return 'ACQUIRED';
+ }
+ return 'INTERNAL_ERROR';
+ }
+
+ /**
+ * @param $session string
+ * @param $type string
+ * @param $keys Array
+ * @return string
+ */
+ public function unlock( $session, $type, array $keys ) {
+ if ( $type === 'SH' ) {
+ foreach ( $keys as $key ) {
+ $this->unset_sh_lock( $key, $session );
+ }
+ return 'RELEASED';
+ } elseif ( $type === 'EX' ) {
+ foreach ( $keys as $key ) {
+ $this->unset_ex_lock( $key, $session );
+ }
+ return 'RELEASED';
+ }
+ return 'INTERNAL_ERROR';
+ }
+
+ /**
+ * @param $session string
+ * @return string
+ */
+ public function release( $session ) {
+ if ( isset( $this->sessionIndexSh[$session] ) ) {
+ foreach ( $this->sessionIndexSh[$session] as $key => $x ) {
+ $this->unset_sh_lock( $key, $session );
+ }
+ }
+ if ( isset( $this->sessionIndexEx[$session] ) ) {
+ foreach ( $this->sessionIndexEx[$session] as $key => $x ) {
+ $this->unset_ex_lock( $key, $session );
+ }
+ }
+ return 'RELEASED_ALL';
+ }
+
+ /**
+ * @param $key string
+ * @param $session string
+ * @return void
+ */
+ protected function set_sh_lock( $key, $session ) {
+ if ( !isset( $this->shLocks[$key][$session] ) ) {
+ $this->shLocks[$key][$session] = 1;
+ $this->sessionIndexSh[$session][$key] = 1;
+ ++$this->lockCount; // we are adding a lock
+ }
+ }
+
+ /**
+ * @param $key string
+ * @param $session string
+ * @return void
+ */
+ protected function set_ex_lock( $key, $session ) {
+ if ( !isset( $this->exLocks[$key][$session] ) ) {
+ $this->exLocks[$key] = $session;
+ $this->sessionIndexEx[$session][$key] = 1;
+ ++$this->lockCount; // we are adding a lock
+ }
+ }
+
+ /**
+ * @param $key string
+ * @param $session string
+ * @return void
+ */
+ protected function unset_sh_lock( $key, $session ) {
+ if ( isset( $this->shLocks[$key][$session] ) ) {
+ unset( $this->shLocks[$key][$session] );
+ if ( !count( $this->shLocks[$key] ) ) {
+ unset( $this->shLocks[$key] );
+ }
+ unset( $this->sessionIndexSh[$session][$key] );
+ if ( !count( $this->sessionIndexSh[$session] ) ) {
+ unset( $this->sessionIndexSh[$session] );
+ }
+ --$this->lockCount;
+ }
+ }
+
+ /**
+ * @param $key string
+ * @param $session string
+ * @return void
+ */
+ protected function unset_ex_lock( $key, $session ) {
+ if ( isset( $this->exLocks[$key] ) && $this->exLocks[$key] === $session ) {
+ unset( $this->exLocks[$key] );
+ unset( $this->sessionIndexEx[$session][$key] );
+ if ( !count( $this->sessionIndexEx[$session] ) ) {
+ unset( $this->sessionIndexEx[$session] );
+ }
+ --$this->lockCount;
+ }
+ }
+}
diff --git a/maintenance/locking/file_locks.sql b/maintenance/locking/file_locks.sql
new file mode 100644
index 00000000..f51d06b3
--- /dev/null
+++ b/maintenance/locking/file_locks.sql
@@ -0,0 +1,11 @@
+-- Table to handle resource locking (EX) with row-level locking
+CREATE TABLE /*_*/filelocks_exclusive (
+ fle_key binary(31) NOT NULL PRIMARY KEY
+) ENGINE=InnoDB, CHECKSUM=0;
+
+-- Table to handle resource locking (SH) with row-level locking
+CREATE TABLE /*_*/filelocks_shared (
+ fls_key binary(31) NOT NULL,
+ fls_session binary(31) NOT NULL,
+ PRIMARY KEY (fls_key,fls_session)
+) ENGINE=InnoDB, CHECKSUM=0;
diff --git a/maintenance/mctest.php b/maintenance/mctest.php
index 651b2958..359cd248 100644
--- a/maintenance/mctest.php
+++ b/maintenance/mctest.php
@@ -29,15 +29,16 @@ class mcTest extends Maintenance {
$this->mDescription = "Makes several 'set', 'incr' and 'get' requests on every"
. " memcached server and shows a report";
$this->addOption( 'i', 'Number of iterations', false, true );
- $this->addArg( 'server', 'Memcached server to test', false );
+ $this->addArg( 'server[:port]', 'Memcached server to test, with optional port', false );
}
public function execute() {
global $wgMemCachedServers;
$iterations = $this->getOption( 'i', 100 );
- if ( $this->hasArg() )
+ if ( $this->hasArg() ) {
$wgMemCachedServers = array( $this->getArg() );
+ }
foreach ( $wgMemCachedServers as $server ) {
$this->output( $server . " ", $server );
diff --git a/maintenance/mergeMessageFileList.php b/maintenance/mergeMessageFileList.php
index 8cfefcbd..b5a911aa 100644
--- a/maintenance/mergeMessageFileList.php
+++ b/maintenance/mergeMessageFileList.php
@@ -26,25 +26,18 @@
define( 'MW_NO_EXTENSION_MESSAGES', 1 );
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
-$maintClass = 'MergeMessageFileList';
-$mmfl = false;
+
class MergeMessageFileList extends Maintenance {
function __construct() {
parent::__construct();
- $this->addOption( 'list-file', 'A file containing a list of extension setup files, one per line.', false, true );
+ $this->addOption( 'list-file', 'A file containing a list of extension setup files, one per line.', true, true );
$this->addOption( 'output', 'Send output to this file (omit for stdout)', false, true );
$this->mDescription = 'Merge $wgExtensionMessagesFiles from various extensions to produce a ' .
'single array containing all message files.';
}
public function execute() {
- global $mmfl;
- if ( !$this->hasOption( 'list-file' ) ) {
- $this->error( 'The --list-file option must be specified.' );
- return;
- }
-
$lines = file( $this->getOption( 'list-file' ) );
if ( $lines === false ) {
$this->error( 'Unable to open list file.' );
@@ -53,43 +46,43 @@ class MergeMessageFileList extends Maintenance {
if ( $this->hasOption( 'output' ) ) {
$mmfl['output'] = $this->getOption( 'output' );
}
- }
-}
-
-require_once( RUN_MAINTENANCE_IF_MAIN );
-foreach ( $mmfl['setupFiles'] as $fileName ) {
- if ( strval( $fileName ) === '' ) {
- continue;
- }
- $fileName = str_replace( '$IP', $IP, $fileName );
- fwrite( STDERR, "Loading data from $fileName\n" );
- include_once( $fileName );
-}
-fwrite( STDERR, "\n" );
-$s =
- "<" . "?php\n" .
- "## This file is generated by mergeMessageFileList.php. Do not edit it directly.\n\n" .
- "if ( defined( 'MW_NO_EXTENSION_MESSAGES' ) ) return;\n\n" .
- '$wgExtensionMessagesFiles = ' . var_export( $wgExtensionMessagesFiles, true ) . ";\n\n" .
- '$wgExtensionAliasesFiles = ' . var_export( $wgExtensionAliasesFiles, true ) . ";\n";
+ global $IP, $wgExtensionMessagesFiles;
+ foreach ( $mmfl['setupFiles'] as $fileName ) {
+ if ( strval( $fileName ) === '' ) {
+ continue;
+ }
+ $fileName = str_replace( '$IP', $IP, $fileName );
+ fwrite( STDERR, "Loading data from $fileName\n" );
+ include_once( $fileName );
+ }
+ fwrite( STDERR, "\n" );
+ $s =
+ "<" . "?php\n" .
+ "## This file is generated by mergeMessageFileList.php. Do not edit it directly.\n\n" .
+ "if ( defined( 'MW_NO_EXTENSION_MESSAGES' ) ) return;\n\n" .
+ '$wgExtensionMessagesFiles = ' . var_export( $wgExtensionMessagesFiles, true ) . ";\n";
-$dirs = array(
- $IP,
- dirname( dirname( __FILE__ ) ),
- realpath( $IP )
-);
+ $dirs = array(
+ $IP,
+ dirname( dirname( __FILE__ ) ),
+ realpath( $IP )
+ );
-foreach ( $dirs as $dir ) {
- $s = preg_replace(
- "/'" . preg_quote( $dir, '/' ) . "([^']*)'/",
- '"$IP\1"',
- $s );
-}
+ foreach ( $dirs as $dir ) {
+ $s = preg_replace(
+ "/'" . preg_quote( $dir, '/' ) . "([^']*)'/",
+ '"$IP\1"',
+ $s );
+ }
-if ( isset( $mmfl['output'] ) ) {
- file_put_contents( $mmfl['output'], $s );
-} else {
- echo $s;
+ if ( isset( $mmfl['output'] ) ) {
+ file_put_contents( $mmfl['output'], $s );
+ } else {
+ echo $s;
+ }
+ }
}
+$maintClass = 'MergeMessageFileList';
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/moveBatch.php b/maintenance/moveBatch.php
index 9b9f9105..6ecc775e 100644
--- a/maintenance/moveBatch.php
+++ b/maintenance/moveBatch.php
@@ -67,6 +67,9 @@ class MoveBatch extends Maintenance {
$this->error( "Unable to read file, exiting", true );
}
$wgUser = User::newFromName( $user );
+ if ( !$wgUser ) {
+ $this->error( "Invalid username", true );
+ }
# Setup complete, now start
$dbw = wfGetDB( DB_MASTER );
diff --git a/maintenance/mssql/tables.sql b/maintenance/mssql/tables.sql
index dca64f17..8c4d5008 100644
--- a/maintenance/mssql/tables.sql
+++ b/maintenance/mssql/tables.sql
@@ -642,16 +642,6 @@ CREATE UNIQUE INDEX /*$wgDBprefix*/ls_field_val ON /*$wgDBprefix*/log_search (ls
CREATE INDEX /*$wgDBprefix*/ls_log_id ON /*$wgDBprefix*/log_search (ls_log_id);
-CREATE TABLE /*$wgDBprefix*/trackbacks (
- tb_id INT PRIMARY KEY,
- tb_page INT REFERENCES /*$wgDBprefix*/page(page_id) ON DELETE CASCADE,
- tb_title NVARCHAR(255) NOT NULL,
- tb_url NVARCHAR(255) NOT NULL,
- tb_ex NVARCHAR(MAX),
- tb_name NVARCHAR(255),
-);
-CREATE INDEX /*$wgDBprefix*/trackbacks_page ON /*$wgDBprefix*/trackbacks(tb_page);
-
-- Jobs performed by parallel apache threads or a command-line daemon
CREATE TABLE /*$wgDBprefix*/job (
job_id INT NOT NULL PRIMARY KEY,
diff --git a/maintenance/mwdocgen.php b/maintenance/mwdocgen.php
index ed511f74..0c3b262e 100644
--- a/maintenance/mwdocgen.php
+++ b/maintenance/mwdocgen.php
@@ -33,7 +33,7 @@
* @todo document
* @ingroup Maintenance
*
- * @author Ashar Voultoiz <hashar at free dot fr>
+ * @author Antoine Musso <hashar at free dot fr>
* @author Brion Vibber
* @author Alexandre Emsenhuber
* @version first release
@@ -89,6 +89,7 @@ require_once( "$mwPath/includes/GlobalFunctions.php" );
/**
* Read a line from the shell
* @param $prompt String
+ * @return string
*/
function readaline( $prompt = '' ) {
print $prompt;
@@ -151,9 +152,12 @@ function getSvnRevision( $dir ) {
* @param $exclude String: Additionals path regex to exclude
* @param $exclude_patterns String: Additionals path regex to exclude
* (LocalSettings.php, AdminSettings.php, .svn and .git directories are always excluded)
+ * @return string
*/
function generateConfigFile( $doxygenTemplate, $outputDirectory, $stripFromPath, $currentVersion, $svnstat, $input, $exclude, $exclude_patterns ) {
+ global $wgDoxyGenerateMan;
+
$template = file_get_contents( $doxygenTemplate );
// Replace template placeholders by correct values.
@@ -166,6 +170,7 @@ function generateConfigFile( $doxygenTemplate, $outputDirectory, $stripFromPath,
'{{EXCLUDE}}' => $exclude,
'{{EXCLUDE_PATTERNS}}' => $exclude_patterns,
'{{HAVE_DOT}}' => `which dot` ? 'YES' : 'NO',
+ '{{GENERATE_MAN}}' => $wgDoxyGenerateMan ? 'YES' : 'NO',
);
$tmpCfg = str_replace( array_keys( $replacements ), array_values( $replacements ), $template );
$tmpFileName = tempnam( wfTempDir(), 'mwdocgen-' );
@@ -180,20 +185,56 @@ function generateConfigFile( $doxygenTemplate, $outputDirectory, $stripFromPath,
unset( $file );
-if ( is_array( $argv ) && isset( $argv[1] ) ) {
- switch( $argv[1] ) {
- case '--all': $input = 0; break;
- case '--includes': $input = 1; break;
- case '--languages': $input = 2; break;
- case '--maintenance': $input = 3; break;
- case '--skins': $input = 4; break;
- case '--file':
- $input = 5;
- if ( isset( $argv[2] ) ) {
- $file = $argv[2];
+if ( is_array( $argv ) ) {
+ for ($i = 0; $i < count($argv); $i++ ) {
+ switch( $argv[$i] ) {
+ case '--all': $input = 0; break;
+ case '--includes': $input = 1; break;
+ case '--languages': $input = 2; break;
+ case '--maintenance': $input = 3; break;
+ case '--skins': $input = 4; break;
+ case '--file':
+ $input = 5;
+ $i++;
+ if ( isset( $argv[$i] ) ) {
+ $file = $argv[$i];
+ }
+ break;
+ case '--no-extensions': $input = 6; break;
+ case '--output':
+ $i++;
+ if ( isset( $argv[$i] ) ) {
+ $doxyOutput = realpath( $argv[$i] );
+ }
+ break;
+ case '--generate-man':
+ $wgDoxyGenerateMan = true;
+ break;
+ case '--help':
+ print <<<END
+Usage: php mwdocgen.php [<command>] [<options>]
+
+Commands:
+ --all Process entire codebase
+ --includes Process only files in includes/ dir
+ --languages Process only files in languages/ dir
+ --maintenance Process only files in maintenance/ dir
+ --skins Process only files in skins/ dir
+ --file <file> Process only the given file
+ --no-extensions Process everything but extensions directorys
+
+If no command is given, you will be prompted.
+
+Other options:
+ --output <dir> Set output directory (default $doxyOutput)
+ --generate-man Generates man page documentation
+ --help Show this help and exit.
+
+
+END;
+ exit(0);
+ break;
}
- break;
- case '--no-extensions': $input = 6; break;
}
}
diff --git a/maintenance/namespaceDupes.php b/maintenance/namespaceDupes.php
index b883ea68..0a5fec33 100644
--- a/maintenance/namespaceDupes.php
+++ b/maintenance/namespaceDupes.php
@@ -26,6 +26,12 @@
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
class NamespaceConflictChecker extends Maintenance {
+
+ /**
+ * @var DatabaseBase
+ */
+ protected $db;
+
public function __construct() {
parent::__construct();
$this->mDescription = "";
@@ -64,6 +70,8 @@ class NamespaceConflictChecker extends Maintenance {
* @todo Document
* @param $fix Boolean: whether or not to fix broken entries
* @param $suffix String: suffix to append to renamed articles
+ *
+ * @return bool
*/
private function checkAll( $fix, $suffix = '' ) {
global $wgContLang, $wgNamespaceAliases, $wgCapitalLinks;
@@ -150,6 +158,7 @@ class NamespaceConflictChecker extends Maintenance {
* @param $name String
* @param $fix Boolean: whether to fix broken entries
* @param $suffix String: suffix to append to renamed articles
+ * @return bool
*/
private function checkNamespace( $ns, $name, $fix, $suffix = '' ) {
$conflicts = $this->getConflicts( $ns, $name );
@@ -171,6 +180,11 @@ class NamespaceConflictChecker extends Maintenance {
/**
* @todo: do this for reals
+ * @param $key
+ * @param $prefix
+ * @param $fix
+ * @param $suffix string
+ * @return bool
*/
private function checkPrefix( $key, $prefix, $fix, $suffix = '' ) {
$this->output( "Checking prefix \"$prefix\" vs namespace $key\n" );
@@ -183,6 +197,8 @@ class NamespaceConflictChecker extends Maintenance {
*
* @param $ns Integer: namespace id (id for new namespace?)
* @param $name String: prefix that is being made a namespace
+ *
+ * @return array
*/
private function getConflicts( $ns, $name ) {
$page = 'page';
@@ -217,6 +233,8 @@ class NamespaceConflictChecker extends Maintenance {
/**
* Report any conflicts we find
+ *
+ * @return bool
*/
private function reportConflict( $row, $suffix ) {
$newTitle = Title::makeTitleSafe( $row->namespace, $row->title );
@@ -254,6 +272,7 @@ class NamespaceConflictChecker extends Maintenance {
* @param $row Object: row from the page table to fix
* @param $resolvable Boolean
* @param $suffix String: suffix to append to the fixed page
+ * @return bool
*/
private function resolveConflict( $row, $resolvable, $suffix ) {
if ( !$resolvable ) {
@@ -285,6 +304,7 @@ class NamespaceConflictChecker extends Maintenance {
* @param $row Object: row from the old broken entry
* @param $table String: table to update
* @param $prefix String: prefix for column name, like page or ar
+ * @return bool
*/
private function resolveConflictOn( $row, $table, $prefix ) {
$this->output( "... resolving on $table... " );
diff --git a/maintenance/nextJobDB.php b/maintenance/nextJobDB.php
index 2d3608d5..67aa3088 100644
--- a/maintenance/nextJobDB.php
+++ b/maintenance/nextJobDB.php
@@ -37,7 +37,7 @@ class nextJobDB extends Maintenance {
$memcKey = 'jobqueue:dbs:v2';
$pendingDBs = $wgMemc->get( $memcKey );
- // If the cache entry wasn't present, or in 1% of cases otherwise,
+ // If the cache entry wasn't present, or in 1% of cases otherwise,
// regenerate the cache.
if ( !$pendingDBs || mt_rand( 0, 100 ) == 0 ) {
$pendingDBs = $this->getPendingDbs();
@@ -65,7 +65,7 @@ class nextJobDB extends Maintenance {
$candidates = array_values( $candidates );
$db = $candidates[ mt_rand( 0, count( $candidates ) - 1 ) ];
if ( !$this->checkJob( $type, $db ) ) {
- // This job is not available in the current database. Remove it from
+ // This job is not available in the current database. Remove it from
// the cache.
if ( $type === false ) {
foreach ( $pendingDBs as $type2 => $dbs ) {
@@ -85,7 +85,10 @@ class nextJobDB extends Maintenance {
/**
* Check if the specified database has a job of the specified type in it.
- * The type may be false to indicate "all".
+ * The type may be false to indicate "all".
+ * @param $type string
+ * @param $dbName string
+ * @return bool
*/
function checkJob( $type, $dbName ) {
$lb = wfGetLB( $dbName );
@@ -103,7 +106,6 @@ class nextJobDB extends Maintenance {
/**
* Get all databases that have a pending job
- * @param $type String Job type
* @return array
*/
private function getPendingDbs() {
diff --git a/maintenance/nukeNS.php b/maintenance/nukeNS.php
index c89fa94b..57417508 100644
--- a/maintenance/nukeNS.php
+++ b/maintenance/nukeNS.php
@@ -41,11 +41,13 @@ class NukeNS extends Maintenance {
$this->mDescription = "Remove pages with only 1 revision from any namespace";
$this->addOption( 'delete', "Actually delete the page" );
$this->addOption( 'ns', 'Namespace to delete from, default NS_MEDIAWIKI', false, true );
+ $this->addOption( 'all', 'Delete everything regardless of revision count' );
}
public function execute() {
$ns = $this->getOption( 'ns', NS_MEDIAWIKI );
$delete = $this->getOption( 'delete', false );
+ $all = $this->getOption( 'all', false );
$dbw = wfGetDB( DB_MASTER );
$dbw->begin();
@@ -70,7 +72,7 @@ class NukeNS extends Maintenance {
$count = count( $revs );
// skip anything that looks modified (i.e. multiple revs)
- if ( $count == 1 ) {
+ if ( $all || $count == 1 ) {
# echo $title->getPrefixedText(), "\t", $count, "\n";
$this->output( "delete: " . $title->getPrefixedText() . "\n" );
@@ -80,7 +82,7 @@ class NukeNS extends Maintenance {
$dbw->query( "DELETE FROM $tbl_pag WHERE page_id = $id" );
$dbw->commit();
// Delete revisions as appropriate
- $child = $this->runChild( 'NukePage', 'NukePage.php' );
+ $child = $this->runChild( 'NukePage', 'nukePage.php' );
$child->deleteRevisions( $revs );
$this->purgeRedundantText( true );
$n_deleted ++;
diff --git a/maintenance/oracle/archives/patch-ar_sha1_field.sql b/maintenance/oracle/archives/patch-ar_sha1_field.sql
new file mode 100644
index 00000000..de723ce7
--- /dev/null
+++ b/maintenance/oracle/archives/patch-ar_sha1_field.sql
@@ -0,0 +1,3 @@
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.archive ADD ar_sha1 VARCHAR2(32);
diff --git a/maintenance/oracle/archives/patch-config.sql b/maintenance/oracle/archives/patch-config.sql
deleted file mode 100644
index 66714a73..00000000
--- a/maintenance/oracle/archives/patch-config.sql
+++ /dev/null
@@ -1,8 +0,0 @@
-define mw_prefix='{$wgDBprefix}';
-
-CREATE TABLE &mw_prefix.config (
- cf_name VARCHAR2(255) NOT NULL,
- cf_value blob NOT NULL
-);
-ALTER TABLE &mw_prefix.config ADD CONSTRAINT &mw_prefix.config_pk PRIMARY KEY (cf_name);
-
diff --git a/maintenance/oracle/archives/patch-job_timestamp_field.sql b/maintenance/oracle/archives/patch-job_timestamp_field.sql
new file mode 100644
index 00000000..4901c87c
--- /dev/null
+++ b/maintenance/oracle/archives/patch-job_timestamp_field.sql
@@ -0,0 +1,4 @@
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.job ADD job_timestamp TIMESTAMP(6) WITH TIME ZONE NULL;
+
diff --git a/maintenance/oracle/archives/patch-job_timestamp_index.sql b/maintenance/oracle/archives/patch-job_timestamp_index.sql
new file mode 100644
index 00000000..6db43046
--- /dev/null
+++ b/maintenance/oracle/archives/patch-job_timestamp_index.sql
@@ -0,0 +1,4 @@
+define mw_prefix='{$wgDBprefix}';
+
+CREATE INDEX &mw_prefix.job_i02 ON &mw_prefix.job (job_timestamp);
+
diff --git a/maintenance/oracle/archives/patch-logging_type_action_index.sql b/maintenance/oracle/archives/patch-logging_type_action_index.sql
new file mode 100644
index 00000000..d30e0cfc
--- /dev/null
+++ b/maintenance/oracle/archives/patch-logging_type_action_index.sql
@@ -0,0 +1,4 @@
+define mw_prefix='{$wgDBprefix}';
+
+CREATE INDEX &mw_prefix.logging_i05 ON &mw_prefix.logging (log_type, log_action, log_timestamp);
+
diff --git a/maintenance/oracle/archives/patch-page_redirect_namespace_len.sql b/maintenance/oracle/archives/patch-page_redirect_namespace_len.sql
new file mode 100644
index 00000000..1f8b9d9a
--- /dev/null
+++ b/maintenance/oracle/archives/patch-page_redirect_namespace_len.sql
@@ -0,0 +1,4 @@
+define mw_prefix='{$wgDBprefix}';
+
+CREATE INDEX &mw_prefix.page_i03 ON &mw_prefix.page (page_is_redirect, page_namespace, page_len);
+
diff --git a/maintenance/oracle/archives/patch-rev_sha1_field.sql b/maintenance/oracle/archives/patch-rev_sha1_field.sql
new file mode 100644
index 00000000..80544e89
--- /dev/null
+++ b/maintenance/oracle/archives/patch-rev_sha1_field.sql
@@ -0,0 +1,4 @@
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.revision ADD rev_sha1 VARCHAR2(32);
+
diff --git a/maintenance/oracle/archives/patch-ug_group-length-increase.sql b/maintenance/oracle/archives/patch-ug_group-length-increase.sql
new file mode 100644
index 00000000..00a3d0c9
--- /dev/null
+++ b/maintenance/oracle/archives/patch-ug_group-length-increase.sql
@@ -0,0 +1,3 @@
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.user_groups MODIFY ug_group VARCHAR2(32) NOT NULL;
diff --git a/maintenance/oracle/archives/patch-us_chunk_inx_field.sql b/maintenance/oracle/archives/patch-us_chunk_inx_field.sql
new file mode 100644
index 00000000..43ee16ec
--- /dev/null
+++ b/maintenance/oracle/archives/patch-us_chunk_inx_field.sql
@@ -0,0 +1,4 @@
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.uploadstash ADD us_chunk_inx NUMBER;
+
diff --git a/maintenance/oracle/archives/patch_fk_rename_deferred.sql b/maintenance/oracle/archives/patch_fk_rename_deferred.sql
index ce5be9af..ca9c997f 100644
--- a/maintenance/oracle/archives/patch_fk_rename_deferred.sql
+++ b/maintenance/oracle/archives/patch_fk_rename_deferred.sql
@@ -35,7 +35,6 @@ ALTER TABLE &mw_prefix.recentchanges ADD CONSTRAINT &mw_prefix.recentchanges_fk1
ALTER TABLE &mw_prefix.recentchanges ADD CONSTRAINT &mw_prefix.recentchanges_fk2 FOREIGN KEY (rc_cur_id) REFERENCES &mw_prefix.page(page_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE &mw_prefix.watchlist ADD CONSTRAINT &mw_prefix.watchlist_fk1 FOREIGN KEY (wl_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE &mw_prefix.logging ADD CONSTRAINT &mw_prefix.logging_fk1 FOREIGN KEY (log_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
-ALTER TABLE &mw_prefix.trackbacks ADD CONSTRAINT &mw_prefix.trackbacks_fk1 FOREIGN KEY (tb_page) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE &mw_prefix.redirect ADD CONSTRAINT &mw_prefix.redirect_fk1 FOREIGN KEY (rd_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE &mw_prefix.page_restrictions ADD CONSTRAINT &mw_prefix.page_restrictions_fk1 FOREIGN KEY (pr_page) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
diff --git a/maintenance/oracle/archives/patch_rebuild_dupfunc.sql b/maintenance/oracle/archives/patch_rebuild_dupfunc.sql
index 0a232dbc..56ee5b3e 100644
--- a/maintenance/oracle/archives/patch_rebuild_dupfunc.sql
+++ b/maintenance/oracle/archives/patch_rebuild_dupfunc.sql
@@ -10,7 +10,7 @@ CREATE OR REPLACE PROCEDURE duplicate_table(p_tabname IN VARCHAR2,
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || p_newprefix || p_tabname ||
- ' CASCADE CONSTRAINTS';
+ ' CASCADE CONSTRAINTS PURGE';
EXCEPTION
WHEN e_table_not_exist THEN
NULL;
@@ -20,8 +20,9 @@ BEGIN
END IF;
IF (l_temporary) THEN
EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE ' || p_newprefix ||
- p_tabname || ' AS SELECT * FROM ' || p_oldprefix ||
- p_tabname || ' WHERE ROWNUM = 0';
+ p_tabname ||
+ ' ON COMMIT PRESERVE ROWS AS SELECT * FROM ' ||
+ p_oldprefix || p_tabname || ' WHERE ROWNUM = 0';
ELSE
EXECUTE IMMEDIATE 'CREATE TABLE ' || p_newprefix || p_tabname ||
' AS SELECT * FROM ' || p_oldprefix || p_tabname ||
@@ -68,7 +69,8 @@ BEGIN
FROM user_constraints uc
WHERE table_name = p_oldprefix || p_tabname
AND constraint_type = 'R') LOOP
- IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
+ IF nvl(length(l_temp_ei_sql), 0) > 0 AND
+ INSTR(l_temp_ei_sql, 'PRIMARY KEY') = 0 THEN
EXECUTE IMMEDIATE l_temp_ei_sql;
END IF;
END LOOP;
@@ -142,5 +144,6 @@ BEGIN
END IF;
END LOOP;
END;
+
/*$mw$*/
diff --git a/maintenance/oracle/archives/patch_remove_not_null_empty_defs2.sql b/maintenance/oracle/archives/patch_remove_not_null_empty_defs2.sql
new file mode 100644
index 00000000..f7a38a05
--- /dev/null
+++ b/maintenance/oracle/archives/patch_remove_not_null_empty_defs2.sql
@@ -0,0 +1,3 @@
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.ipblocks MODIFY ipb_by_text DEFAULT NULL NULL;
diff --git a/maintenance/oracle/tables.sql b/maintenance/oracle/tables.sql
index c6162753..9f875aed 100644
--- a/maintenance/oracle/tables.sql
+++ b/maintenance/oracle/tables.sql
@@ -31,12 +31,19 @@ INSERT INTO &mw_prefix.mwuser
CREATE TABLE &mw_prefix.user_groups (
ug_user NUMBER DEFAULT 0 NOT NULL,
- ug_group VARCHAR2(16) NOT NULL
+ ug_group VARCHAR2(32) NOT NULL
);
ALTER TABLE &mw_prefix.user_groups ADD CONSTRAINT &mw_prefix.user_groups_fk1 FOREIGN KEY (ug_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
CREATE UNIQUE INDEX &mw_prefix.user_groups_u01 ON &mw_prefix.user_groups (ug_user,ug_group);
CREATE INDEX &mw_prefix.user_groups_i01 ON &mw_prefix.user_groups (ug_group);
+CREATE TABLE &mw_prefix.user_former_groups (
+ ufg_user NUMBER DEFAULT 0 NOT NULL,
+ ufg_group VARCHAR2(16) NOT NULL
+);
+ALTER TABLE &mw_prefix.user_former_groups ADD CONSTRAINT &mw_prefix.user_former_groups_fk1 FOREIGN KEY (ufg_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+CREATE UNIQUE INDEX &mw_prefix.user_former_groups_u01 ON &mw_prefix.user_former_groups (ufg_user,ufg_group);
+
CREATE TABLE &mw_prefix.user_newtalk (
user_id NUMBER DEFAULT 0 NOT NULL,
user_ip VARCHAR2(40) NULL,
@@ -72,6 +79,7 @@ ALTER TABLE &mw_prefix.page ADD CONSTRAINT &mw_prefix.page_pk PRIMARY KEY (page_
CREATE UNIQUE INDEX &mw_prefix.page_u01 ON &mw_prefix.page (page_namespace,page_title);
CREATE INDEX &mw_prefix.page_i01 ON &mw_prefix.page (page_random);
CREATE INDEX &mw_prefix.page_i02 ON &mw_prefix.page (page_len);
+CREATE INDEX &mw_prefix.page_i03 ON &mw_prefix.page (page_is_redirect, page_namespace, page_len);
-- Create a dummy page to satisfy fk contraints especially with revisions
INSERT INTO &mw_prefix.page
@@ -97,7 +105,8 @@ CREATE TABLE &mw_prefix.revision (
rev_minor_edit CHAR(1) DEFAULT '0' NOT NULL,
rev_deleted CHAR(1) DEFAULT '0' NOT NULL,
rev_len NUMBER NULL,
- rev_parent_id NUMBER DEFAULT NULL
+ rev_parent_id NUMBER DEFAULT NULL,
+ rev_sha1 VARCHAR2(32) NULL
);
ALTER TABLE &mw_prefix.revision ADD CONSTRAINT &mw_prefix.revision_pk PRIMARY KEY (rev_id);
ALTER TABLE &mw_prefix.revision ADD CONSTRAINT &mw_prefix.revision_fk1 FOREIGN KEY (rev_page) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
@@ -131,7 +140,8 @@ CREATE TABLE &mw_prefix.archive (
ar_deleted CHAR(1) DEFAULT '0' NOT NULL,
ar_len NUMBER,
ar_page_id NUMBER,
- ar_parent_id NUMBER
+ ar_parent_id NUMBER,
+ ar_sha1 VARCHAR2(32) NULL
);
ALTER TABLE &mw_prefix.archive ADD CONSTRAINT &mw_prefix.archive_fk1 FOREIGN KEY (ar_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX &mw_prefix.archive_i01 ON &mw_prefix.archive (ar_namespace,ar_title,ar_timestamp);
@@ -250,7 +260,7 @@ CREATE TABLE &mw_prefix.ipblocks (
ipb_address VARCHAR2(255) NULL,
ipb_user NUMBER DEFAULT 0 NOT NULL,
ipb_by NUMBER DEFAULT 0 NOT NULL,
- ipb_by_text VARCHAR2(255) NOT NULL,
+ ipb_by_text VARCHAR2(255) NULL,
ipb_reason VARCHAR2(255) NOT NULL,
ipb_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL,
ipb_auto CHAR(1) DEFAULT '0' NOT NULL,
@@ -355,6 +365,31 @@ CREATE INDEX &mw_prefix.filearchive_i02 ON &mw_prefix.filearchive (fa_storage_gr
CREATE INDEX &mw_prefix.filearchive_i03 ON &mw_prefix.filearchive (fa_deleted_timestamp);
CREATE INDEX &mw_prefix.filearchive_i04 ON &mw_prefix.filearchive (fa_user_text,fa_timestamp);
+CREATE SEQUENCE uploadstash_us_id_seq;
+CREATE TABLE &mw_prefix.uploadstash (
+ us_id NUMBER NOT NULL,
+ us_user NUMBER DEFAULT 0 NOT NULL,
+ us_key VARCHAR2(255) NOT NULL,
+ us_orig_path VARCHAR2(255) NOT NULL,
+ us_path VARCHAR2(255) NOT NULL,
+ us_source_type VARCHAR2(50),
+ us_timestamp TIMESTAMP(6) WITH TIME ZONE,
+ us_status VARCHAR2(50) NOT NULL,
+ us_chunk_inx NUMBER,
+ us_size NUMBER NOT NULL,
+ us_sha1 VARCHAR2(32) NOT NULL,
+ us_mime VARCHAR2(255),
+ us_media_type VARCHAR2(32) DEFAULT NULL,
+ us_image_width NUMBER,
+ us_image_height NUMBER,
+ us_image_bits NUMBER
+);
+ALTER TABLE &mw_prefix.uploadstash ADD CONSTRAINT &mw_prefix.uploadstash_pk PRIMARY KEY (us_id);
+ALTER TABLE &mw_prefix.uploadstash ADD CONSTRAINT &mw_prefix.uploadstash_fk1 FOREIGN KEY (us_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
+CREATE INDEX &mw_prefix.uploadstash_i01 ON &mw_prefix.uploadstash (us_user);
+CREATE INDEX &mw_prefix.uploadstash_i02 ON &mw_prefix.uploadstash (us_timestamp);
+CREATE UNIQUE INDEX &mw_prefix.uploadstash_u01 ON &mw_prefix.uploadstash (us_key);
+
CREATE SEQUENCE recentchanges_rc_id_seq;
CREATE TABLE &mw_prefix.recentchanges (
rc_id NUMBER NOT NULL,
@@ -467,6 +502,7 @@ CREATE INDEX &mw_prefix.logging_i01 ON &mw_prefix.logging (log_type, log_timesta
CREATE INDEX &mw_prefix.logging_i02 ON &mw_prefix.logging (log_user, log_timestamp);
CREATE INDEX &mw_prefix.logging_i03 ON &mw_prefix.logging (log_namespace, log_title, log_timestamp);
CREATE INDEX &mw_prefix.logging_i04 ON &mw_prefix.logging (log_timestamp);
+CREATE INDEX &mw_prefix.logging_i05 ON &mw_prefix.logging (log_type, log_action, log_timestamp);
CREATE TABLE &mw_prefix.log_search (
ls_field VARCHAR2(32) NOT NULL,
@@ -476,18 +512,6 @@ CREATE TABLE &mw_prefix.log_search (
ALTER TABLE &mw_prefix.log_search ADD CONSTRAINT log_search_pk PRIMARY KEY (ls_field,ls_value,ls_log_id);
CREATE INDEX &mw_prefix.log_search_i01 ON &mw_prefix.log_search (ls_log_id);
-CREATE SEQUENCE trackbacks_tb_id_seq;
-CREATE TABLE &mw_prefix.trackbacks (
- tb_id NUMBER NOT NULL,
- tb_page NUMBER,
- tb_title VARCHAR2(255) NOT NULL,
- tb_url VARCHAR2(255) NOT NULL,
- tb_ex CLOB,
- tb_name VARCHAR2(255)
-);
-ALTER TABLE &mw_prefix.trackbacks ADD CONSTRAINT &mw_prefix.trackbacks_pk PRIMARY KEY (tb_id);
-ALTER TABLE &mw_prefix.trackbacks ADD CONSTRAINT &mw_prefix.trackbacks_fk1 FOREIGN KEY (tb_page) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
-CREATE INDEX &mw_prefix.trackbacks_i01 ON &mw_prefix.trackbacks (tb_page);
CREATE SEQUENCE job_job_id_seq;
CREATE TABLE &mw_prefix.job (
@@ -495,10 +519,12 @@ CREATE TABLE &mw_prefix.job (
job_cmd VARCHAR2(60) NOT NULL,
job_namespace NUMBER DEFAULT 0 NOT NULL,
job_title VARCHAR2(255) NOT NULL,
+ job_timestamp TIMESTAMP(6) WITH TIME ZONE NULL,
job_params CLOB NOT NULL
);
ALTER TABLE &mw_prefix.job ADD CONSTRAINT &mw_prefix.job_pk PRIMARY KEY (job_id);
CREATE INDEX &mw_prefix.job_i01 ON &mw_prefix.job (job_cmd, job_namespace, job_title);
+CREATE INDEX &mw_prefix.job_i02 ON &mw_prefix.job (job_timestamp);
CREATE TABLE &mw_prefix.querycache_info (
qci_type VARCHAR2(32) NOT NULL,
@@ -642,8 +668,7 @@ CREATE TABLE &mw_prefix.config (
cf_value blob NOT NULL
);
ALTER TABLE &mw_prefix.config ADD CONSTRAINT &mw_prefix.config_pk PRIMARY KEY (cf_name);
--- leaving index out for now ...
-
+-- leaving index out for now ...
-- do not prefix this table as it breaks parserTests
CREATE TABLE wiki_field_info_full (
@@ -653,9 +678,9 @@ data_default VARCHAR2(4000),
data_length NUMBER NOT NULL,
data_type VARCHAR2(106),
not_null CHAR(1) NOT NULL,
-prim NUMBER(1),
+prim NUMBER(1),
uniq NUMBER(1),
-nonuniq NUMBER(1)
+nonuniq NUMBER(1)
);
ALTER TABLE wiki_field_info_full ADD CONSTRAINT wiki_field_info_full_pk PRIMARY KEY (table_name, column_name);
@@ -722,7 +747,7 @@ CREATE OR REPLACE PROCEDURE duplicate_table(p_tabname IN VARCHAR2,
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || p_newprefix || p_tabname ||
- ' CASCADE CONSTRAINTS';
+ ' CASCADE CONSTRAINTS PURGE';
EXCEPTION
WHEN e_table_not_exist THEN
NULL;
@@ -732,8 +757,9 @@ BEGIN
END IF;
IF (l_temporary) THEN
EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE ' || p_newprefix ||
- p_tabname || ' AS SELECT * FROM ' || p_oldprefix ||
- p_tabname || ' WHERE ROWNUM = 0';
+ p_tabname ||
+ ' ON COMMIT PRESERVE ROWS AS SELECT * FROM ' ||
+ p_oldprefix || p_tabname || ' WHERE ROWNUM = 0';
ELSE
EXECUTE IMMEDIATE 'CREATE TABLE ' || p_newprefix || p_tabname ||
' AS SELECT * FROM ' || p_oldprefix || p_tabname ||
@@ -780,7 +806,8 @@ BEGIN
FROM user_constraints uc
WHERE table_name = p_oldprefix || p_tabname
AND constraint_type = 'R') LOOP
- IF nvl(length(l_temp_ei_sql), 0) > 0 THEN
+ IF nvl(length(l_temp_ei_sql), 0) > 0 AND
+ INSTR(l_temp_ei_sql, 'PRIMARY KEY') = 0 THEN
EXECUTE IMMEDIATE l_temp_ei_sql;
END IF;
END LOOP;
diff --git a/maintenance/orphans.php b/maintenance/orphans.php
index 1986ff35..faaadd37 100644
--- a/maintenance/orphans.php
+++ b/maintenance/orphans.php
@@ -53,10 +53,11 @@ class Orphans extends Maintenance {
* @param $db DatabaseBase object
* @param $extraTable String The name of any extra tables to lock (eg: text)
*/
- private function lockTables( &$db, $extraTable = null ) {
+ private function lockTables( $db, $extraTable = array() ) {
$tbls = array( 'page', 'revision', 'redirect' );
- if ( $extraTable )
- $tbls[] = $extraTable;
+ if ( $extraTable ) {
+ $tbls = array_merge( $tbls, $extraTable );
+ }
$db->lockTables( array(), $tbls, __METHOD__, false );
}
@@ -167,7 +168,7 @@ class Orphans extends Maintenance {
$revision = $dbw->tableName( 'revision' );
if ( $fix ) {
- $dbw->lockTables( $dbw, 'text', __METHOD__ );
+ $this->lockTables( $dbw, array( 'user', 'text' ) );
}
$this->output( "\nChecking for pages whose page_latest links are incorrect... (this may take a while on a large wiki)\n" );
@@ -206,7 +207,7 @@ class Orphans extends Maintenance {
$this->output( "... updating to revision $maxId\n" );
$maxRev = Revision::newFromId( $maxId );
$title = Title::makeTitle( $row->page_namespace, $row->page_title );
- $article = new Article( $title );
+ $article = WikiPage::factory( $title );
$article->updateRevisionOn( $dbw, $maxRev );
}
}
diff --git a/maintenance/ourusers.php b/maintenance/ourusers.php
deleted file mode 100644
index c8578e24..00000000
--- a/maintenance/ourusers.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-/**
- * Wikimedia specific
- *
- * This script generates SQL used to update MySQL users on a hardcoded
- * list of hosts. It takes care of setting the wikiuser for every
- * database as well as setting up wikiadmin.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @todo document
- * @file
- * @ingroup Maintenance
- * @ingroup Wikimedia
- */
-
-/** */
-$wikiuser_pass = `wikiuser_pass`;
-$wikiadmin_pass = `wikiadmin_pass`;
-$nagios_pass = `nagios_sql_pass`;
-
-$hosts = array(
- 'localhost',
- '10.0.%',
- '66.230.200.%',
- '208.80.152.%',
-);
-
-$databases = array(
- '%wik%',
- 'centralauth',
-);
-
-print "/*!40100 set old_passwords=1 */;\n";
-print "/*!40100 set global old_passwords=1 */;\n";
-
-foreach ( $hosts as $host ) {
- print "--\n-- $host\n--\n";
- print "\n-- wikiuser\n\n";
- print "GRANT REPLICATION CLIENT,PROCESS ON *.* TO 'wikiuser'@'$host' IDENTIFIED BY '$wikiuser_pass';\n";
- print "GRANT ALL PRIVILEGES ON `boardvote%`.* TO 'wikiuser'@'$host' IDENTIFIED BY '$wikiuser_pass';\n";
- foreach ( $databases as $db ) {
- print "GRANT SELECT, INSERT, UPDATE, DELETE ON `$db`.* TO 'wikiuser'@'$host' IDENTIFIED BY '$wikiuser_pass';\n";
- }
-
- 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";
- foreach ( $databases as $db ) {
- print "GRANT ALL PRIVILEGES ON `$db`.* TO wikiadmin@'$host' IDENTIFIED BY '$wikiadmin_pass';\n";
- }
- print "\n-- nagios\n\n";
- print "GRANT REPLICATION CLIENT ON *.* TO 'nagios'@'$host' IDENTIFIED BY '$nagios_pass';\n";
-
- print "\n";
-}
-
diff --git a/maintenance/parse.php b/maintenance/parse.php
new file mode 100644
index 00000000..876f28e9
--- /dev/null
+++ b/maintenance/parse.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * CLI script to easily parse some wikitext.
+ * Wikitext can be given by stdin or using a file. The wikitext will be parsed
+ * using 'CLIParser' as a title. This can be overriden with --title option.
+ *
+ * Example1:
+ * @code
+ * $ php parse.php --title foo
+ * ''[[foo]]''^D
+ * <p><i><strong class="selflink">foo</strong></i>
+ * </p>
+ * @endcode
+ *
+ * Example2:
+ * @code
+ * $ echo "'''bold'''" > /tmp/foo.txt
+ * $ php parse.php /tmp/foo.txt
+ * <p><b>bold</b>
+ * </p>$
+ * @endcode
+ *
+ * Example3:
+ * @code
+ * $ cat /tmp/foo | php parse.php
+ * <p><b>bold</b>
+ * </p>$
+ * @endcode
+ *
+ * @ingroup Maintenance
+ * @author Antoine Musso <hashar at free dot fr>
+ * @license GNU General Public License 2.0 or later
+ */
+require_once( dirname(__FILE__) . '/Maintenance.php' );
+
+class CLIParser extends Maintenance {
+ protected $parser;
+
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Parse a given wikitext";
+ $this->addOption( 'title', 'Title name for the given wikitext (Default: \'CLIParser\')', false, true );
+ $this->addArg( 'file', 'File containing wikitext (Default: stdin)', false );
+ }
+
+ public function execute() {
+ $this->initParser();
+ print $this->render( $this->WikiText() );
+ }
+
+ /**
+ * @param string $wikitext Wikitext to get rendered
+ * @return string HTML Rendering
+ */
+ public function render( $wikitext ) {
+ return $this->parse( $wikitext )->getText();
+ }
+
+ /**
+ * Get wikitext from a the file passed as argument or STDIN
+ * @return string Wikitext
+ */
+ protected function Wikitext() {
+
+ $php_stdin = 'php://stdin';
+ $input_file = $this->getArg( 0, $php_stdin );
+
+ if( $input_file === $php_stdin ) {
+ $this->error( basename(__FILE__) .": warning: reading wikitext from STDIN\n" );
+ }
+
+ return file_get_contents( $input_file );
+ }
+
+ protected function initParser() {
+ global $wgParserConf;
+ $parserClass = $wgParserConf['class'];
+ $this->parser = new $parserClass();
+ }
+
+ /**
+ * Title object to use for CLI parsing.
+ * Default title is 'CLIParser', it can be overriden with the option
+ * --title <Your:Title>
+ *
+ * @return Title object
+ */
+ protected function getTitle( ) {
+ $title =
+ $this->getOption( 'title' )
+ ? $this->getOption( 'title' )
+ : 'CLIParser' ;
+ return Title::newFromText( $title );
+ }
+
+ /**
+ * @param string $wikitext Wikitext to parse
+ * @return ParserOutput
+ */
+ protected function parse( $wikitext ) {
+ return $this->parser->parse(
+ $wikitext
+ , $this->getTitle()
+ , new ParserOptions()
+ );
+ }
+}
+
+$maintClass = "CLIParser";
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/populateCategory.php b/maintenance/populateCategory.php
index 4e9c44c4..0b45493e 100644
--- a/maintenance/populateCategory.php
+++ b/maintenance/populateCategory.php
@@ -22,8 +22,6 @@
* @author Simetrical
*/
-$optionsWithArgs = array( 'begin', 'max-slave-lag', 'throttle' );
-
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
diff --git a/maintenance/populateSha1.php b/maintenance/populateImageSha1.php
index 1ab9109d..4cd2747c 100644
--- a/maintenance/populateSha1.php
+++ b/maintenance/populateImageSha1.php
@@ -22,7 +22,7 @@
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
-class PopulateSha1 extends Maintenance {
+class PopulateImageSha1 extends LoggedUpdateMaintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Populate the img_sha1 field";
@@ -31,26 +31,46 @@ class PopulateSha1 extends Maintenance {
$this->addOption( 'file', 'Fix for a specific file, without File: namespace prefixed', false, true );
}
+ protected function getUpdateKey() {
+ return 'populate img_sha1';
+ }
+
+ protected function updateSkippedMessage() {
+ return 'img_sha1 column of image table already populated.';
+ }
+
public function execute() {
+ if ( $this->getOption( 'file' ) ) {
+ $this->doDBUpdates(); // skip update log checks/saves
+ } else {
+ parent::execute();
+ }
+ }
+
+ public function doDBUpdates() {
$method = $this->getOption( 'method', 'normal' );
$file = $this->getOption( 'file' );
$t = -microtime( true );
$dbw = wfGetDB( DB_MASTER );
if ( $file ) {
- $res = $dbw->selectRow(
+ $res = $dbw->select(
'image',
array( 'img_name' ),
- array( 'img_name' => $dbw->addQuotes( $file ) ),
+ array( 'img_name' => $file ),
__METHOD__
);
if ( !$res ) {
$this->error( "No such file: $file", true );
- return;
+ return false;
}
+ $this->output( "Populating img_sha1 field for specified files\n" );
} else {
- $res = $dbw->select( 'image', array( 'img_name' ), array( 'img_sha1' => '' ), __METHOD__ );
+ $res = $dbw->select( 'image',
+ array( 'img_name' ), array( 'img_sha1' => '' ), __METHOD__ );
+ $this->output( "Populating img_sha1 field\n" );
}
+
$imageTable = $dbw->tableName( 'image' );
if ( $method == 'pipe' ) {
@@ -66,7 +86,7 @@ class PopulateSha1 extends Maintenance {
$numRows = $res->numRows();
$i = 0;
foreach ( $res as $row ) {
- if ( $i % 100 == 0 ) {
+ if ( $i % $this->mBatchSize == 0 ) {
$this->output( sprintf( "Done %d of %d, %5.3f%% \r", $i, $numRows, $i / $numRows * 100 ) );
wfWaitForSlaves();
}
@@ -74,7 +94,7 @@ class PopulateSha1 extends Maintenance {
if ( !$file ) {
continue;
}
- $sha1 = File::sha1Base36( $file->getPath() );
+ $sha1 = $file->getRepo()->getFileSha1( $file->getPath() );
if ( strval( $sha1 ) !== '' ) {
$sql = "UPDATE $imageTable SET img_sha1=" . $dbw->addQuotes( $sha1 ) .
" WHERE img_name=" . $dbw->addQuotes( $row->img_name );
@@ -92,8 +112,10 @@ class PopulateSha1 extends Maintenance {
}
$t += microtime( true );
$this->output( sprintf( "\nDone %d files in %.1f seconds\n", $numRows, $t ) );
+
+ return !$file; // we only updated *some* files, don't log
}
}
-$maintClass = "PopulateSha1";
+$maintClass = "PopulateImageSha1";
require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/populateLogSearch.php b/maintenance/populateLogSearch.php
index f13873cb..e3f6067f 100644
--- a/maintenance/populateLogSearch.php
+++ b/maintenance/populateLogSearch.php
@@ -23,21 +23,28 @@
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
-class PopulateLogSearch extends Maintenance {
-
- const LOG_SEARCH_BATCH_SIZE = 100;
-
+class PopulateLogSearch extends LoggedUpdateMaintenance {
static $tableMap = array( 'rev' => 'revision', 'fa' => 'filearchive', 'oi' => 'oldimage', 'ar' => 'archive' );
public function __construct() {
parent::__construct();
$this->mDescription = "Migrate log params to new table and index for searching";
+ $this->setBatchSize( 100 );
+ }
+
+ protected function getUpdateKey() {
+ return 'populate log_search';
+ }
+
+ protected function updateSkippedMessage() {
+ return 'log_search table already populated.';
}
- public function execute() {
+ protected function doDBUpdates() {
$db = $this->getDB( DB_MASTER );
if ( !$db->tableExists( 'log_search' ) ) {
- $this->error( "log_search does not exist", true );
+ $this->error( "log_search does not exist" );
+ return false;
}
$start = $db->selectField( 'logging', 'MIN(log_id)', false, __FUNCTION__ );
if ( !$start ) {
@@ -47,9 +54,9 @@ class PopulateLogSearch extends Maintenance {
$end = $db->selectField( 'logging', 'MAX(log_id)', false, __FUNCTION__ );
# Do remaining chunk
- $end += self::LOG_SEARCH_BATCH_SIZE - 1;
+ $end += $this->mBatchSize - 1;
$blockStart = $start;
- $blockEnd = $start + self::LOG_SEARCH_BATCH_SIZE - 1;
+ $blockEnd = $start + $this->mBatchSize - 1;
$delTypes = array( 'delete', 'suppress' ); // revisiondelete types
while ( $blockEnd <= $end ) {
@@ -128,23 +135,12 @@ class PopulateLogSearch extends Maintenance {
$log->addRelations( 'target_author_ip', $userIPs, $row->log_id );
}
}
- $blockStart += self::LOG_SEARCH_BATCH_SIZE;
- $blockEnd += self::LOG_SEARCH_BATCH_SIZE;
+ $blockStart += $this->mBatchSize;
+ $blockEnd += $this->mBatchSize;
wfWaitForSlaves();
}
- if ( $db->insert(
- 'updatelog',
- array( 'ul_key' => 'populate log_search' ),
- __FUNCTION__,
- 'IGNORE'
- )
- ) {
- $this->output( "log_search population complete.\n" );
- return true;
- } else {
- $this->output( "Could not insert log_search population row.\n" );
- return false;
- }
+ $this->output( "Done populating log_search table.\n" );
+ return true;
}
}
diff --git a/maintenance/populateLogUsertext.php b/maintenance/populateLogUsertext.php
index e9e6926e..2b0e2d64 100644
--- a/maintenance/populateLogUsertext.php
+++ b/maintenance/populateLogUsertext.php
@@ -25,14 +25,22 @@
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
-class PopulateLogUsertext extends Maintenance {
+class PopulateLogUsertext extends LoggedUpdateMaintenance {
public function __construct() {
parent::__construct();
- $this->mDescription = "Populates the log_user_text";
+ $this->mDescription = "Populates the log_user_text field";
$this->setBatchSize( 100 );
}
- public function execute() {
+ protected function getUpdateKey() {
+ return 'populate log_usertext';
+ }
+
+ protected function updateSkippedMessage() {
+ return 'log_user_text column of logging table already populated.';
+ }
+
+ protected function doDBUpdates() {
$db = $this->getDB( DB_MASTER );
$start = $db->selectField( 'logging', 'MIN(log_id)', false, __METHOD__ );
if ( !$start ) {
@@ -61,19 +69,8 @@ class PopulateLogUsertext extends Maintenance {
$blockEnd += $this->mBatchSize;
wfWaitForSlaves();
}
- if ( $db->insert(
- 'updatelog',
- array( 'ul_key' => 'populate log_usertext' ),
- __METHOD__,
- 'IGNORE'
- )
- ) {
- $this->output( "log_usertext population complete.\n" );
- return true;
- } else {
- $this->output( "Could not insert log_usertext population row.\n" );
- return false;
- }
+ $this->output( "Done populating log_user_text field.\n" );
+ return true;
}
}
diff --git a/maintenance/populateParentId.php b/maintenance/populateParentId.php
index 7cbc267b..14f158c9 100644
--- a/maintenance/populateParentId.php
+++ b/maintenance/populateParentId.php
@@ -1,5 +1,5 @@
<?php
-/*
+/**
* Makes the required database updates for rev_parent_id
* to be of any use. It can be used for some simple tracking
* and to find new page edits by users.
@@ -24,28 +24,32 @@
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
-class PopulateParentId extends Maintenance {
+class PopulateParentId extends LoggedUpdateMaintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Populates rev_parent_id";
- $this->setBatchSize( 200 );
}
- public function execute() {
+ protected function getUpdateKey() {
+ return 'populate rev_parent_id';
+ }
+
+ protected function updateSkippedMessage() {
+ return 'rev_parent_id column of revision table already populated.';
+ }
+
+ protected function doDBUpdates() {
$db = wfGetDB( DB_MASTER );
if ( !$db->tableExists( 'revision' ) ) {
- $this->error( "revision table does not exist", true );
+ $this->error( "revision table does not exist" );
+ return false;
}
$this->output( "Populating rev_parent_id column\n" );
$start = $db->selectField( 'revision', 'MIN(rev_id)', false, __FUNCTION__ );
$end = $db->selectField( 'revision', 'MAX(rev_id)', false, __FUNCTION__ );
if ( is_null( $start ) || is_null( $end ) ) {
- $this->output( "...revision table seems to be empty.\n" );
- $db->insert( 'updatelog',
- array( 'ul_key' => 'populate rev_parent_id' ),
- __METHOD__,
- 'IGNORE' );
- return;
+ $this->output( "...revision table seems to be empty, nothing to do.\n" );
+ return true;
}
# Do remaining chunk
$blockStart = intval( $start );
@@ -100,17 +104,8 @@ class PopulateParentId extends Maintenance {
$blockEnd += $this->mBatchSize;
wfWaitForSlaves();
}
- $logged = $db->insert( 'updatelog',
- array( 'ul_key' => 'populate rev_parent_id' ),
- __METHOD__,
- 'IGNORE' );
- if ( $logged ) {
- $this->output( "rev_parent_id population complete ... {$count} rows [{$changed} changed]\n" );
- return true;
- } else {
- $this->output( "Could not insert rev_parent_id population row.\n" );
- return false;
- }
+ $this->output( "rev_parent_id population complete ... {$count} rows [{$changed} changed]\n" );
+ return true;
}
}
diff --git a/maintenance/populateRevisionLength.php b/maintenance/populateRevisionLength.php
index d020b4cb..6626cbc1 100644
--- a/maintenance/populateRevisionLength.php
+++ b/maintenance/populateRevisionLength.php
@@ -1,5 +1,5 @@
<?php
-/*
+/**
* Populates the rev_len field for old revisions created before MW 1.10.
*
* This program is free software; you can redistribute it and/or modify
@@ -22,29 +22,35 @@
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
-class PopulateRevisionLength extends Maintenance {
+class PopulateRevisionLength extends LoggedUpdateMaintenance {
public function __construct() {
parent::__construct();
- $this->mDescription = "Populates rev_len";
+ $this->mDescription = "Populates the rev_len field";
$this->setBatchSize( 200 );
}
- public function execute() {
+ protected function getUpdateKey() {
+ return 'populate rev_len';
+ }
+
+ protected function updateSkippedMessage() {
+ return 'rev_len column of revision table already populated.';
+ }
+
+ public function doDBUpdates() {
$db = $this->getDB( DB_MASTER );
if ( !$db->tableExists( 'revision' ) ) {
$this->error( "revision table does not exist", true );
}
$this->output( "Populating rev_len column\n" );
- $start = $db->selectField( 'revision', 'MIN(rev_id)', false, __FUNCTION__ );
- $end = $db->selectField( 'revision', 'MAX(rev_id)', false, __FUNCTION__ );
- if ( is_null( $start ) || is_null( $end ) ) {
+
+ $start = $db->selectField( 'revision', 'MIN(rev_id)', false, __METHOD__ );
+ $end = $db->selectField( 'revision', 'MAX(rev_id)', false, __METHOD__ );
+ if ( !$start || !$end ) {
$this->output( "...revision table seems to be empty.\n" );
- $db->insert( 'updatelog',
- array( 'ul_key' => 'populate rev_len' ),
- __METHOD__,
- 'IGNORE' );
- return;
+ return true;
}
+
# Do remaining chunks
$blockStart = intval( $start );
$blockEnd = intval( $start ) + $this->mBatchSize - 1;
@@ -80,17 +86,9 @@ class PopulateRevisionLength extends Maintenance {
$blockEnd += $this->mBatchSize;
wfWaitForSlaves();
}
- $logged = $db->insert( 'updatelog',
- array( 'ul_key' => 'populate rev_len' ),
- __METHOD__,
- 'IGNORE' );
- if ( $logged ) {
- $this->output( "rev_len population complete ... {$count} rows changed ({$missing} missing)\n" );
- return true;
- } else {
- $this->output( "Could not insert rev_len population row.\n" );
- return false;
- }
+
+ $this->output( "rev_len population complete ... {$count} rows changed ({$missing} missing)\n" );
+ return true;
}
}
diff --git a/maintenance/populateRevisionSha1.php b/maintenance/populateRevisionSha1.php
new file mode 100644
index 00000000..55e2a93d
--- /dev/null
+++ b/maintenance/populateRevisionSha1.php
@@ -0,0 +1,185 @@
+<?php
+/**
+ * Fills the rev_sha1 and ar_sha1 columns of revision
+ * and archive tables for revisions created before MW 1.19.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @ingroup Maintenance
+ */
+
+require_once( dirname( __FILE__ ) . '/Maintenance.php' );
+
+class PopulateRevisionSha1 extends LoggedUpdateMaintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Populates the rev_sha1 and ar_sha1 fields";
+ $this->setBatchSize( 200 );
+ }
+
+ protected function getUpdateKey() {
+ return 'populate rev_sha1';
+ }
+
+ protected function doDBUpdates() {
+ $db = $this->getDB( DB_MASTER );
+
+ if ( !$db->tableExists( 'revision' ) ) {
+ $this->error( "revision table does not exist", true );
+ } elseif ( !$db->tableExists( 'archive' ) ) {
+ $this->error( "archive table does not exist", true );
+ }
+
+ $this->output( "Populating rev_sha1 column\n" );
+ $rc = $this->doSha1Updates( 'revision', 'rev_id', 'rev' );
+
+ $this->output( "Populating ar_sha1 column\n" );
+ $ac = $this->doSha1Updates( 'archive', 'ar_rev_id', 'ar' );
+ $this->output( "Populating ar_sha1 column legacy rows\n" );
+ $ac += $this->doSha1LegacyUpdates();
+
+ $this->output( "rev_sha1 and ar_sha1 population complete [$rc revision rows, $ac archive rows].\n" );
+ return true;
+ }
+
+ /**
+ * @param $table string
+ * @param $idCol
+ * @param $prefix string
+ * @return Integer Rows changed
+ */
+ protected function doSha1Updates( $table, $idCol, $prefix ) {
+ $db = $this->getDB( DB_MASTER );
+ $start = $db->selectField( $table, "MIN($idCol)", false, __METHOD__ );
+ $end = $db->selectField( $table, "MAX($idCol)", false, __METHOD__ );
+ if ( !$start || !$end ) {
+ $this->output( "...$table table seems to be empty.\n" );
+ return 0;
+ }
+
+ $count = 0;
+ # Do remaining chunk
+ $end += $this->mBatchSize - 1;
+ $blockStart = $start;
+ $blockEnd = $start + $this->mBatchSize - 1;
+ while ( $blockEnd <= $end ) {
+ $this->output( "...doing $idCol from $blockStart to $blockEnd\n" );
+ $cond = "$idCol BETWEEN $blockStart AND $blockEnd
+ AND $idCol IS NOT NULL AND {$prefix}_sha1 = ''";
+ $res = $db->select( $table, '*', $cond, __METHOD__ );
+
+ $db->begin();
+ foreach ( $res as $row ) {
+ if ( $this->upgradeRow( $row, $table, $idCol, $prefix ) ) {
+ $count++;
+ }
+ }
+ $db->commit();
+
+ $blockStart += $this->mBatchSize;
+ $blockEnd += $this->mBatchSize;
+ wfWaitForSlaves();
+ }
+ return $count;
+ }
+
+ /**
+ * @return int
+ */
+ protected function doSha1LegacyUpdates() {
+ $count = 0;
+ $db = $this->getDB( DB_MASTER );
+ $res = $db->select( 'archive', '*', array( 'ar_rev_id IS NULL' ), __METHOD__ );
+
+ $updateSize = 0;
+ $db->begin();
+ foreach ( $res as $row ) {
+ if ( $this->upgradeLegacyArchiveRow( $row ) ) {
+ ++$count;
+ }
+ if ( ++$updateSize >= 100 ) {
+ $updateSize = 0;
+ $db->commit();
+ $this->output( "Commited row with ar_timestamp={$row->ar_timestamp}\n" );
+ wfWaitForSlaves();
+ $db->begin();
+ }
+ }
+ $db->commit();
+ return $count;
+ }
+
+ /**
+ * @param $row
+ * @param $table
+ * @param $idCol
+ * @param $prefix
+ * @return bool
+ */
+ protected function upgradeRow( $row, $table, $idCol, $prefix ) {
+ $db = $this->getDB( DB_MASTER );
+ if ( $table === 'archive' ) {
+ $rev = Revision::newFromArchiveRow( $row );
+ } else {
+ $rev = new Revision( $row );
+ }
+ $text = $rev->getRawText();
+ if ( !is_string( $text ) ) {
+ # This should not happen, but sometimes does (bug 20757)
+ $this->output( "Text of revision with {$idCol}={$row->$idCol} unavailable!\n" );
+ return false;
+ } else {
+ $db->update( $table,
+ array( "{$prefix}_sha1" => Revision::base36Sha1( $text ) ),
+ array( $idCol => $row->$idCol ),
+ __METHOD__
+ );
+ return true;
+ }
+ }
+
+ /**
+ * @param $row
+ * @return bool
+ */
+ protected function upgradeLegacyArchiveRow( $row ) {
+ $db = $this->getDB( DB_MASTER );
+ $rev = Revision::newFromArchiveRow( $row );
+ $text = $rev->getRawText();
+ if ( !is_string( $text ) ) {
+ # This should not happen, but sometimes does (bug 20757)
+ $this->output( "Text of revision with timestamp {$row->ar_timestamp} unavailable!\n" );
+ return false;
+ } else {
+ # Archive table as no PK, but (NS,title,time) should be near unique.
+ # Any duplicates on those should also have duplicated text anyway.
+ $db->update( 'archive',
+ array( 'ar_sha1' => Revision::base36Sha1( $text ) ),
+ array(
+ 'ar_namespace' => $row->ar_namespace,
+ 'ar_title' => $row->ar_title,
+ 'ar_timestamp' => $row->ar_timestamp,
+ 'ar_len' => $row->ar_len // extra sanity
+ ),
+ __METHOD__
+ );
+ return true;
+ }
+ }
+}
+
+$maintClass = "PopulateRevisionSha1";
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/postgres/mediawiki_mysql2postgres.pl b/maintenance/postgres/mediawiki_mysql2postgres.pl
index 9133477e..8f170abc 100644
--- a/maintenance/postgres/mediawiki_mysql2postgres.pl
+++ b/maintenance/postgres/mediawiki_mysql2postgres.pl
@@ -417,7 +417,6 @@ SELECT setval('page_restrictions_pr_id_seq', 1+coalesce(max(pr_id) ,0),false) F
SELECT setval('recentchanges_rc_id_seq', 1+coalesce(max(rc_id) ,0),false) FROM recentchanges;
SELECT setval('revision_rev_id_seq', 1+coalesce(max(rev_id) ,0),false) FROM revision;
SELECT setval('text_old_id_seq', 1+coalesce(max(old_id) ,0),false) FROM pagecontent;
-SELECT setval('trackbacks_tb_id_seq', 1+coalesce(max(tb_id) ,0),false) FROM trackbacks;
SELECT setval('user_user_id_seq', 1+coalesce(max(user_id),0),false) FROM mwuser;
};
@@ -437,7 +436,6 @@ profiling
objectcache
## Which tables to ignore depending on the version
-VERSION 1.5: trackback
VERSION 1.6: externallinks job templatelinks transcache
VERSION 1.7: filearchive langlinks querycache_info
VERSION 1.9: querycachetwo page_restrictions redirect
diff --git a/maintenance/postgres/tables.sql b/maintenance/postgres/tables.sql
index 9f6b8049..6890df91 100644
--- a/maintenance/postgres/tables.sql
+++ b/maintenance/postgres/tables.sql
@@ -16,7 +16,6 @@ DROP SEQUENCE IF EXISTS page_restrictions_id_seq CASCADE;
DROP SEQUENCE IF EXISTS ipblocks_ipb_id_seq CASCADE;
DROP SEQUENCE IF EXISTS recentchanges_rc_id_seq CASCADE;
DROP SEQUENCE IF EXISTS logging_log_id_seq CASCADE;
-DROP SEQUENCE IF EXISTS trackbacks_tb_id_seq CASCADE;
DROP SEQUENCE IF EXISTS job_job_id_seq CASCADE;
DROP SEQUENCE IF EXISTS category_cat_id_seq CASCADE;
DROP FUNCTION IF EXISTS page_deleted() CASCADE;
@@ -116,7 +115,8 @@ CREATE TABLE revision (
rev_minor_edit SMALLINT NOT NULL DEFAULT 0,
rev_deleted SMALLINT NOT NULL DEFAULT 0,
rev_len INTEGER NULL,
- rev_parent_id INTEGER NULL
+ rev_parent_id INTEGER NULL,
+ rev_sha1 TEXT NOT NULL DEFAULT ''
);
CREATE UNIQUE INDEX revision_unique ON revision (rev_page, rev_id);
CREATE INDEX rev_text_id_idx ON revision (rev_text_id);
@@ -159,6 +159,7 @@ CREATE TABLE archive (
ar_text TEXT, -- technically should be bytea, but not used anymore
ar_page_id INTEGER NULL,
ar_parent_id INTEGER NULL,
+ ar_sha1 TEXT NOT NULL DEFAULT '',
ar_comment TEXT,
ar_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
ar_user_text TEXT NOT NULL,
@@ -358,11 +359,11 @@ CREATE INDEX fa_dupe ON filearchive (fa_storage_group, fa_storage_key);
CREATE INDEX fa_notime ON filearchive (fa_deleted_timestamp);
CREATE INDEX fa_nouser ON filearchive (fa_deleted_user);
-CREATE SEQUENCE us_id_seq;
+CREATE SEQUENCE uploadstash_us_id_seq;
CREATE TYPE media_type AS ENUM ('UNKNOWN','BITMAP','DRAWING','AUDIO','VIDEO','MULTIMEDIA','OFFICE','TEXT','EXECUTABLE','ARCHIVE');
CREATE TABLE uploadstash (
- us_id INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('us_id_seq'),
+ us_id INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('uploadstash_us_id_seq'),
us_user INTEGER,
us_key TEXT,
us_orig_path TEXT,
@@ -370,6 +371,7 @@ CREATE TABLE uploadstash (
us_source_type TEXT,
us_timestamp TIMESTAMPTZ,
us_status TEXT,
+ us_chunk_inx INTEGER NULL,
us_size INTEGER,
us_sha1 TEXT,
us_mime TEXT,
@@ -510,17 +512,6 @@ CREATE TABLE log_search (
);
CREATE INDEX ls_log_id ON log_search (ls_log_id);
-CREATE SEQUENCE trackbacks_tb_id_seq;
-CREATE TABLE trackbacks (
- tb_id INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('trackbacks_tb_id_seq'),
- tb_page INTEGER REFERENCES page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
- tb_title TEXT NOT NULL,
- tb_url TEXT NOT NULL,
- tb_ex TEXT,
- tb_name TEXT
-);
-CREATE INDEX trackback_page ON trackbacks (tb_page);
-
CREATE SEQUENCE job_job_id_seq;
CREATE TABLE job (
@@ -528,9 +519,11 @@ CREATE TABLE job (
job_cmd TEXT NOT NULL,
job_namespace SMALLINT NOT NULL,
job_title TEXT NOT NULL,
+ job_timestamp TIMESTAMPTZ,
job_params TEXT NOT NULL
);
CREATE INDEX job_cmd_namespace_title ON job (job_cmd, job_namespace, job_title);
+CREATE INDEX job_timestamp_idx ON job (job_timestamp);
-- Tsearch2 2 stuff. Will fail if we don't have proper access to the tsearch2 tables
-- Version 8.3 or higher only. Previous versions would need another parmeter for to_tsvector.
diff --git a/maintenance/protect.php b/maintenance/protect.php
index aab84d68..56958ea7 100644
--- a/maintenance/protect.php
+++ b/maintenance/protect.php
@@ -28,8 +28,9 @@ class Protect extends Maintenance {
$this->mDescription = "Protect or unprotect an article from the command line.";
$this->addOption( 'unprotect', 'Removes protection' );
$this->addOption( 'semiprotect', 'Adds semi-protection' );
- $this->addOption( 'u', 'Username to protect with', false, true );
- $this->addOption( 'r', 'Reason for un/protection', false, true );
+ $this->addOption( 'cascade', 'Add cascading protection' );
+ $this->addOption( 'user', 'Username to protect with', false, true, 'u' );
+ $this->addOption( 'reason', 'Reason for un/protection', false, true, 'r' );
$this->addArg( 'title', 'Title to protect', true );
}
@@ -39,6 +40,8 @@ class Protect extends Maintenance {
$userName = $this->getOption( 'u', 'Maintenance script' );
$reason = $this->getOption( 'r', '' );
+ $cascade = $this->hasOption( 'cascade' );
+
$protection = "sysop";
if ( $this->hasOption( 'semiprotect' ) ) {
$protection = "autoconfirmed";
@@ -46,7 +49,11 @@ class Protect extends Maintenance {
$protection = "";
}
- $wgUser = User::newFromName( $userName );
+ $user = User::newFromName( $userName );
+ if ( !$user ) {
+ $this->error( "Invalid username", true );
+ }
+
$restrictions = array( 'edit' => $protection, 'move' => $protection );
$t = Title::newFromText( $this->getArg() );
@@ -54,12 +61,18 @@ class Protect extends Maintenance {
$this->error( "Invalid title", true );
}
- $article = new Article( $t );
+ $restrictions = array();
+ foreach( $t->getRestrictionTypes() as $type ) {
+ $restrictions[$type] = $protection;
+ }
# un/protect the article
$this->output( "Updating protection status... " );
- $success = $article->updateRestrictions( $restrictions, $reason );
- if ( $success ) {
+
+ $page = WikiPage::factory( $t );
+ $status = $page->doUpdateRestrictions( $restrictions, array(), $cascade, $reason, $user );
+
+ if ( $status->isOK() ) {
$this->output( "done\n" );
} else {
$this->output( "failed\n" );
diff --git a/maintenance/proxy_check.php b/maintenance/proxy_check.php
index 2bc46c0d..9c5f32b2 100644
--- a/maintenance/proxy_check.php
+++ b/maintenance/proxy_check.php
@@ -3,6 +3,7 @@
* Command line script to check for an open proxy at a specified location
*
* @file
+ * @ingroup Maintenance
*/
if( php_sapi_name() != 'cli' ) {
diff --git a/maintenance/pruneFileCache.php b/maintenance/pruneFileCache.php
new file mode 100644
index 00000000..f1a1cfd4
--- /dev/null
+++ b/maintenance/pruneFileCache.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Prune file cache for pages, objects, resources, ect...
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @ingroup Maintenance
+ */
+
+require_once( dirname( __FILE__ ) . '/Maintenance.php' );
+
+class PruneFileCache extends Maintenance {
+
+ protected $minSurviveTimestamp;
+
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Build file cache for content pages";
+ $this->addOption( 'agedays', 'How many days old files must be in order to delete', true, true );
+ $this->addOption( 'subdir', 'Prune one $wgFileCacheDirectory subdirectory name', false, true );
+ }
+
+ public function execute() {
+ global $wgUseFileCache, $wgFileCacheDirectory;
+
+ if ( !$wgUseFileCache ) {
+ $this->error( "Nothing to do -- \$wgUseFileCache is disabled.", true );
+ }
+
+ $age = $this->getOption( 'agedays' );
+ if ( !ctype_digit( $age ) ) {
+ $this->error( "Non-integer 'age' parameter given.", true );
+ }
+ // Delete items with a TS older than this
+ $this->minSurviveTimestamp = time() - ( 86400 * $age );
+
+ $dir = $wgFileCacheDirectory;
+ if ( !is_dir( $dir ) ) {
+ $this->error( "Nothing to do -- \$wgFileCacheDirectory directory not found.", true );
+ }
+
+ $subDir = $this->getOption( 'subdir' );
+ if ( $subDir !== null ) {
+ if ( !is_dir( "$dir/$subDir" ) ) {
+ $this->error( "The specified subdirectory `$subDir` does not exist.", true );
+ }
+ $this->output( "Pruning `$dir/$subDir` directory...\n" );
+ $this->prune_directory( "$dir/$subDir", 'report' );
+ $this->output( "Done pruning `$dir/$subDir` directory\n" );
+ } else {
+ $this->output( "Pruning `$dir` directory...\n" );
+ // Note: don't prune things like .cdb files on the top level!
+ $this->prune_directory( $dir, 'report' );
+ $this->output( "Done pruning `$dir` directory\n" );
+ }
+ }
+
+ /**
+ * @param $dir string
+ * @param $report string|bool Use 'report' to report the directories being scanned
+ */
+ protected function prune_directory( $dir, $report = false ) {
+ $tsNow = time();
+ $dirHandle = opendir( $dir );
+ while ( false !== ( $file = readdir( $dirHandle ) ) ) {
+ // Skip ".", "..", and also any dirs or files like ".svn" or ".htaccess"
+ if ( $file[0] != "." ) {
+ $path = $dir . '/' . $file; // absolute
+ if ( is_dir( $path ) ) {
+ if ( $report === 'report' ) {
+ $this->output( "Scanning `$path`...\n" );
+ }
+ $this->prune_directory( $path );
+ } else {
+ $mts = filemtime( $path );
+ // Sanity check the file extension against known cache types
+ if ( $mts < $this->minSurviveTimestamp
+ && preg_match( '/\.(?:html|cache)(?:\.gz)?$/', $file )
+ && unlink( $path ) )
+ {
+ $daysOld = round( ( $tsNow - $mts ) / 86400, 2 );
+ $this->output( "Deleted `$path` [days=$daysOld]\n" );
+ }
+ }
+ }
+ }
+ closedir( $dirHandle );
+ }
+}
+
+$maintClass = "PruneFileCache";
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/purgeDeletedFiles.php b/maintenance/purgeDeletedFiles.php
new file mode 100644
index 00000000..c8d4fc07
--- /dev/null
+++ b/maintenance/purgeDeletedFiles.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Scans the deletion log and purges affected files within a timeframe.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @ingroup Maintenance
+ */
+
+require_once( dirname( __FILE__ ) . '/Maintenance.php' );
+
+class PurgeDeletedFiles extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = "Scan the logging table and purge files that where deleted.";
+ $this->addOption( 'starttime', 'Starting timestamp', false, true );
+ $this->addOption( 'endtime', 'Ending timestamp', false, true );
+ }
+
+ public function execute() {
+ $this->output( "Purging cache and thumbnails for deleted files...\n" );
+ $this->purgeFromLogType( 'delete' );
+ $this->output( "...deleted files purged.\n\n" );
+
+ $this->output( "Purging cache and thumbnails for suppressed files...\n" );
+ $this->purgeFromLogType( 'suppress' );
+ $this->output( "...suppressed files purged.\n" );
+ }
+
+ protected function purgeFromLogType( $logType ) {
+ $repo = RepoGroup::singleton()->getLocalRepo();
+ $db = $repo->getSlaveDB();
+
+ $conds = array(
+ 'log_namespace' => NS_FILE,
+ 'log_type' => $logType,
+ 'log_action' => array( 'delete', 'revision' )
+ );
+ $start = $this->getOption( 'starttime' );
+ if ( $start ) {
+ $conds[] = 'log_timestamp >= ' . $db->addQuotes( $db->timestamp( $start ) );
+ }
+ $end = $this->getOption( 'endtime' );
+ if ( $end ) {
+ $conds[] = 'log_timestamp <= ' . $db->addQuotes( $db->timestamp( $end ) );
+ }
+
+ $res = $db->select( 'logging', array( 'log_title', 'log_timestamp' ), $conds, __METHOD__ );
+ foreach ( $res as $row ) {
+ $file = $repo->newFile( Title::makeTitle( NS_FILE, $row->log_title ) );
+
+ // Purge current version and any versions in oldimage table
+ $file->purgeCache();
+ $file->purgeHistory();
+ // Purge items from fileachive table (rows are likely here)
+ $this->purgeFromArchiveTable( $file );
+
+ $this->output( "Purged file {$row->log_title}; deleted on {$row->log_timestamp}.\n" );
+ }
+ }
+
+ protected function purgeFromArchiveTable( LocalFile $file ) {
+ $db = $file->getRepo()->getSlaveDB();
+ $res = $db->select( 'filearchive',
+ array( 'fa_archive_name' ),
+ array( 'fa_name' => $file->getName() ),
+ __METHOD__
+ );
+ foreach ( $res as $row ) {
+ $file->purgeOldThumbnails( $row->fa_archive_name );
+ }
+ }
+}
+
+$maintClass = "PurgeDeletedFiles";
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/purgeList.php b/maintenance/purgeList.php
index 85a7aae2..f1452bca 100644
--- a/maintenance/purgeList.php
+++ b/maintenance/purgeList.php
@@ -47,7 +47,7 @@ class PurgeList extends Maintenance {
while ( !feof( $stdin ) ) {
$page = trim( fgets( $stdin ) );
- if ( substr( $page, 0, 7 ) == 'http://' ) {
+ if ( preg_match( '%^https?://%', $page ) ) {
$urls[] = $page;
} elseif ( $page !== '' ) {
$title = Title::newFromText( $page );
diff --git a/maintenance/purgeParserCache.php b/maintenance/purgeParserCache.php
index 4b550b6e..4d775f95 100644
--- a/maintenance/purgeParserCache.php
+++ b/maintenance/purgeParserCache.php
@@ -1,8 +1,14 @@
<?php
+/**
+ * @ingroup Maintenance
+ * @file
+ */
require( dirname( __FILE__ ) . '/Maintenance.php' );
class PurgeParserCache extends Maintenance {
+ var $lastProgress;
+
function __construct() {
parent::__construct();
$this->addDescription( "Remove old objects from the parser cache. " .
@@ -31,12 +37,26 @@ class PurgeParserCache extends Maintenance {
echo "Deleting objects expiring before " . $english->timeanddate( $date ) . "\n";
$pc = wfGetParserCacheStorage();
- $success = $pc->deleteObjectsExpiringBefore( $date );
+ $success = $pc->deleteObjectsExpiringBefore( $date, array( $this, 'showProgress' ) );
if ( !$success ) {
- echo "Cannot purge this kind of parser cache.\n";
+ echo "\nCannot purge this kind of parser cache.\n";
exit( 1 );
}
- echo "Done\n";
+ $this->showProgress( 100 );
+ echo "\nDone\n";
+ }
+
+ function showProgress( $percent ) {
+ $percentString = sprintf( "%.2f", $percent );
+ if ( $percentString === $this->lastProgress ) {
+ return;
+ }
+ $this->lastProgress = $percentString;
+
+ $stars = floor( $percent / 2 );
+ echo '[' . str_repeat( '*', $stars ), str_repeat( '.', 50 - $stars ) . '] ' .
+ "$percentString%\r";
+
}
}
$maintClass = 'PurgeParserCache';
diff --git a/maintenance/purgeStaleMemcachedText.php b/maintenance/purgeStaleMemcachedText.php
index c4f5006f..fc9a6a89 100644
--- a/maintenance/purgeStaleMemcachedText.php
+++ b/maintenance/purgeStaleMemcachedText.php
@@ -1,4 +1,8 @@
<?php
+/**
+ * @ingroup Maintenance Memcached
+ * @file
+ */
require_once( dirname( __FILE__ ) . '/commandLine.inc' );
diff --git a/maintenance/reassignEdits.php b/maintenance/reassignEdits.php
index bb34e51c..3830fe38 100644
--- a/maintenance/reassignEdits.php
+++ b/maintenance/reassignEdits.php
@@ -139,8 +139,8 @@ class ReassignEdits extends Maintenance {
* i.e. user => id, user_text => text
*
* @param $user User for the spec
- * @param $idfield Field name containing the identifier
- * @param $utfield Field name containing the user text
+ * @param $idfield string Field name containing the identifier
+ * @param $utfield string Field name containing the user text
* @return array
*/
private function userSpecification( &$user, $idfield, $utfield ) {
@@ -160,6 +160,9 @@ class ReassignEdits extends Maintenance {
$user->setName( $username );
} else {
$user = User::newFromName( $username );
+ if ( !$user ) {
+ $this->error( "Invalid username", true );
+ }
}
$user->load();
return $user;
diff --git a/maintenance/rebuildFileCache.php b/maintenance/rebuildFileCache.php
index 84ada11c..e7ce3521 100644
--- a/maintenance/rebuildFileCache.php
+++ b/maintenance/rebuildFileCache.php
@@ -26,29 +26,52 @@ class RebuildFileCache extends Maintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Build file cache for content pages";
- $this->addArg( 'start', 'Page_id to start from', true );
- $this->addArg( 'overwrite', 'Refresh page cache', false );
+ $this->addOption( 'start', 'Page_id to start from', false, true );
+ $this->addOption( 'end', 'Page_id to end on', false, true );
+ $this->addOption( 'overwrite', 'Refresh page cache' );
$this->setBatchSize( 100 );
}
+ public function finalSetup() {
+ global $wgDebugToolbar;
+
+ // Debug toolbar makes content uncacheable so we disable it.
+ // Has to be done before Setup.php initialize MWDebug
+ $wgDebugToolbar = false;
+ parent::finalSetup();
+ }
+
public function execute() {
- global $wgUseFileCache, $wgDisableCounters, $wgContentNamespaces, $wgRequestTime;
+ global $wgUseFileCache, $wgReadOnly, $wgContentNamespaces, $wgRequestTime;
global $wgTitle, $wgOut;
if ( !$wgUseFileCache ) {
$this->error( "Nothing to do -- \$wgUseFileCache is disabled.", true );
}
- $wgDisableCounters = false;
- $start = $this->getArg( 0, "0" );
+
+ $wgReadOnly = 'Building cache'; // avoid DB writes (like enotif/counters)
+
+ $start = $this->getOption( 'start', "0" );
if ( !ctype_digit( $start ) ) {
$this->error( "Invalid value for start parameter.", true );
}
$start = intval( $start );
- $overwrite = $this->hasArg( 1 ) && $this->getArg( 1 ) === 'overwrite';
+
+ $end = $this->getOption( 'end', "0" );
+ if ( !ctype_digit( $end ) ) {
+ $this->error( "Invalid value for end parameter.", true );
+ }
+ $end = intval( $end );
+
$this->output( "Building content page file cache from page {$start}!\n" );
$dbr = wfGetDB( DB_SLAVE );
- $start = $start > 0 ? $start : $dbr->selectField( 'page', 'MIN(page_id)', false, __FUNCTION__ );
- $end = $dbr->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ );
+ $overwrite = $this->getOption( 'overwrite', false );
+ $start = ( $start > 0 )
+ ? $start
+ : $dbr->selectField( 'page', 'MIN(page_id)', false, __FUNCTION__ );
+ $end = ( $end > 0 )
+ ? $end
+ : $dbr->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ );
if ( !$start ) {
$this->error( "Nothing to do.", true );
}
@@ -69,22 +92,29 @@ class RebuildFileCache extends Maintenance {
"page_id BETWEEN $blockStart AND $blockEnd" ),
array( 'ORDER BY' => 'page_id ASC', 'USE INDEX' => 'PRIMARY' )
);
+
+ $dbw->begin(); // for any changes
foreach ( $res as $row ) {
$rebuilt = false;
- $wgRequestTime = wfTime(); # bug 22852
- $context = new RequestContext;
+ $wgRequestTime = microtime( true ); # bug 22852
+
$wgTitle = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
- $context->setTitle( $wgTitle );
if ( null == $wgTitle ) {
$this->output( "Page {$row->page_id} has bad title\n" );
continue; // broken title?
}
+
+ $context = new RequestContext;
+ $context->setTitle( $wgTitle );
+ $article = Article::newFromTitle( $wgTitle, $context );
+ $context->setWikiPage( $article->getPage() );
+
$wgOut = $context->getOutput(); // set display title
- $article = new Article( $wgTitle );
+
// If the article is cacheable, then load it
if ( $article->isFileCacheable() ) {
- $cache = new HTMLFileCache( $wgTitle );
- if ( $cache->isFileCacheGood() ) {
+ $cache = HTMLFileCache::newFromTitle( $wgTitle, 'view' );
+ if ( $cache->isCacheGood() ) {
if ( $overwrite ) {
$rebuilt = true;
} else {
@@ -100,18 +130,19 @@ class RebuildFileCache extends Maintenance {
wfRestoreWarnings();
$wgUseFileCache = true;
ob_end_clean(); // clear buffer
- if ( $rebuilt )
+ if ( $rebuilt ) {
$this->output( "Re-cached page {$row->page_id}\n" );
- else
+ } else {
$this->output( "Cached page {$row->page_id}\n" );
+ }
} else {
$this->output( "Page {$row->page_id} not cacheable\n" );
}
- $dbw->commit(); // commit any changes
}
+ $dbw->commit(); // commit any changes (just for sanity)
+
$blockStart += $this->mBatchSize;
$blockEnd += $this->mBatchSize;
- wfWaitForSlaves();
}
$this->output( "Done!\n" );
diff --git a/maintenance/rebuildImages.php b/maintenance/rebuildImages.php
index 17111831..fe3b35c9 100644
--- a/maintenance/rebuildImages.php
+++ b/maintenance/rebuildImages.php
@@ -27,7 +27,7 @@
*
* @file
* @author Brion Vibber <brion at pobox.com>
- * @ingroup maintenance
+ * @ingroup Maintenance
*/
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
@@ -148,8 +148,7 @@ class ImageBuilder extends Maintenance {
}
function buildOldImage() {
- $this->buildTable( 'oldimage', 'oi_archive_name',
- array( $this, 'oldimageCallback' ) );
+ $this->buildTable( 'oldimage', 'oi_archive_name', array( $this, 'oldimageCallback' ) );
}
function oldimageCallback( $row, $copy ) {
@@ -164,42 +163,33 @@ class ImageBuilder extends Maintenance {
}
function crawlMissing() {
- $repo = RepoGroup::singleton()->getLocalRepo();
- $repo->enumFilesInFS( array( $this, 'checkMissingImage' ) );
+ $this->getRepo()->enumFiles( array( $this, 'checkMissingImage' ) );
}
function checkMissingImage( $fullpath ) {
$filename = wfBaseName( $fullpath );
- if ( is_dir( $fullpath ) ) {
- return;
- }
- if ( is_link( $fullpath ) ) {
- $this->output( "skipping symlink at $fullpath\n" );
- return;
- }
$row = $this->dbw->selectRow( 'image',
array( 'img_name' ),
array( 'img_name' => $filename ),
__METHOD__ );
- if ( $row ) {
- // already known, move on
- return;
- } else {
+ if ( !$row ) { // file not registered
$this->addMissingImage( $filename, $fullpath );
}
}
function addMissingImage( $filename, $fullpath ) {
- $timestamp = $this->dbw->timestamp( filemtime( $fullpath ) );
-
global $wgContLang;
+
+ $timestamp = $this->dbw->timestamp( $this->getRepo()->getFileTimestamp( $fullpath ) );
+
$altname = $wgContLang->checkTitleEncoding( $filename );
if ( $altname != $filename ) {
if ( $this->dryrun ) {
$filename = $altname;
$this->output( "Estimating transcoding... $altname\n" );
} else {
+ # @FIXME: create renameFile()
$filename = $this->renameFile( $filename );
}
}
diff --git a/maintenance/rebuildInterwiki.php b/maintenance/rebuildInterwiki.php
deleted file mode 100644
index 25aea2de..00000000
--- a/maintenance/rebuildInterwiki.php
+++ /dev/null
@@ -1,275 +0,0 @@
-<?php
-/**
- * Rebuild interwiki table using the file on meta and the language list
- * Wikimedia specific!
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @todo document
- * @ingroup Maintenance
- * @ingroup Wikimedia
- */
-
-require_once( dirname( __FILE__ ) . '/Site.php' );
-
-require_once( dirname( __FILE__ ) . '/Maintenance.php' );
-
-class RebuildInterwiki extends Maintenance {
- public function __construct() {
- parent::__construct();
- $this->mDescription = "Rebuild the interwiki table using the file on meta and the language list.";
- $this->addOption( 'langlist', 'File with one language code per line', false, true );
- $this->addOption( 'dblist', 'File with one db per line', false, true );
- $this->addOption( 'd', 'Output folder', false, true );
- }
-
- function execute() {
- # List of language prefixes likely to be found in multi-language sites
- $this->langlist = array_map( "trim", file( $this->getOption( 'langlist', "/home/wikipedia/common/langlist" ) ) );
-
- # List of all database names
- $this->dblist = array_map( "trim", file( $this->getOption( 'dblist', "/home/wikipedia/common/all.dblist" ) ) );
-
- # Special-case databases
- //$this->specials = array_flip( array_map( "trim", file( $this->getOption( 'specialdbs', "/home/wikipedia/common/special.dblist" ) ) ) );
-
- $this->makeInterwikiSQL( $this->getOption( 'd', '/home/wikipedia/conf/interwiki/sql' ) );
- }
-
- function makeInterwikiSQL( $destDir ) {
- $this->output( "Making new interwiki SQL files in $destDir\n" );
-
- # Multi-language sites
- # db suffix => db suffix, iw prefix, hostname
- $sites = array(
- 'wiki' => new Site( 'wiki', 'w', 'wikipedia.org' ),
- 'wiktionary' => new Site( 'wiktionary', 'wikt', 'wiktionary.org' ),
- 'wikiquote' => new Site( 'wikiquote', 'q', 'wikiquote.org' ),
- 'wikibooks' => new Site( 'wikibooks', 'b', 'wikibooks.org' ),
- 'wikinews' => new Site( 'wikinews', 'n', 'wikinews.org' ),
- 'wikisource' => new Site( 'wikisource', 's', 'wikisource.org' ),
- 'wikimedia' => new Site( 'wikimedia', 'chapter', 'wikimedia.org' ),
- 'wikiversity' => new Site( 'wikiversity', 'v', 'wikiversity.org' ),
- );
-
- # Special-case hostnames
- $this->specials = array(
- 'sourceswiki' => 'sources.wikipedia.org',
- 'quotewiki' => 'wikiquote.org',
- 'textbookwiki' => 'wikibooks.org',
- 'sep11wiki' => 'sep11.wikipedia.org',
- 'metawiki' => 'meta.wikimedia.org',
- 'commonswiki' => 'commons.wikimedia.org',
- 'specieswiki' => 'species.wikimedia.org',
- );
-
- # Extra interwiki links that can't be in the intermap for some reason
- $extraLinks = array(
- array( 'm', 'http://meta.wikimedia.org/wiki/$1', 1 ),
- array( 'meta', 'http://meta.wikimedia.org/wiki/$1', 1 ),
- array( 'sep11', 'http://sep11.wikipedia.org/wiki/$1', 1 ),
- );
-
- # Language aliases, usually configured as redirects to the real wiki in apache
- # Interlanguage links are made directly to the real wiki
- # Something horrible happens if you forget to list an alias here, I can't
- # remember what
- $this->languageAliases = array(
- 'zh-cn' => 'zh',
- 'zh-tw' => 'zh',
- 'dk' => 'da',
- 'nb' => 'no',
- );
-
- # Special case prefix rewrites, for the benefit of Swedish which uses s:t
- # as an abbreviation for saint
- $this->prefixRewrites = array(
- 'svwiki' => array( 's' => 'src' ),
- );
-
- # Construct a list of reserved prefixes
- $reserved = array();
- foreach ( $this->langlist as $lang ) {
- $reserved[$lang] = 1;
- }
- foreach ( $this->languageAliases as $alias => $lang ) {
- $reserved[$alias] = 1;
- }
- foreach ( $sites as $site ) {
- $reserved[$site->lateral] = 1;
- }
-
- # Extract the intermap from meta
- $intermap = Http::get( 'http://meta.wikimedia.org/w/index.php?title=Interwiki_map&action=raw', 30 );
- $lines = array_map( 'trim', explode( "\n", trim( $intermap ) ) );
-
- if ( !$lines || count( $lines ) < 2 ) {
- $this->error( "m:Interwiki_map not found", true );
- }
-
- $iwArray = array();
-
- foreach ( $lines as $line ) {
- $matches = array();
- if ( preg_match( '/^\|\s*(.*?)\s*\|\|\s*(https?:\/\/.*?)\s*$/', $line, $matches ) ) {
- $prefix = strtolower( $matches[1] );
- $url = $matches[2];
- if ( preg_match( '/(wikipedia|wiktionary|wikisource|wikiquote|wikibooks|wikimedia)\.org/', $url ) ) {
- $local = 1;
- } else {
- $local = 0;
- }
-
- if ( empty( $reserved[$prefix] ) ) {
- $iwArray[$prefix] = array( "iw_prefix" => $prefix, "iw_url" => $url, "iw_local" => $local );
- }
- }
- }
-
- foreach ( $this->dblist as $db ) {
- $sql = "-- Generated by rebuildInterwiki.php";
- if ( isset( $this->specials[$db] ) ) {
- # Special wiki
- # Has interwiki links and interlanguage links to wikipedia
-
- $host = $this->specials[$db];
- $sql .= "\n--$host\n\n";
- $sql .= "USE $db;\n" .
- "TRUNCATE TABLE interwiki;\n" .
- "INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES \n";
- $first = true;
-
- # Intermap links
- foreach ( $iwArray as $iwEntry ) {
- $sql .= $this->makeLink( $iwEntry, $first, $db );
- }
-
- # Links to multilanguage sites
- foreach ( $sites as $targetSite ) {
- $sql .= $this->makeLink( array( $targetSite->lateral, $targetSite->getURL( 'en' ), 1 ), $first, $db );
- }
-
- # Interlanguage links to wikipedia
- $sql .= $this->makeLanguageLinks( $sites['wiki'], $first, $db );
-
- # Extra links
- foreach ( $extraLinks as $link ) {
- $sql .= $this->makeLink( $link, $first, $db );
- }
-
- $sql .= ";\n";
- } else {
- # Find out which site this DB belongs to
- $site = false;
- foreach ( $sites as $candidateSite ) {
- $suffix = $candidateSite->suffix;
- if ( preg_match( "/(.*)$suffix$/", $db, $matches ) ) {
- $site = $candidateSite;
- break;
- }
- }
- if ( !$site ) {
- print "Invalid database $db\n";
- continue;
- }
- $lang = $matches[1];
- $host = "$lang." . $site->url;
- $sql .= "\n--$host\n\n";
-
- $sql .= "USE $db;\n" .
- "TRUNCATE TABLE interwiki;\n" .
- "INSERT INTO interwiki (iw_prefix,iw_url,iw_local) VALUES\n";
- $first = true;
-
- # Intermap links
- foreach ( $iwArray as $iwEntry ) {
- # Suppress links with the same name as the site
- if ( ( $suffix == 'wiki' && $iwEntry['iw_prefix'] != 'wikipedia' ) ||
- ( $suffix != 'wiki' && $suffix != $iwEntry['iw_prefix'] ) )
- {
- $sql .= $this->makeLink( $iwEntry, $first, $db );
- }
- }
-
- # Lateral links
- foreach ( $sites as $targetSite ) {
- # Suppress link to self
- if ( $targetSite->suffix != $site->suffix ) {
- $sql .= $this->makeLink( array( $targetSite->lateral, $targetSite->getURL( $lang ), 1 ), $first, $db );
- }
- }
-
- # Interlanguage links
- $sql .= $this->makeLanguageLinks( $site, $first, $db );
-
- # w link within wikipedias
- # Other sites already have it as a lateral link
- if ( $site->suffix == "wiki" ) {
- $sql .= $this->makeLink( array( "w", "http://en.wikipedia.org/wiki/$1", 1 ), $first, $db );
- }
-
- # Extra links
- foreach ( $extraLinks as $link ) {
- $sql .= $this->makeLink( $link, $first, $db );
- }
- $sql .= ";\n";
- }
- file_put_contents( "$destDir/$db.sql", $sql );
- }
- }
-
- # ------------------------------------------------------------------------------------------
-
- # Returns part of an INSERT statement, corresponding to all interlanguage links to a particular site
- function makeLanguageLinks( &$site, &$first, $source ) {
- $sql = "";
-
- # Actual languages with their own databases
- foreach ( $this->langlist as $targetLang ) {
- $sql .= $this->makeLink( array( $targetLang, $site->getURL( $targetLang ), 1 ), $first, $source );
- }
-
- # Language aliases
- foreach ( $this->languageAliases as $alias => $lang ) {
- $sql .= $this->makeLink( array( $alias, $site->getURL( $lang ), 1 ), $first, $source );
- }
- return $sql;
- }
-
- # Make SQL for a single link from an array
- function makeLink( $entry, &$first, $source ) {
-
- if ( isset( $this->prefixRewrites[$source] ) && isset($entry[0]) && isset( $this->prefixRewrites[$source][$entry[0]] ) ) {
- $entry[0] = $this->prefixRewrites[$source][$entry[0]];
- }
-
- $sql = "";
- # Add comma
- if ( $first ) {
- $first = false;
- } else {
- $sql .= ",\n";
- }
- $dbr = wfGetDB( DB_SLAVE );
- $sql .= "(" . $dbr->makeList( $entry ) . ")";
- return $sql;
- }
-}
-
-$maintClass = "RebuildInterwiki";
-require_once( RUN_MAINTENANCE_IF_MAIN );
-
diff --git a/maintenance/rebuildrecentchanges.php b/maintenance/rebuildrecentchanges.php
index 5cacac65..92d60902 100644
--- a/maintenance/rebuildrecentchanges.php
+++ b/maintenance/rebuildrecentchanges.php
@@ -119,11 +119,11 @@ class RebuildRecentchanges extends Maintenance {
if ( $row ) {
$lastOldId = intval( $row->rev_id );
# Grab the last text size if available
- $lastSize = !is_null( $row->rev_len ) ? intval( $row->rev_len ) : 'NULL';
+ $lastSize = !is_null( $row->rev_len ) ? intval( $row->rev_len ) : null;
} else {
# No previous edit
$lastOldId = 0;
- $lastSize = 'NULL';
+ $lastSize = null;
$new = 1; // probably true
}
}
diff --git a/maintenance/rebuildtextindex.php b/maintenance/rebuildtextindex.php
index 04606c75..494e0a75 100644
--- a/maintenance/rebuildtextindex.php
+++ b/maintenance/rebuildtextindex.php
@@ -112,7 +112,7 @@ class RebuildTextIndex extends Maintenance {
*/
private function dropMysqlTextIndex() {
$searchindex = $this->db->tableName( 'searchindex' );
- if ( $this->db->indexExists( 'searchindex', 'si_title' ) ) {
+ if ( $this->db->indexExists( 'searchindex', 'si_title', __METHOD__ ) ) {
$this->output( "Dropping index...\n" );
$sql = "ALTER TABLE $searchindex DROP INDEX si_title, DROP INDEX si_text";
$this->db->query( $sql, __METHOD__ );
diff --git a/maintenance/refreshImageMetadata.php b/maintenance/refreshImageMetadata.php
index ec612183..958b2ba1 100644
--- a/maintenance/refreshImageMetadata.php
+++ b/maintenance/refreshImageMetadata.php
@@ -24,7 +24,7 @@
*
* @file
* @author Brian Wolff
- * @ingroup maintenance
+ * @ingroup Maintenance
*/
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
@@ -156,6 +156,10 @@ class RefreshImageMetadata extends Maintenance {
}
}
+ /**
+ * @param $dbw DatabaseBase
+ * @return array
+ */
function getConditions( $dbw ) {
$conds = array();
@@ -179,8 +183,12 @@ class RefreshImageMetadata extends Maintenance {
return $conds;
}
+ /**
+ * @param $force bool
+ * @param $brokenOnly bool
+ */
function setupParameters( $force, $brokenOnly ) {
- global $wgUpdateCompatibleMetadata, $wgReadOnly;
+ global $wgUpdateCompatibleMetadata;
if ( $brokenOnly ) {
$wgUpdateCompatibleMetadata = false;
diff --git a/maintenance/refreshLinks.php b/maintenance/refreshLinks.php
index 0515ef1b..c16b6963 100644
--- a/maintenance/refreshLinks.php
+++ b/maintenance/refreshLinks.php
@@ -184,17 +184,15 @@ class RefreshLinks extends Maintenance {
__METHOD__ );
return;
}
- $article = new Article( $title );
- $rt = $article->followRedirect();
+ $page = WikiPage::factory( $title );
+ $rt = $page->getRedirectTarget();
- if ( !$rt || !is_object( $rt ) ) {
+ if ( $rt === null ) {
// $title is not a redirect
// Delete any redirect table entry for it
$dbw->delete( 'redirect', array( 'rd_from' => $id ),
__METHOD__ );
- } else {
- $article->updateRedirectOn( $dbw, $rt );
}
}
@@ -213,13 +211,14 @@ class RefreshLinks extends Maintenance {
if ( is_null( $title ) ) {
return;
}
- $dbw->begin();
$revision = Revision::newFromTitle( $title );
if ( !$revision ) {
return;
}
+ $dbw->begin();
+
$options = new ParserOptions;
$parserOutput = $wgParser->parse( $revision->getText(), $title, $options, true, true, $revision->getId() );
$update = new LinksUpdate( $title, $parserOutput, false );
@@ -229,7 +228,7 @@ class RefreshLinks extends Maintenance {
/**
* Removes non-existing links from pages from pagelinks, imagelinks,
- * categorylinks, templatelinks and externallinks tables.
+ * categorylinks, templatelinks, externallinks, interwikilinks, langlinks and redirect tables.
*
* @param $maxLag
* @param $batchSize The size of deletion batches
@@ -254,6 +253,7 @@ class RefreshLinks extends Maintenance {
'iwlinks' => 'iwl_from',
'langlinks' => 'll_from',
'redirect' => 'rd_from',
+ 'page_props' => 'pp_page',
);
foreach ( $linksTables as $table => $field ) {
@@ -271,7 +271,6 @@ class RefreshLinks extends Maintenance {
$counter = 0;
$list = array();
$this->output( "0.." );
-
foreach ( $results as $row ) {
$counter++;
$list[] = $row->$field;
diff --git a/maintenance/removeUnusedAccounts.php b/maintenance/removeUnusedAccounts.php
index 44c27b35..ba25efdd 100644
--- a/maintenance/removeUnusedAccounts.php
+++ b/maintenance/removeUnusedAccounts.php
@@ -92,7 +92,7 @@ class RemoveUnusedAccounts extends Maintenance {
private function isInactiveAccount( $id, $master = false ) {
$dbo = wfGetDB( $master ? DB_MASTER : DB_SLAVE );
$checks = array( 'revision' => 'rev', 'archive' => 'ar', 'logging' => 'log',
- 'image' => 'img', 'oldimage' => 'oi' );
+ 'image' => 'img', 'oldimage' => 'oi', 'filearchive' => 'fa' );
$count = 0;
$dbo->begin();
diff --git a/maintenance/renamewiki.php b/maintenance/renamewiki.php
deleted file mode 100644
index 4146525e..00000000
--- a/maintenance/renamewiki.php
+++ /dev/null
@@ -1,89 +0,0 @@
-<?php
-/**
- * Why yes, this *is* another special-purpose Wikimedia maintenance script!
- * Should be fixed up and generalized.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- * @ingroup Wikimedia
- */
-
-require_once( dirname( __FILE__ ) . '/Maintenance.php' );
-
-class RenameWiki extends Maintenance {
- public function __construct() {
- parent::__construct();
- $this->mDescription = "Rename external storage dbs and leave a new one";
- $this->addArg( 'olddb', 'Old DB name' );
- $this->addArg( 'newdb', 'New DB name' );
- }
-
- public function getDbType() {
- return Maintenance::DB_ADMIN;
- }
-
- public function execute() {
- global $wgDefaultExternalStore;
-
- # Setup
- $from = $this->getArg( 0 );
- $to = $this->getArg( 1 );
- $this->output( "Renaming blob tables in ES from $from to $to...\n" );
- $this->output( "Sleeping 5 seconds...\n" );
- sleep( 5 );
-
- # Initialise external storage
- if ( is_array( $wgDefaultExternalStore ) ) {
- $stores = $wgDefaultExternalStore;
- } elseif ( $wgDefaultExternalStore ) {
- $stores = array( $wgDefaultExternalStore );
- } else {
- $stores = array();
- }
-
- if ( count( $stores ) ) {
- $this->output( "Initialising external storage...\n" );
- global $wgDBuser, $wgDBpassword, $wgExternalServers;
- foreach ( $stores as $storeURL ) {
- $m = array();
- if ( !preg_match( '!^DB://(.*)$!', $storeURL, $m ) ) {
- continue;
- }
-
- $cluster = $m[1];
-
- # Hack
- $wgExternalServers[$cluster][0]['user'] = $wgDBuser;
- $wgExternalServers[$cluster][0]['password'] = $wgDBpassword;
-
- $store = new ExternalStoreDB;
- $extdb =& $store->getMaster( $cluster );
- $extdb->query( "SET table_type=InnoDB" );
- $extdb->query( "CREATE DATABASE {$to}" );
- $extdb->query( "ALTER TABLE {$from}.blobs RENAME TO {$to}.blobs" );
- $extdb->selectDB( $from );
- $extdb->sourceFile( $this->getDir() . '/storage/blobs.sql' );
- $extdb->commit();
- }
- }
- $this->output( "done.\n" );
- }
-}
-
-$maintClass = "RenameWiki";
-require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/rollbackEdits.php b/maintenance/rollbackEdits.php
index e1c126e1..3e57e01f 100644
--- a/maintenance/rollbackEdits.php
+++ b/maintenance/rollbackEdits.php
@@ -62,10 +62,12 @@ class RollbackEdits extends Maintenance {
return;
}
+ $doer = User::newFromName( 'Maintenance script' );
+
foreach ( $titles as $t ) {
- $a = new Article( $t );
- $this->output( 'Processing ' . $t->getPrefixedText() . '...' );
- if ( !$a->commitRollback( $user, $summary, $bot, $results ) ) {
+ $page = WikiPage::factory( $t );
+ $this->output( 'Processing ' . $t->getPrefixedText() . '... ' );
+ if ( !$page->commitRollback( $user, $summary, $bot, $results, $doer ) ) {
$this->output( "done\n" );
} else {
$this->output( "failed\n" );
@@ -76,6 +78,7 @@ class RollbackEdits extends Maintenance {
/**
* Get all pages that should be rolled back for a given user
* @param $user String a name to check against rev_user_text
+ * @return array
*/
private function getRollbackTitles( $user ) {
$dbr = wfGetDB( DB_SLAVE );
diff --git a/maintenance/runBatchedQuery.php b/maintenance/runBatchedQuery.php
index 9a6b6383..83e0cab8 100644
--- a/maintenance/runBatchedQuery.php
+++ b/maintenance/runBatchedQuery.php
@@ -36,7 +36,6 @@ class BatchedQueryRunner extends Maintenance {
$this->error( "No query specified. Specify the query as a command line parameter.", true );
$query = $this->getArg();
- $wait = $this->getOption( 'wait', 5 );
$n = 1;
$dbw = wfGetDB( DB_MASTER );
do {
diff --git a/maintenance/runJobs.php b/maintenance/runJobs.php
index 0edf7ac9..6068311e 100644
--- a/maintenance/runJobs.php
+++ b/maintenance/runJobs.php
@@ -61,16 +61,18 @@ class RunJobs extends Maintenance {
$dbw = wfGetDB( DB_MASTER );
$n = 0;
$conds = '';
- if ( $type !== false )
+ if ( $type !== false ) {
$conds = "job_cmd = " . $dbw->addQuotes( $type );
+ }
while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) {
$offset = 0;
for ( ; ; ) {
$job = !$type ? Job::pop( $offset ) : Job::pop_type( $type );
- if ( !$job )
+ if ( !$job ) {
break;
+ }
wfWaitForSlaves();
$t = microtime( true );
diff --git a/maintenance/showJobs.php b/maintenance/showJobs.php
index 886d7d45..ff7d3fc0 100644
--- a/maintenance/showJobs.php
+++ b/maintenance/showJobs.php
@@ -21,7 +21,7 @@
*
* @ingroup Maintenance
* @author Tim Starling
- * @author Ashar Voultoiz
+ * @author Antoine Musso
*/
require_once( dirname( __FILE__ ) . '/Maintenance.php' );
diff --git a/maintenance/showStats.php b/maintenance/showStats.php
index f695c440..b284a9ac 100644
--- a/maintenance/showStats.php
+++ b/maintenance/showStats.php
@@ -20,7 +20,7 @@
* http://www.gnu.org/copyleft/gpl.html
*
* @ingroup Maintenance
- * @author Ashar Voultoiz <hashar at free dot fr>
+ * @author Antoine Musso <hashar at free dot fr>
* Based on initStats.php by:
* @author Brion Vibber
* @author Rob Church <robchur@gmail.com>
@@ -42,7 +42,6 @@ class ShowStats extends Maintenance {
'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',
);
diff --git a/maintenance/sql.php b/maintenance/sql.php
index e1f2bb5f..c4af6307 100644
--- a/maintenance/sql.php
+++ b/maintenance/sql.php
@@ -30,32 +30,59 @@ class MwSql extends Maintenance {
}
public function execute() {
+ $dbw = wfGetDB( DB_MASTER );
if ( $this->hasArg() ) {
$fileName = $this->getArg();
$file = fopen( $fileName, 'r' );
- $promptCallback = false;
- } else {
- $file = $this->getStdin();
- $promptObject = new SqlPromptPrinter( "> " );
- $promptCallback = $promptObject->cb();
+ if ( !$file ) {
+ $this->error( "Unable to open input file", true );
+ }
+
+ $error = $dbw->sourceStream( $file, false, array( $this, 'sqlPrintResult' ) );
+ if ( $error !== true ) {
+ $this->error( $error, true );
+ } else {
+ exit( 0 );
+ }
}
- if ( !$file )
- $this->error( "Unable to open input file", true );
+ $useReadline = function_exists( 'readline_add_history' )
+ && Maintenance::posix_isatty( 0 /*STDIN*/ );
- $dbw = wfGetDB( DB_MASTER );
- $error = $dbw->sourceStream( $file, $promptCallback, array( $this, 'sqlPrintResult' ) );
- if ( $error !== true ) {
- $this->error( $error, true );
- } else {
- exit( 0 );
+ if ( $useReadline ) {
+ global $IP;
+ $historyFile = isset( $_ENV['HOME'] ) ?
+ "{$_ENV['HOME']}/.mwsql_history" : "$IP/maintenance/.mwsql_history";
+ readline_read_history( $historyFile );
+ }
+
+ $wholeLine = '';
+ while ( ( $line = Maintenance::readconsole() ) !== false ) {
+ $done = $dbw->streamStatementEnd( $wholeLine, $line );
+
+ $wholeLine .= $line;
+
+ if ( !$done ) {
+ continue;
+ }
+ if ( $useReadline ) {
+ readline_add_history( $wholeLine );
+ readline_write_history( $historyFile );
+ }
+ try{
+ $res = $dbw->query( $wholeLine );
+ $this->sqlPrintResult( $res, $dbw );
+ $wholeLine = '';
+ } catch (DBQueryError $e) {
+ $this->error( $e, true );
+ }
}
}
/**
* Print the results, callback for $db->sourceStream()
- * @param $res The results object
- * @param $db Database object
+ * @param $res ResultWrapper The results object
+ * @param $db DatabaseBase object
*/
public function sqlPrintResult( $res, $db ) {
if ( !$res ) {
@@ -70,24 +97,13 @@ class MwSql extends Maintenance {
}
}
+ /**
+ * @return int DB_TYPE constant
+ */
public function getDbType() {
return Maintenance::DB_ADMIN;
}
}
-class SqlPromptPrinter {
- function __construct( $prompt ) {
- $this->prompt = $prompt;
- }
-
- function cb() {
- return array( $this, 'printPrompt' );
- }
-
- function printPrompt() {
- echo $this->prompt;
- }
-}
-
$maintClass = "MwSql";
require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/sqlite.php b/maintenance/sqlite.php
index dc8a430e..864d5ab6 100644
--- a/maintenance/sqlite.php
+++ b/maintenance/sqlite.php
@@ -35,6 +35,8 @@ class SqliteMaintenance extends Maintenance {
/**
* While we use database connection, this simple lie prevents useless --dbpass and
* --dbuser options from appearing in help message for this script.
+ *
+ * @return int DB constant
*/
public function getDbType() {
return Maintenance::DB_NONE;
@@ -129,4 +131,4 @@ class SqliteMaintenance extends Maintenance {
}
$maintClass = "SqliteMaintenance";
-require_once( RUN_MAINTENANCE_IF_MAIN ); \ No newline at end of file
+require_once( RUN_MAINTENANCE_IF_MAIN );
diff --git a/maintenance/sqlite/archives/initial-indexes.sql b/maintenance/sqlite/archives/initial-indexes.sql
index 2573ca13..73b008cc 100644
--- a/maintenance/sqlite/archives/initial-indexes.sql
+++ b/maintenance/sqlite/archives/initial-indexes.sql
@@ -3,7 +3,7 @@
-- Unique indexes need to be handled with INSERT SELECT since just running
-- the CREATE INDEX statement will fail if there are duplicate values.
--
--- Ignore duplicates, several tables will have them (e.g. bug 16966) but in
+-- Ignore duplicates, several tables will have them (e.g. bug 16966) but in
-- most cases it's harmless to discard them.
--------------------------------------------------------------------------------
@@ -218,7 +218,7 @@ CREATE TABLE /*_*/math_tmp (
math_outputhash varbinary(16) NOT NULL,
math_html_conservativeness tinyint NOT NULL,
math_html text,
- math_mathml text
+ math_mathml text
);
CREATE UNIQUE INDEX /*i*/math_inputhash ON /*_*/math_tmp (math_inputhash);
@@ -406,7 +406,6 @@ CREATE INDEX /*i*/type_time ON /*_*/logging (log_type, log_timestamp);
CREATE INDEX /*i*/user_time ON /*_*/logging (log_user, log_timestamp);
CREATE INDEX /*i*/page_time ON /*_*/logging (log_namespace, log_title, log_timestamp);
CREATE INDEX /*i*/times ON /*_*/logging (log_timestamp);
-CREATE INDEX /*i*/tb_page ON /*_*/trackbacks (tb_page);
CREATE INDEX /*i*/job_cmd_namespace_title ON /*_*/job (job_cmd, job_namespace, job_title);
CREATE INDEX /*i*/rd_ns_title ON /*_*/redirect (rd_namespace,rd_title,rd_from);
CREATE INDEX /*i*/qcc_type ON /*_*/querycachetwo (qcc_type,qcc_value);
diff --git a/maintenance/sqlite/archives/patch-drop-user_options.sql b/maintenance/sqlite/archives/patch-drop-user_options.sql
new file mode 100644
index 00000000..5bc6a47c
--- /dev/null
+++ b/maintenance/sqlite/archives/patch-drop-user_options.sql
@@ -0,0 +1,31 @@
+-- Remove user_options field from user table
+
+CREATE TABLE /*_*/user_tmp (
+ user_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ user_name varchar(255) binary NOT NULL default '',
+ user_real_name varchar(255) binary NOT NULL default '',
+ user_password tinyblob NOT NULL,
+ user_newpassword tinyblob NOT NULL,
+ user_newpass_time binary(14),
+ user_email tinytext NOT NULL,
+ user_touched binary(14) NOT NULL default '',
+ user_token binary(32) NOT NULL default '',
+ user_email_authenticated binary(14),
+ user_email_token binary(32),
+ user_email_token_expires binary(14),
+ user_registration binary(14),
+ user_editcount int
+) /*$wgDBTableOptions*/;
+
+INSERT INTO /*_*/user_tmp
+ SELECT user_id, user_name, user_real_name, user_password, user_newpassword, user_newpass_time, user_email, user_touched,
+ user_token, user_email_authenticated, user_email_token, user_email_token_expires, user_registration, user_editcount
+ FROM /*_*/user;
+
+DROP TABLE /*_*/user;
+
+ALTER TABLE /*_*/user_tmp RENAME TO /*_*/user;
+
+CREATE UNIQUE INDEX /*i*/user_name ON /*_*/user (user_name);
+CREATE INDEX /*i*/user_email_token ON /*_*/user (user_email_token);
+CREATE INDEX /*i*/user_email ON /*_*/user (user_email(50));
diff --git a/maintenance/sqlite/archives/patch-jobs-add-timestamp.sql b/maintenance/sqlite/archives/patch-jobs-add-timestamp.sql
new file mode 100644
index 00000000..c5e6e711
--- /dev/null
+++ b/maintenance/sqlite/archives/patch-jobs-add-timestamp.sql
@@ -0,0 +1,2 @@
+ALTER TABLE /*_*/job ADD COLUMN job_timestamp varbinary(14) NULL default NULL;
+CREATE INDEX /*i*/job_timestamp ON /*_*/job(job_timestamp);
diff --git a/maintenance/sqlite/archives/patch-page_redirect_namespace_len.sql b/maintenance/sqlite/archives/patch-page_redirect_namespace_len.sql
new file mode 100644
index 00000000..d9eedadd
--- /dev/null
+++ b/maintenance/sqlite/archives/patch-page_redirect_namespace_len.sql
@@ -0,0 +1,7 @@
+--
+-- Add the page_redirect_namespace_len index
+--
+
+CREATE INDEX /*i*/page_redirect_namespace_len ON /*_*/page (page_is_redirect, page_namespace, page_len);
+
+
diff --git a/maintenance/sqlite/archives/patch-ufg_group-length-increase.sql b/maintenance/sqlite/archives/patch-ufg_group-length-increase.sql
new file mode 100644
index 00000000..c6dcea5e
--- /dev/null
+++ b/maintenance/sqlite/archives/patch-ufg_group-length-increase.sql
@@ -0,0 +1,15 @@
+CREATE TABLE /*_*/user_former_groups_tmp (
+ ug_user int unsigned NOT NULL default 0,
+ ug_group varbinary(32) NOT NULL default ''
+) /*$wgDBTableOptions*/;
+
+INSERT INTO /*_*/user_former_groups_tmp
+ SELECT ug_user, ug_group
+ FROM /*_*/user_groups;
+
+DROP TABLE /*_*/user_former_groups;
+
+ALTER TABLE /*_*/user_former_groups_tmp RENAME TO /*_*/user_former_groups;
+
+CREATE UNIQUE INDEX /*i*/ufg_user_group ON /*_*/user_former_groups (ufg_user,ufg_group);
+
diff --git a/maintenance/sqlite/archives/patch-ug_group-length-increase.sql b/maintenance/sqlite/archives/patch-ug_group-length-increase.sql
new file mode 100644
index 00000000..5e810937
--- /dev/null
+++ b/maintenance/sqlite/archives/patch-ug_group-length-increase.sql
@@ -0,0 +1,15 @@
+CREATE TABLE /*_*/user_groups_tmp (
+ ug_user int unsigned NOT NULL default 0,
+ ug_group varbinary(32) NOT NULL default ''
+) /*$wgDBTableOptions*/;
+
+INSERT INTO /*_*/user_groups_tmp
+ SELECT ug_user, ug_group
+ FROM /*_*/user_groups;
+
+DROP TABLE /*_*/user_groups;
+
+ALTER TABLE /*_*/user_groups_tmp RENAME TO /*_*/user_groups;
+
+CREATE UNIQUE INDEX /*i*/ug_user_group ON /*_*/user_groups (ug_user,ug_group);
+CREATE INDEX /*i*/ug_group ON /*_*/user_groups (ug_group);
diff --git a/maintenance/stats.php b/maintenance/stats.php
index 1fb46fa9..46926dd0 100644
--- a/maintenance/stats.php
+++ b/maintenance/stats.php
@@ -54,14 +54,12 @@ class CacheStats extends Maintenance {
$this->output( "\nParser cache\n" );
$hits = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_hit' ) ) );
- $invalid = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_miss_invalid' ) ) );
$expired = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_miss_expired' ) ) );
$absent = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_miss_absent' ) ) );
$stub = intval( $wgMemc->get( wfMemcKey( 'stats', 'pcache_miss_stub' ) ) );
- $total = $hits + $invalid + $expired + $absent + $stub;
+ $total = $hits + $expired + $absent + $stub;
if ( $total ) {
$this->output( sprintf( "hits: %-10d %6.2f%%\n", $hits, $hits / $total * 100 ) );
- $this->output( sprintf( "invalid: %-10d %6.2f%%\n", $invalid, $invalid / $total * 100 ) );
$this->output( sprintf( "expired: %-10d %6.2f%%\n", $expired, $expired / $total * 100 ) );
$this->output( sprintf( "absent: %-10d %6.2f%%\n", $absent, $absent / $total * 100 ) );
$this->output( sprintf( "stub threshold: %-10d %6.2f%%\n", $stub, $stub / $total * 100 ) );
diff --git a/maintenance/storage/checkStorage.php b/maintenance/storage/checkStorage.php
index c372b9c4..af1f9ee2 100644
--- a/maintenance/storage/checkStorage.php
+++ b/maintenance/storage/checkStorage.php
@@ -21,8 +21,6 @@
* @ingroup Maintenance ExternalStorage
*/
-define( 'CONCAT_HEADER', 'O:27:"concatenatedgziphistoryblob"' );
-
if ( !defined( 'MEDIAWIKI' ) ) {
require_once( dirname( __FILE__ ) . '/../commandLine.inc' );
@@ -43,6 +41,7 @@ if ( !defined( 'MEDIAWIKI' ) ) {
* @ingroup Maintenance ExternalStorage
*/
class CheckStorage {
+ const CONCAT_HEADER = 'O:27:"concatenatedgziphistoryblob"';
var $oldIdMap, $errors;
var $dbStore = null;
@@ -55,15 +54,13 @@ class CheckStorage {
);
function check( $fix = false, $xml = '' ) {
- $fname = 'checkStorage';
$dbr = wfGetDB( DB_SLAVE );
if ( $fix ) {
- $dbw = wfGetDB( DB_MASTER );
print "Checking, will fix errors if possible...\n";
} else {
print "Checking...\n";
}
- $maxRevId = $dbr->selectField( 'revision', 'MAX(rev_id)', false, $fname );
+ $maxRevId = $dbr->selectField( 'revision', 'MAX(rev_id)', false, __METHOD__ );
$chunkSize = 1000;
$flagStats = array();
$objectStats = array();
@@ -84,7 +81,7 @@ class CheckStorage {
$this->oldIdMap = array();
$dbr->ping();
$res = $dbr->select( 'revision', array( 'rev_id', 'rev_text_id' ),
- array( "rev_id BETWEEN $chunkStart AND $chunkEnd" ), $fname );
+ array( "rev_id BETWEEN $chunkStart AND $chunkEnd" ), __METHOD__ );
foreach ( $res as $row ) {
$this->oldIdMap[$row->rev_id] = $row->rev_text_id;
}
@@ -99,8 +96,11 @@ class CheckStorage {
$externalRevs = array();
$objectRevs = array();
$res = $dbr->select( 'text', array( 'old_id', 'old_flags' ),
- 'old_id IN (' . implode( ',', $this->oldIdMap ) . ')', $fname );
+ 'old_id IN (' . implode( ',', $this->oldIdMap ) . ')', __METHOD__ );
foreach ( $res as $row ) {
+ /**
+ * @var $flags int
+ */
$flags = $row->old_flags;
$id = $row->old_id;
@@ -133,7 +133,7 @@ class CheckStorage {
$dbw = wfGetDB( DB_MASTER );
$dbw->ping();
$dbw->update( 'text', array( 'old_flags' => '' ),
- array( 'old_id' => $id ), $fname );
+ array( 'old_id' => $id ), __METHOD__ );
echo "Fixed\n";
} else {
$this->error( 'fixable', "Warning: old_flags set to 0", $id );
@@ -154,7 +154,7 @@ class CheckStorage {
$externalNormalBlobs = array();
if ( count( $externalRevs ) ) {
$res = $dbr->select( 'text', array( 'old_id', 'old_flags', 'old_text' ),
- array( 'old_id IN (' . implode( ',', $externalRevs ) . ')' ), $fname );
+ array( 'old_id IN (' . implode( ',', $externalRevs ) . ')' ), __METHOD__ );
foreach ( $res as $row ) {
$urlParts = explode( '://', $row->old_text, 2 );
if ( count( $urlParts ) !== 2 || $urlParts[1] == '' ) {
@@ -192,7 +192,7 @@ class CheckStorage {
$blobsTable = $this->dbStore->getTable( $extDb );
$res = $extDb->select( $blobsTable,
array( 'blob_id' ),
- array( 'blob_id IN( ' . implode( ',', $blobIds ) . ')' ), $fname );
+ array( 'blob_id IN( ' . implode( ',', $blobIds ) . ')' ), __METHOD__ );
foreach ( $res as $row ) {
unset( $xBlobIds[$row->blob_id] );
}
@@ -211,7 +211,7 @@ class CheckStorage {
if ( count( $objectRevs ) ) {
$headerLength = 300;
$res = $dbr->select( 'text', array( 'old_id', 'old_flags', "LEFT(old_text, $headerLength) AS header" ),
- array( 'old_id IN (' . implode( ',', $objectRevs ) . ')' ), $fname );
+ array( 'old_id IN (' . implode( ',', $objectRevs ) . ')' ), __METHOD__ );
foreach ( $res as $row ) {
$oldId = $row->old_id;
$matches = array();
@@ -262,7 +262,7 @@ class CheckStorage {
if ( count( $concatBlobs ) ) {
$headerLength = 300;
$res = $dbr->select( 'text', array( 'old_id', 'old_flags', "LEFT(old_text, $headerLength) AS header" ),
- array( 'old_id IN (' . implode( ',', array_keys( $concatBlobs ) ) . ')' ), $fname );
+ array( 'old_id IN (' . implode( ',', array_keys( $concatBlobs ) ) . ')' ), __METHOD__ );
foreach ( $res as $row ) {
$flags = explode( ',', $row->old_flags );
if ( in_array( 'external', $flags ) ) {
@@ -285,7 +285,7 @@ class CheckStorage {
$this->error( 'unfixable', "Error: invalid flags \"{$row->old_flags}\" on concat bulk row {$row->old_id}",
$concatBlobs[$row->old_id] );
}
- } elseif ( strcasecmp( substr( $row->header, 0, strlen( CONCAT_HEADER ) ), CONCAT_HEADER ) ) {
+ } elseif ( strcasecmp( substr( $row->header, 0, strlen( self::CONCAT_HEADER ) ), self::CONCAT_HEADER ) ) {
$this->error( 'restore text', "Error: Incorrect object header for concat bulk row {$row->old_id}",
$concatBlobs[$row->old_id] );
} # else good
@@ -354,7 +354,6 @@ class CheckStorage {
}
function checkExternalConcatBlobs( $externalConcatBlobs ) {
- $fname = 'CheckStorage::checkExternalConcatBlobs';
if ( !count( $externalConcatBlobs ) ) {
return;
}
@@ -367,12 +366,12 @@ class CheckStorage {
$blobIds = array_keys( $oldIds );
$extDb =& $this->dbStore->getSlave( $cluster );
$blobsTable = $this->dbStore->getTable( $extDb );
- $headerLength = strlen( CONCAT_HEADER );
+ $headerLength = strlen( self::CONCAT_HEADER );
$res = $extDb->select( $blobsTable,
array( 'blob_id', "LEFT(blob_text, $headerLength) AS header" ),
- array( 'blob_id IN( ' . implode( ',', $blobIds ) . ')' ), $fname );
+ array( 'blob_id IN( ' . implode( ',', $blobIds ) . ')' ), __METHOD__ );
foreach ( $res as $row ) {
- if ( strcasecmp( $row->header, CONCAT_HEADER ) ) {
+ if ( strcasecmp( $row->header, self::CONCAT_HEADER ) ) {
$this->error( 'restore text', "Error: invalid header on target $cluster/{$row->blob_id} of two-part ES URL",
$oldIds[$row->blob_id] );
}
@@ -440,8 +439,6 @@ class CheckStorage {
}
function importRevision( &$revision, &$importer ) {
- $fname = 'CheckStorage::importRevision';
-
$id = $revision->getID();
$text = $revision->getText();
if ( $text === '' ) {
@@ -462,7 +459,7 @@ class CheckStorage {
// Find text row again
$dbr = wfGetDB( DB_SLAVE );
- $oldId = $dbr->selectField( 'revision', 'rev_text_id', array( 'rev_id' => $id ), $fname );
+ $oldId = $dbr->selectField( 'revision', 'rev_text_id', array( 'rev_id' => $id ), __METHOD__ );
if ( !$oldId ) {
echo "Missing revision row for rev_id $id\n";
return;
@@ -476,7 +473,7 @@ class CheckStorage {
$dbw->update( 'text',
array( 'old_flags' => $flags, 'old_text' => $text ),
array( 'old_id' => $oldId ),
- $fname, array( 'LIMIT' => 1 )
+ __METHOD__, array( 'LIMIT' => 1 )
);
// Remove it from the unfixed list and add it to the fixed list
diff --git a/maintenance/storage/compressOld.php b/maintenance/storage/compressOld.php
index da82d93b..afe01458 100644
--- a/maintenance/storage/compressOld.php
+++ b/maintenance/storage/compressOld.php
@@ -70,7 +70,7 @@ class CompressOld extends Maintenance {
$type = $this->getOption( 'type', 'concat' );
$chunkSize = $this->getOption( 'chunksize', 20 );
- $startId = $this->getOption( 'start-id', 0 );
+ $startId = $this->getOption( 'startid', 0 );
$beginDate = $this->getOption( 'begin-date', '' );
$endDate = $this->getOption( 'end-date', '' );
$extDB = $this->getOption( 'extdb', '' );
@@ -123,7 +123,12 @@ class CompressOld extends Maintenance {
} while( true );
}
- /** @todo document */
+ /**
+ * @todo document
+ * @param $row
+ * @param $extdb
+ * @return bool
+ */
private function compressPage( $row, $extdb ) {
if ( false !== strpos( $row->old_flags, 'gzip' ) || false !== strpos( $row->old_flags, 'object' ) ) {
#print "Already compressed row {$row->old_id}\n";
@@ -156,7 +161,15 @@ class CompressOld extends Maintenance {
return true;
}
- /** @todo document */
+ /**
+ * @param $startId
+ * @param $maxChunkSize
+ * @param $beginDate
+ * @param $endDate
+ * @param $extdb string
+ * @param $maxPageId bool|int
+ * @return bool
+ */
private function compressWithConcat( $startId, $maxChunkSize, $beginDate,
$endDate, $extdb = "", $maxPageId = false )
{
diff --git a/maintenance/storage/fixBug20757.php b/maintenance/storage/fixBug20757.php
index b6def2da..cb2663d1 100644
--- a/maintenance/storage/fixBug20757.php
+++ b/maintenance/storage/fixBug20757.php
@@ -302,6 +302,9 @@ class FixBug20757 extends Maintenance {
/**
* This is based on part of HistoryBlobStub::getText().
* Determine if the text can be retrieved from the row in the normal way.
+ * @param $stub
+ * @param $secondaryRow
+ * @return bool
*/
function isUnbrokenStub( $stub, $secondaryRow ) {
$flags = explode( ',', $secondaryRow->old_flags );
diff --git a/maintenance/storage/recompressTracked.php b/maintenance/storage/recompressTracked.php
index 09ab3e57..c8aac64b 100644
--- a/maintenance/storage/recompressTracked.php
+++ b/maintenance/storage/recompressTracked.php
@@ -169,6 +169,7 @@ class RecompressTracked {
/**
* Make sure the tracking table exists and isn't empty
+ * @return bool
*/
function checkTrackingTable() {
$dbr = wfGetDB( DB_SLAVE );
@@ -588,6 +589,7 @@ class RecompressTracked {
/**
* Returns the name of the next target cluster
+ * @return string
*/
function getTargetCluster() {
$cluster = next( $this->destClusters );
@@ -599,6 +601,8 @@ class RecompressTracked {
/**
* Gets a DB master connection for the given external cluster name
+ * @param $cluster string
+ * @return DatabaseBase
*/
function getExtDB( $cluster ) {
$lb = wfGetLBFactory()->getExternalLB( $cluster );
@@ -684,6 +688,9 @@ class CgzCopyTransaction {
/**
* Add text.
* Returns false if it's ready to commit.
+ * @param $text string
+ * @param $textId
+ * @return bool
*/
function addItem( $text, $textId ) {
if ( !$this->cgz ) {
diff --git a/maintenance/tables.sql b/maintenance/tables.sql
index f879f02f..db89c37e 100644
--- a/maintenance/tables.sql
+++ b/maintenance/tables.sql
@@ -86,12 +86,6 @@ CREATE TABLE /*_*/user (
-- Same with passwords.
user_email tinytext NOT NULL,
- -- Newline-separated list of name=value defining the user
- -- preferences
- -- Now obsolete in favour of user_properties table;
- -- old values will be migrated from here transparently.
- 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
@@ -158,7 +152,7 @@ CREATE TABLE /*_*/user_groups (
-- 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 varbinary(16) NOT NULL default ''
+ ug_group varbinary(32) NOT NULL default ''
) /*$wgDBTableOptions*/;
CREATE UNIQUE INDEX /*i*/ug_user_group ON /*_*/user_groups (ug_user,ug_group);
@@ -169,7 +163,7 @@ CREATE INDEX /*i*/ug_group ON /*_*/user_groups (ug_group);
CREATE TABLE /*_*/user_former_groups (
-- Key to user_id
ufg_user int unsigned NOT NULL default 0,
- ufg_group varbinary(16) NOT NULL default ''
+ ufg_group varbinary(32) NOT NULL default ''
) /*$wgDBTableOptions*/;
CREATE UNIQUE INDEX /*i*/ufg_user_group ON /*_*/user_former_groups (ufg_user,ufg_group);
@@ -271,7 +265,7 @@ CREATE TABLE /*_*/page (
CREATE UNIQUE INDEX /*i*/name_title ON /*_*/page (page_namespace,page_title);
CREATE INDEX /*i*/page_random ON /*_*/page (page_random);
CREATE INDEX /*i*/page_len ON /*_*/page (page_len);
-
+CREATE INDEX /*i*/page_redirect_namespace_len ON /*_*/page (page_is_redirect, page_namespace, page_len);
--
-- Every edit of a page creates also a revision row.
@@ -279,6 +273,7 @@ CREATE INDEX /*i*/page_len ON /*_*/page (page_len);
-- to the text storage backend.
--
CREATE TABLE /*_*/revision (
+ -- Unique ID to identify each revision
rev_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
-- Key to page_id. This should _never_ be invalid.
@@ -302,14 +297,14 @@ CREATE TABLE /*_*/revision (
-- Text username or IP address of the editor.
rev_user_text varchar(255) binary NOT NULL default '',
- -- Timestamp
+ -- Timestamp of when revision was created
rev_timestamp binary(14) NOT NULL default '',
-- Records whether the user marked the 'minor edit' checkbox.
-- Many automated edits are marked as minor.
rev_minor_edit tinyint unsigned NOT NULL default 0,
- -- Not yet used; reserved for future changes to the deletion system.
+ -- Restrictions on who can access this revision
rev_deleted tinyint unsigned NOT NULL default 0,
-- Length of this revision in bytes
@@ -317,7 +312,10 @@ CREATE TABLE /*_*/revision (
-- Key to revision.rev_id
-- This field is used to add support for a tree structure (The Adjacency List Model)
- rev_parent_id int unsigned default NULL
+ rev_parent_id int unsigned default NULL,
+
+ -- SHA-1 text content hash in base-36
+ rev_sha1 varbinary(32) NOT NULL default ''
) /*$wgDBTableOptions*/ MAX_ROWS=10000000 AVG_ROW_LENGTH=1024;
-- In case tables are created as MyISAM, use row hints for MySQL <5.0 to avoid 4GB limit
@@ -424,7 +422,10 @@ CREATE TABLE /*_*/archive (
ar_page_id int unsigned,
-- Original previous revision
- ar_parent_id int unsigned default NULL
+ ar_parent_id int unsigned default NULL,
+
+ -- SHA-1 text content hash in base-36
+ ar_sha1 varbinary(32) NOT NULL default ''
) /*$wgDBTableOptions*/;
CREATE INDEX /*i*/name_title_timestamp ON /*_*/archive (ar_namespace,ar_title,ar_timestamp);
@@ -966,6 +967,9 @@ CREATE TABLE /*_*/uploadstash (
us_status varchar(50) not null,
+ -- chunk counter starts at 0, current offset is stored in us_size
+ us_chunk_inx int unsigned NULL,
+
-- file properties from File::getPropsFromPath. these may prove unnecessary.
--
us_size int unsigned NOT NULL,
@@ -997,6 +1001,8 @@ CREATE INDEX /*i*/us_timestamp ON /*_*/uploadstash (us_timestamp);
CREATE TABLE /*_*/recentchanges (
rc_id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
rc_timestamp varbinary(14) NOT NULL default '',
+
+ -- This is no longer used
rc_cur_time varbinary(14) NOT NULL default '',
-- As in revision
@@ -1016,6 +1022,7 @@ CREATE TABLE /*_*/recentchanges (
-- default view.
rc_bot tinyint unsigned NOT NULL default 0,
+ -- Set if this change corresponds to a page creation
rc_new tinyint unsigned NOT NULL default 0,
-- Key to page_id (was cur_id prior to 1.5).
@@ -1029,8 +1036,10 @@ CREATE TABLE /*_*/recentchanges (
-- rev_id of the prior revision, for generating diff links.
rc_last_oldid int unsigned NOT NULL default 0,
- -- These may no longer be used, with the new move log.
+ -- The type of change entry (RC_EDIT,RC_NEW,RC_LOG)
rc_type tinyint unsigned NOT NULL default 0,
+
+ -- These may no longer be used, with the new move log.
rc_moved_to_ns tinyint unsigned NOT NULL default 0,
rc_moved_to_title varchar(255) binary NOT NULL default '',
@@ -1226,6 +1235,7 @@ CREATE INDEX /*i*/page_time ON /*_*/logging (log_namespace, log_title, log_times
CREATE INDEX /*i*/times ON /*_*/logging (log_timestamp);
CREATE INDEX /*i*/log_user_type_time ON /*_*/logging (log_user, log_type, log_timestamp);
CREATE INDEX /*i*/log_page_id_time ON /*_*/logging (log_page,log_timestamp);
+CREATE INDEX /*i*/type_action ON /*_*/logging(log_type, log_action, log_timestamp);
CREATE TABLE /*_*/log_search (
@@ -1240,17 +1250,6 @@ CREATE UNIQUE INDEX /*i*/ls_field_val ON /*_*/log_search (ls_field,ls_value,ls_l
CREATE INDEX /*i*/ls_log_id ON /*_*/log_search (ls_log_id);
-CREATE TABLE /*_*/trackbacks (
- tb_id int PRIMARY KEY AUTO_INCREMENT,
- tb_page int REFERENCES /*_*/page(page_id) ON DELETE CASCADE,
- tb_title varchar(255) NOT NULL,
- tb_url blob NOT NULL,
- tb_ex text,
- tb_name varchar(255)
-) /*$wgDBTableOptions*/;
-CREATE INDEX /*i*/tb_page ON /*_*/trackbacks (tb_page);
-
-
-- Jobs performed by parallel apache threads or a command-line daemon
CREATE TABLE /*_*/job (
job_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
@@ -1264,12 +1263,17 @@ CREATE TABLE /*_*/job (
job_namespace int NOT NULL,
job_title varchar(255) binary NOT NULL,
+ -- Timestamp of when the job was inserted
+ -- NULL for jobs added before addition of the timestamp
+ job_timestamp varbinary(14) NULL default NULL,
+
-- Any other parameters to the command
-- Stored as a PHP serialized array, or an empty string if there are no parameters
job_params blob NOT NULL
) /*$wgDBTableOptions*/;
CREATE INDEX /*i*/job_cmd ON /*_*/job (job_cmd, job_namespace, job_title, job_params(128));
+CREATE INDEX /*i*/job_timestamp ON /*_*/job(job_timestamp);
-- Details of updates to cached special pages
diff --git a/maintenance/term/MWTerm.php b/maintenance/term/MWTerm.php
new file mode 100644
index 00000000..36fb8eec
--- /dev/null
+++ b/maintenance/term/MWTerm.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @ingroup Testing
+ *
+ * Set of classes to help with test output and such. Right now pretty specific
+ * to the parser tests but could be more useful one day :)
+ *
+ * @todo Fixme: Make this more generic
+ */
+
+class AnsiTermColorer {
+ function __construct() {
+ }
+
+ /**
+ * Return ANSI terminal escape code for changing text attribs/color
+ *
+ * @param $color String: semicolon-separated list of attribute/color codes
+ * @return String
+ */
+ public function color( $color ) {
+ global $wgCommandLineDarkBg;
+
+ $light = $wgCommandLineDarkBg ? "1;" : "0;";
+
+ return "\x1b[{$light}{$color}m";
+ }
+
+ /**
+ * Return ANSI terminal escape code for restoring default text attributes
+ *
+ * @return String
+ */
+ public function reset() {
+ return $this->color( 0 );
+ }
+}
+
+/* A colour-less terminal */
+class DummyTermColorer {
+ public function color( $color ) {
+ return '';
+ }
+
+ public function reset() {
+ return '';
+ }
+}
+
diff --git a/maintenance/undelete.php b/maintenance/undelete.php
index 7213d096..1c3b14a5 100644
--- a/maintenance/undelete.php
+++ b/maintenance/undelete.php
@@ -44,6 +44,9 @@ class Undelete extends Maintenance {
$this->error( "Invalid title", true );
}
$wgUser = User::newFromName( $user );
+ if ( !$wgUser ) {
+ $this->error( "Invalid username", true );
+ }
$archive = new PageArchive( $title );
$this->output( "Undeleting " . $title->getPrefixedDBkey() . '...' );
$archive->undelete( array(), $reason );
diff --git a/maintenance/update.php b/maintenance/update.php
index 6173befd..c4bf3b22 100644
--- a/maintenance/update.php
+++ b/maintenance/update.php
@@ -89,6 +89,8 @@ class UpdateMediaWiki extends Maintenance {
$this->output( "MediaWiki {$wgVersion} Updater\n\n" );
+ wfWaitForSlaves( 5 ); // let's not kill databases, shall we? ;) --tor
+
if ( !$this->hasOption( 'skip-compat-checks' ) ) {
$this->compatChecks();
} else {
@@ -119,8 +121,12 @@ class UpdateMediaWiki extends Maintenance {
$updater->doUpdates( $updates );
foreach( $updater->getPostDatabaseUpdateMaintenance() as $maint ) {
+ if ( $updater->updateRowExists( $maint ) ) {
+ continue;
+ }
$child = $this->runChild( $maint );
$child->execute();
+ $updater->insertUpdateRow( $maint );
}
$this->output( "\nDone.\n" );
diff --git a/maintenance/updateCollation.php b/maintenance/updateCollation.php
index 7e8a7ee0..023409fa 100644
--- a/maintenance/updateCollation.php
+++ b/maintenance/updateCollation.php
@@ -43,7 +43,7 @@ using the page title and cl_sortkey_prefix. If everything's collation is
up-to-date, it will do nothing.
TEXT;
- $this->addOption( 'force', 'Run on all rows, even if the collation is ' .
+ $this->addOption( 'force', 'Run on all rows, even if the collation is ' .
'supposed to be up-to-date.' );
$this->addOption( 'previous-collation', 'Set the previous value of ' .
'$wgCategoryCollation here to speed up this script, especially if your ' .
@@ -111,7 +111,7 @@ TEXT;
# This is an old-style row, so the sortkey needs to be
# converted.
if ( $row->cl_sortkey == $title->getText()
- || $row->cl_sortkey == $title->getPrefixedText() ) {
+ || $row->cl_sortkey == $title->getPrefixedText() ) {
$prefix = '';
} else {
# Custom sortkey, use it as a prefix
@@ -148,14 +148,14 @@ TEXT;
if ( $force && $row ) {
$encFrom = $dbw->addQuotes( $row->cl_from );
$encTo = $dbw->addQuotes( $row->cl_to );
- $batchConds = array(
+ $batchConds = array(
"(cl_from = $encFrom AND cl_to > $encTo) " .
" OR cl_from > $encFrom" );
}
$count += $res->numRows();
$this->output( "$count done.\n" );
-
+
if ( ++$batchCount % self::SYNC_INTERVAL == 0 ) {
$this->output( "Waiting for slaves ... " );
wfWaitForSlaves();
diff --git a/maintenance/upgrade1_5.php b/maintenance/upgrade1_5.php
index 730e7637..1577c237 100644
--- a/maintenance/upgrade1_5.php
+++ b/maintenance/upgrade1_5.php
@@ -39,6 +39,12 @@ define( 'MW_UPGRADE_CALLBACK', null ); // for self-documentation only
* @ingroup Maintenance
*/
class FiveUpgrade extends Maintenance {
+
+ /**
+ * @var DatabaseBase
+ */
+ protected $db;
+
function __construct() {
parent::__construct();
@@ -321,6 +327,8 @@ class FiveUpgrade extends Maintenance {
/**
* Helper function for copyTable array_filter
+ * @param $x
+ * @return bool
*/
static private function notUpgradeNull( $x ) {
return $x !== MW_UPGRADE_NULL;
@@ -800,8 +808,10 @@ END;
* Rename a given image or archived image file to the converted filename,
* leaving a symlink for URL compatibility.
*
- * @param string $oldname pre-conversion filename
- * @param string $basename pre-conversion base filename for dir hashing, if an archive
+ * @param $oldname string pre-conversion filename
+ * @param $subdirCallback string
+ * @param $basename string pre-conversion base filename for dir hashing, if an archive
+ * @return bool|string
* @access private
*/
function renameFile( $oldname, $subdirCallback = 'wfImageDir', $basename = null ) {
diff --git a/maintenance/userOptions.inc b/maintenance/userOptions.inc
index 6edef9d9..a6659fe7 100644
--- a/maintenance/userOptions.inc
+++ b/maintenance/userOptions.inc
@@ -50,7 +50,14 @@ class userOptions {
}
- /** This is used to check options. Only needed on construction */
+ /**
+ * This is used to check options. Only needed on construction
+ *
+ * @param $opts array
+ * @param $args array
+ *
+ * @return bool
+ */
private function checkOpts( $opts, $args ) {
// The three possible ways to run the script:
$list = isset( $opts['list'] );
@@ -63,7 +70,14 @@ class userOptions {
return $isValid;
}
- /** load script options in the object */
+ /**
+ * load script options in the object
+ *
+ * @param $opts array
+ * @param $args array
+ *
+ * @return true
+ */
private function initializeOpts( $opts, $args ) {
$this->mQuick = isset( $opts['nowarn'] );
@@ -94,8 +108,8 @@ class userOptions {
return false;
}
- $this-> { $this->mMode } ( );
-
+ $this->{ $this->mMode } ( );
+ return true;
}
#
@@ -206,8 +220,10 @@ class userOptions {
}
}
-
- /** Return an array of option names */
+ /**
+ * Return an array of option names
+ * @return array
+ */
public static function getDefaultOptionsNames() {
$def = User::getDefaultOptions();
$ret = array();
@@ -217,7 +233,6 @@ class userOptions {
return $ret;
}
-
#
# Helper methods
#
@@ -250,7 +265,10 @@ USAGE;
exit( 0 );
}
- /** The warning message and countdown */
+ /**
+ * The warning message and countdown
+ * @return bool
+ */
public function warn() {
if ( $this->mQuick ) {
diff --git a/maintenance/userOptions.php b/maintenance/userOptions.php
index 6e1681c3..64368f63 100644
--- a/maintenance/userOptions.php
+++ b/maintenance/userOptions.php
@@ -23,7 +23,7 @@
*
* @file
* @ingroup Maintenance
- * @author Ashar Voultoiz <hashar at free dot fr>
+ * @author Antoine Musso <hashar at free dot fr>
*/
// This is a command line script, load tools and parse args
diff --git a/maintenance/wikipedia-interwiki.sql b/maintenance/wikipedia-interwiki.sql
deleted file mode 100644
index 6a213166..00000000
--- a/maintenance/wikipedia-interwiki.sql
+++ /dev/null
@@ -1,289 +0,0 @@
--- For convenience, here are the *in-project* interwiki prefixes
--- for Wikipedia.
-
-REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES
--- Non-Wikipedia sites:
-('q','http://en.wikiquote.org/wiki/$1',1),
-('b','http://en.wikibooks.org/wiki/$1',1),
-('s','http://en.wikisource.org/wiki/$1',1),
-('n','http://en.wikinews.org/wiki/$1',1),
-('v','http://en.wikiversity.org/wiki/$1',1),
-('meta','http://meta.wikimedia.org/wiki/$1',1),
-('m','http://meta.wikimedia.org/wiki/$1',1),
--- An alphabetical list of Wikipedia sites:
-('aa','http://aa.wikipedia.org/wiki/$1',1),
-('ab','http://ab.wikipedia.org/wiki/$1',1),
-('ace','http://ace.wikipedia.org/wiki/$1',1),
-('af','http://af.wikipedia.org/wiki/$1',1),
-('ak','http://ak.wikipedia.org/wiki/$1',1),
-('als','http://als.wikipedia.org/wiki/$1',1),
-('am','http://am.wikipedia.org/wiki/$1',1),
-('an','http://an.wikipedia.org/wiki/$1',1),
-('ang','http://ang.wikipedia.org/wiki/$1',1),
-('ar','http://ar.wikipedia.org/wiki/$1',1),
-('arc','http://arc.wikipedia.org/wiki/$1',1),
-('arz','http://arz.wikipedia.org/wiki/$1',1),
-('as','http://as.wikipedia.org/wiki/$1',1),
-('ast','http://ast.wikipedia.org/wiki/$1',1),
-('av','http://av.wikipedia.org/wiki/$1',1),
-('ay','http://ay.wikipedia.org/wiki/$1',1),
-('az','http://az.wikipedia.org/wiki/$1',1),
-('ba','http://ba.wikipedia.org/wiki/$1',1),
-('bar','http://bar.wikipedia.org/wiki/$1',1),
-('bat-smg','http://bat-smg.wikipedia.org/wiki/$1',1),
-('bcl','http://bcl.wikipedia.org/wiki/$1',1),
-('be','http://be.wikipedia.org/wiki/$1',1),
-('be-x-old','http://be-x-old.wikipedia.org/wiki/$1',1),
-('bg','http://bg.wikipedia.org/wiki/$1',1),
-('bh','http://bh.wikipedia.org/wiki/$1',1),
-('bi','http://bi.wikipedia.org/wiki/$1',1),
-('bm','http://bm.wikipedia.org/wiki/$1',1),
-('bn','http://bn.wikipedia.org/wiki/$1',1),
-('bo','http://bo.wikipedia.org/wiki/$1',1),
-('bpy','http://bpy.wikipedia.org/wiki/$1',1),
-('br','http://br.wikipedia.org/wiki/$1',1),
-('bs','http://bs.wikipedia.org/wiki/$1',1),
-('bug','http://bug.wikipedia.org/wiki/$1',1),
-('bxr','http://bxr.wikipedia.org/wiki/$1',1),
-('ca','http://ca.wikipedia.org/wiki/$1',1),
-('cbk-zam','http://cbk-zam.wikipedia.org/wiki/$1',1),
-('cdo','http://cdo.wikipedia.org/wiki/$1',1),
-('ce','http://ce.wikipedia.org/wiki/$1',1),
-('ceb','http://ceb.wikipedia.org/wiki/$1',1),
-('ch','http://ch.wikipedia.org/wiki/$1',1),
-('cho','http://cho.wikipedia.org/wiki/$1',1),
-('chr','http://chr.wikipedia.org/wiki/$1',1),
-('chy','http://chy.wikipedia.org/wiki/$1',1),
-('ckb','http://ckb.wikipedia.org/wiki/$1',1),
-('co','http://co.wikipedia.org/wiki/$1',1),
-('cr','http://cr.wikipedia.org/wiki/$1',1),
-('crh','http://crh.wikipedia.org/wiki/$1',1),
-('cs','http://cs.wikipedia.org/wiki/$1',1),
-('csb','http://csb.wikipedia.org/wiki/$1',1),
-('cu','http://cu.wikipedia.org/wiki/$1',1),
-('cv','http://cv.wikipedia.org/wiki/$1',1),
-('cy','http://cy.wikipedia.org/wiki/$1',1),
-('da','http://da.wikipedia.org/wiki/$1',1),
-('de','http://de.wikipedia.org/wiki/$1',1),
-('diq','http://diq.wikipedia.org/wiki/$1',1),
-('dk','http://da.wikipedia.org/wiki/$1',1),
-('dsb','http://dsb.wikipedia.org/wiki/$1',1),
-('dv','http://dv.wikipedia.org/wiki/$1',1),
-('dz','http://dz.wikipedia.org/wiki/$1',1),
-('ee','http://ee.wikipedia.org/wiki/$1',1),
-('el','http://el.wikipedia.org/wiki/$1',1),
-('en','http://en.wikipedia.org/wiki/$1',1),
-('eo','http://eo.wikipedia.org/wiki/$1',1),
-('es','http://es.wikipedia.org/wiki/$1',1),
-('et','http://et.wikipedia.org/wiki/$1',1),
-('eu','http://eu.wikipedia.org/wiki/$1',1),
-('ext','http://ext.wikipedia.org/wiki/$1',1),
-('fa','http://fa.wikipedia.org/wiki/$1',1),
-('ff','http://ff.wikipedia.org/wiki/$1',1),
-('fi','http://fi.wikipedia.org/wiki/$1',1),
-('fiu-vro','http://fiu-vro.wikipedia.org/wiki/$1',1),
-('fj','http://fj.wikipedia.org/wiki/$1',1),
-('fo','http://fo.wikipedia.org/wiki/$1',1),
-('fr','http://fr.wikipedia.org/wiki/$1',1),
-('frp','http://frp.wikipedia.org/wiki/$1',1),
-('fur','http://fur.wikipedia.org/wiki/$1',1),
-('fy','http://fy.wikipedia.org/wiki/$1',1),
-('ga','http://ga.wikipedia.org/wiki/$1',1),
-('gan','http://gan.wikipedia.org/wiki/$1',1),
-('gd','http://gd.wikipedia.org/wiki/$1',1),
-('gl','http://gl.wikipedia.org/wiki/$1',1),
-('glk','http://glk.wikipedia.org/wiki/$1',1),
-('gn','http://gn.wikipedia.org/wiki/$1',1),
-('got','http://got.wikipedia.org/wiki/$1',1),
-('gu','http://gu.wikipedia.org/wiki/$1',1),
-('gv','http://gv.wikipedia.org/wiki/$1',1),
-('ha','http://ha.wikipedia.org/wiki/$1',1),
-('hak','http://hak.wikipedia.org/wiki/$1',1),
-('haw','http://haw.wikipedia.org/wiki/$1',1),
-('he','http://he.wikipedia.org/wiki/$1',1),
-('hi','http://hi.wikipedia.org/wiki/$1',1),
-('hif','http://hif.wikipedia.org/wiki/$1',1),
-('ho','http://ho.wikipedia.org/wiki/$1',1),
-('hr','http://hr.wikipedia.org/wiki/$1',1),
-('hsb','http://hsb.wikipedia.org/wiki/$1',1),
-('ht','http://ht.wikipedia.org/wiki/$1',1),
-('hu','http://hu.wikipedia.org/wiki/$1',1),
-('hy','http://hy.wikipedia.org/wiki/$1',1),
-('hz','http://hz.wikipedia.org/wiki/$1',1),
-('ia','http://ia.wikipedia.org/wiki/$1',1),
-('id','http://id.wikipedia.org/wiki/$1',1),
-('ie','http://ie.wikipedia.org/wiki/$1',1),
-('ig','http://ig.wikipedia.org/wiki/$1',1),
-('ii','http://ii.wikipedia.org/wiki/$1',1),
-('ik','http://ik.wikipedia.org/wiki/$1',1),
-('ilo','http://ilo.wikipedia.org/wiki/$1',1),
-('io','http://io.wikipedia.org/wiki/$1',1),
-('is','http://is.wikipedia.org/wiki/$1',1),
-('it','http://it.wikipedia.org/wiki/$1',1),
-('iu','http://iu.wikipedia.org/wiki/$1',1),
-('ja','http://ja.wikipedia.org/wiki/$1',1),
-('jbo','http://jbo.wikipedia.org/wiki/$1',1),
-('jv','http://jv.wikipedia.org/wiki/$1',1),
-('ka','http://ka.wikipedia.org/wiki/$1',1),
-('kab','http://kab.wikipedia.org/wiki/$1',1),
-('kg','http://kg.wikipedia.org/wiki/$1',1),
-('ki','http://ki.wikipedia.org/wiki/$1',1),
-('kj','http://kj.wikipedia.org/wiki/$1',1),
-('kk','http://kk.wikipedia.org/wiki/$1',1),
-('kl','http://kl.wikipedia.org/wiki/$1',1),
-('km','http://km.wikipedia.org/wiki/$1',1),
-('kn','http://kn.wikipedia.org/wiki/$1',1),
-('ko','http://ko.wikipedia.org/wiki/$1',1),
-('kr','http://kr.wikipedia.org/wiki/$1',1),
-('ks','http://ks.wikipedia.org/wiki/$1',1),
-('ksh','http://ksh.wikipedia.org/wiki/$1',1),
-('ku','http://ku.wikipedia.org/wiki/$1',1),
-('kv','http://kv.wikipedia.org/wiki/$1',1),
-('kw','http://kw.wikipedia.org/wiki/$1',1),
-('ky','http://ky.wikipedia.org/wiki/$1',1),
-('la','http://la.wikipedia.org/wiki/$1',1),
-('lad','http://lad.wikipedia.org/wiki/$1',1),
-('lb','http://lb.wikipedia.org/wiki/$1',1),
-('lbe','http://lbe.wikipedia.org/wiki/$1',1),
-('lg','http://lg.wikipedia.org/wiki/$1',1),
-('li','http://li.wikipedia.org/wiki/$1',1),
-('lij','http://lij.wikipedia.org/wiki/$1',1),
-('lmo','http://lmo.wikipedia.org/wiki/$1',1),
-('ln','http://ln.wikipedia.org/wiki/$1',1),
-('lo','http://lo.wikipedia.org/wiki/$1',1),
-('lt','http://lt.wikipedia.org/wiki/$1',1),
-('lv','http://lv.wikipedia.org/wiki/$1',1),
-('map-bms','http://map-bms.wikipedia.org/wiki/$1',1),
-('mdf','http://mdf.wikipedia.org/wiki/$1',1),
-('mg','http://mg.wikipedia.org/wiki/$1',1),
-('mh','http://mh.wikipedia.org/wiki/$1',1),
-('mhr','http://mhr.wikipedia.org/wiki/$1',1),
-('mi','http://mi.wikipedia.org/wiki/$1',1),
-('minnan','http://zh-min-nan.wikipedia.org/wiki/$1',1),
-('mk','http://mk.wikipedia.org/wiki/$1',1),
-('ml','http://ml.wikipedia.org/wiki/$1',1),
-('mn','http://mn.wikipedia.org/wiki/$1',1),
-('mo','http://mo.wikipedia.org/wiki/$1',1),
-('mr','http://mr.wikipedia.org/wiki/$1',1),
-('ms','http://ms.wikipedia.org/wiki/$1',1),
-('mt','http://mt.wikipedia.org/wiki/$1',1),
-('mus','http://mus.wikipedia.org/wiki/$1',1),
-('mwl','http://mwl.wikipedia.org/wiki/$1',1),
-('my','http://my.wikipedia.org/wiki/$1',1),
-('myv','http://myv.wikipedia.org/wiki/$1',1),
-('mzn','http://mzn.wikipedia.org/wiki/$1',1),
-('na','http://na.wikipedia.org/wiki/$1',1),
-('nah','http://nah.wikipedia.org/wiki/$1',1),
-('nan','http://zh-min-nan.wikipedia.org/wiki/$1',1),
-('nap','http://nap.wikipedia.org/wiki/$1',1),
-('nb','http://nb.wikipedia.org/wiki/$1',1),
-('nds','http://nds.wikipedia.org/wiki/$1',1),
-('nds-nl','http://nds-nl.wikipedia.org/wiki/$1',1),
-('ne','http://ne.wikipedia.org/wiki/$1',1),
-('ng','http://ng.wikipedia.org/wiki/$1',1),
-('nl','http://nl.wikipedia.org/wiki/$1',1),
-('nn','http://nn.wikipedia.org/wiki/$1',1),
-('no','http://no.wikipedia.org/wiki/$1',1),
-('nov','http://nov.wikipedia.org/wiki/$1',1),
-('nrm','http://nrm.wikipedia.org/wiki/$1',1),
-('nv','http://nv.wikipedia.org/wiki/$1',1),
-('ny','http://ny.wikipedia.org/wiki/$1',1),
-('oc','http://oc.wikipedia.org/wiki/$1',1),
-('om','http://om.wikipedia.org/wiki/$1',1),
-('or','http://or.wikipedia.org/wiki/$1',1),
-('os','http://os.wikipedia.org/wiki/$1',1),
-('pa','http://pa.wikipedia.org/wiki/$1',1),
-('pag','http://pag.wikipedia.org/wiki/$1',1),
-('pam','http://pam.wikipedia.org/wiki/$1',1),
-('pap','http://pap.wikipedia.org/wiki/$1',1),
-('pdc','http://pdc.wikipedia.org/wiki/$1',1),
-('pi','http://pi.wikipedia.org/wiki/$1',1),
-('pih','http://pih.wikipedia.org/wiki/$1',1),
-('pl','http://pl.wikipedia.org/wiki/$1',1),
-('pms','http://pms.wikipedia.org/wiki/$1',1),
-('pnb','http://pnb.wikipedia.org/wiki/$1',1),
-('ps','http://ps.wikipedia.org/wiki/$1',1),
-('pt','http://pt.wikipedia.org/wiki/$1',1),
-('qu','http://qu.wikipedia.org/wiki/$1',1),
-('rm','http://rm.wikipedia.org/wiki/$1',1),
-('rmy','http://rmy.wikipedia.org/wiki/$1',1),
-('rn','http://rn.wikipedia.org/wiki/$1',1),
-('ro','http://ro.wikipedia.org/wiki/$1',1),
-('roa-rup','http://roa-rup.wikipedia.org/wiki/$1',1),
-('roa-tara','http://roa-tara.wikipedia.org/wiki/$1',1),
-('ru','http://ru.wikipedia.org/wiki/$1',1),
-('rw','http://rw.wikipedia.org/wiki/$1',1),
-('sa','http://sa.wikipedia.org/wiki/$1',1),
-('sah','http://sah.wikipedia.org/wiki/$1',1),
-('sc','http://sc.wikipedia.org/wiki/$1',1),
-('scn','http://scn.wikipedia.org/wiki/$1',1),
-('sco','http://sco.wikipedia.org/wiki/$1',1),
-('sd','http://sd.wikipedia.org/wiki/$1',1),
-('se','http://se.wikipedia.org/wiki/$1',1),
-('sep11','http://sep11.wikipedia.org/wiki/$1',1),
-('sg','http://sg.wikipedia.org/wiki/$1',1),
-('sh','http://sh.wikipedia.org/wiki/$1',1),
-('si','http://si.wikipedia.org/wiki/$1',1),
-('simple','http://simple.wikipedia.org/wiki/$1',1),
-('sk','http://sk.wikipedia.org/wiki/$1',1),
-('sl','http://sl.wikipedia.org/wiki/$1',1),
-('sm','http://sm.wikipedia.org/wiki/$1',1),
-('sn','http://sn.wikipedia.org/wiki/$1',1),
-('so','http://so.wikipedia.org/wiki/$1',1),
-('sq','http://sq.wikipedia.org/wiki/$1',1),
-('sr','http://sr.wikipedia.org/wiki/$1',1),
-('srn','http://srn.wikipedia.org/wiki/$1',1),
-('ss','http://ss.wikipedia.org/wiki/$1',1),
-('st','http://st.wikipedia.org/wiki/$1',1),
-('stq','http://stq.wikipedia.org/wiki/$1',1),
-('su','http://su.wikipedia.org/wiki/$1',1),
-('sv','http://sv.wikipedia.org/wiki/$1',1),
-('sw','http://sw.wikipedia.org/wiki/$1',1),
-('szl','http://szl.wikipedia.org/wiki/$1',1),
-('ta','http://ta.wikipedia.org/wiki/$1',1),
-('te','http://te.wikipedia.org/wiki/$1',1),
-('tet','http://tet.wikipedia.org/wiki/$1',1),
-('tg','http://tg.wikipedia.org/wiki/$1',1),
-('th','http://th.wikipedia.org/wiki/$1',1),
-('ti','http://ti.wikipedia.org/wiki/$1',1),
-('tk','http://tk.wikipedia.org/wiki/$1',1),
-('tl','http://tl.wikipedia.org/wiki/$1',1),
-('tn','http://tn.wikipedia.org/wiki/$1',1),
-('to','http://to.wikipedia.org/wiki/$1',1),
-('tpi','http://tpi.wikipedia.org/wiki/$1',1),
-('tr','http://tr.wikipedia.org/wiki/$1',1),
-('ts','http://ts.wikipedia.org/wiki/$1',1),
-('tt','http://tt.wikipedia.org/wiki/$1',1),
-('tum','http://tum.wikipedia.org/wiki/$1',1),
-('tw','http://tw.wikipedia.org/wiki/$1',1),
-('ty','http://ty.wikipedia.org/wiki/$1',1),
-('udm','http://udm.wikipedia.org/wiki/$1',1),
-('ug','http://ug.wikipedia.org/wiki/$1',1),
-('uk','http://uk.wikipedia.org/wiki/$1',1),
-('ur','http://ur.wikipedia.org/wiki/$1',1),
-('uz','http://uz.wikipedia.org/wiki/$1',1),
-('ve','http://ve.wikipedia.org/wiki/$1',1),
-('vec','http://vec.wikipedia.org/wiki/$1',1),
-('vi','http://vi.wikipedia.org/wiki/$1',1),
-('vls','http://vls.wikipedia.org/wiki/$1',1),
-('vo','http://vo.wikipedia.org/wiki/$1',1),
-('w','http://en.wikipedia.org/wiki/$1',1),
-('wa','http://wa.wikipedia.org/wiki/$1',1),
-('war','http://war.wikipedia.org/wiki/$1',1),
-('wo','http://wo.wikipedia.org/wiki/$1',1),
-('wuu','http://wuu.wikipedia.org/wiki/$1',1),
-('xal','http://xal.wikipedia.org/wiki/$1',1),
-('xh','http://xh.wikipedia.org/wiki/$1',1),
-('yi','http://yi.wikipedia.org/wiki/$1',1),
-('yo','http://yo.wikipedia.org/wiki/$1',1),
-('yue','http://zh-yue.wikipedia.org/wiki/$1',1),
-('za','http://za.wikipedia.org/wiki/$1',1),
-('zea','http://zea.wikipedia.org/wiki/$1',1),
-('zh','http://zh.wikipedia.org/wiki/$1',1),
-('zh-cfr','http://zh-min-nan.wikipedia.org/wiki/$1',1),
-('zh-classical','http://zh-classical.wikipedia.org/wiki/$1',1),
-('zh-cn','http://zh.wikipedia.org/wiki/$1',1),
-('zh-min-nan','http://zh-min-nan.wikipedia.org/wiki/$1',1),
-('zh-tw','http://zh.wikipedia.org/wiki/$1',1),
-('zh-yue','http://zh-yue.wikipedia.org/wiki/$1',1),
-('zu','http://zu.wikipedia.org/wiki/$1',1);
diff --git a/maintenance/wiktionary-interwiki.sql b/maintenance/wiktionary-interwiki.sql
deleted file mode 100644
index f55235b1..00000000
--- a/maintenance/wiktionary-interwiki.sql
+++ /dev/null
@@ -1,184 +0,0 @@
--- For convenience, here are the *in-project* interwiki prefixes
--- for Wiktionary.
-
-REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES
-('w','http://www.wikipedia.org/wiki/$1',1),
-('m','http://meta.wikipedia.org/wiki/$1',1),
-('meta','http://meta.wikipedia.org/wiki/$1',1),
-('sep11','http://sep11.wikipedia.org/wiki/$1',1),
-('simple','http://simple.wiktionary.org/wiki/$1',1),
-('aa','http://aa.wiktionary.org/wiki/$1',1),
-('ab','http://ab.wiktionary.org/wiki/$1',1),
-('af','http://af.wiktionary.org/wiki/$1',1),
-('ak','http://ak.wiktionary.org/wiki/$1',1),
-('als','http://als.wiktionary.org/wiki/$1',1),
-('am','http://am.wiktionary.org/wiki/$1',1),
-('an','http://an.wiktionary.org/wiki/$1',1),
-('ang','http://ang.wiktionary.org/wiki/$1',1),
-('ar','http://ar.wiktionary.org/wiki/$1',1),
-('as','http://as.wiktionary.org/wiki/$1',1),
-('ast','http://ast.wiktionary.org/wiki/$1',1),
-('av','http://av.wiktionary.org/wiki/$1',1),
-('ay','http://ay.wiktionary.org/wiki/$1',1),
-('az','http://az.wiktionary.org/wiki/$1',1),
-('ba','http://ba.wiktionary.org/wiki/$1',1),
-('be','http://be.wiktionary.org/wiki/$1',1),
-('bg','http://bg.wiktionary.org/wiki/$1',1),
-('bh','http://bh.wiktionary.org/wiki/$1',1),
-('bi','http://bi.wiktionary.org/wiki/$1',1),
-('bm','http://bm.wiktionary.org/wiki/$1',1),
-('bn','http://bn.wiktionary.org/wiki/$1',1),
-('bo','http://bo.wiktionary.org/wiki/$1',1),
-('br','http://br.wiktionary.org/wiki/$1',1),
-('bs','http://bs.wiktionary.org/wiki/$1',1),
-('ca','http://ca.wiktionary.org/wiki/$1',1),
-('ch','http://ch.wiktionary.org/wiki/$1',1),
-('chr','http://chr.wiktionary.org/wiki/$1',1),
-('co','http://co.wiktionary.org/wiki/$1',1),
-('cr','http://cr.wiktionary.org/wiki/$1',1),
-('cs','http://cs.wiktionary.org/wiki/$1',1),
-('csb','http://csb.wiktionary.org/wiki/$1',1),
-('cy','http://cy.wiktionary.org/wiki/$1',1),
-('da','http://da.wiktionary.org/wiki/$1',1),
-('de','http://de.wiktionary.org/wiki/$1',1),
-('dk','http://da.wiktionary.org/wiki/$1',1),
-('dv','http://dv.wiktionary.org/wiki/$1',1),
-('dz','http://dz.wiktionary.org/wiki/$1',1),
-('el','http://el.wiktionary.org/wiki/$1',1),
-('en','http://en.wiktionary.org/wiki/$1',1),
-('eo','http://eo.wiktionary.org/wiki/$1',1),
-('es','http://es.wiktionary.org/wiki/$1',1),
-('et','http://et.wiktionary.org/wiki/$1',1),
-('eu','http://eu.wiktionary.org/wiki/$1',1),
-('fa','http://fa.wiktionary.org/wiki/$1',1),
-('fi','http://fi.wiktionary.org/wiki/$1',1),
-('fj','http://fj.wiktionary.org/wiki/$1',1),
-('fo','http://fo.wiktionary.org/wiki/$1',1),
-('fr','http://fr.wiktionary.org/wiki/$1',1),
-('fy','http://fy.wiktionary.org/wiki/$1',1),
-('ga','http://ga.wiktionary.org/wiki/$1',1),
-('gd','http://gd.wiktionary.org/wiki/$1',1),
-('gl','http://gl.wiktionary.org/wiki/$1',1),
-('gn','http://gn.wiktionary.org/wiki/$1',1),
-('gu','http://gu.wiktionary.org/wiki/$1',1),
-('gv','http://gv.wiktionary.org/wiki/$1',1),
-('ha','http://ha.wiktionary.org/wiki/$1',1),
-('he','http://he.wiktionary.org/wiki/$1',1),
-('hi','http://hi.wiktionary.org/wiki/$1',1),
-('hr','http://hr.wiktionary.org/wiki/$1',1),
-('hsb','http://hsb.wiktionary.org/wiki/$1',1),
-('hu','http://hu.wiktionary.org/wiki/$1',1),
-('hy','http://hy.wiktionary.org/wiki/$1',1),
-('ia','http://ia.wiktionary.org/wiki/$1',1),
-('id','http://id.wiktionary.org/wiki/$1',1),
-('ie','http://ie.wiktionary.org/wiki/$1',1),
-('ik','http://ik.wiktionary.org/wiki/$1',1),
-('io','http://io.wiktionary.org/wiki/$1',1),
-('is','http://is.wiktionary.org/wiki/$1',1),
-('it','http://it.wiktionary.org/wiki/$1',1),
-('iu','http://iu.wiktionary.org/wiki/$1',1),
-('ja','http://ja.wiktionary.org/wiki/$1',1),
-('jbo','http://jbo.wiktionary.org/wiki/$1',1),
-('jv','http://jv.wiktionary.org/wiki/$1',1),
-('ka','http://ka.wiktionary.org/wiki/$1',1),
-('kk','http://kk.wiktionary.org/wiki/$1',1),
-('kl','http://kl.wiktionary.org/wiki/$1',1),
-('km','http://km.wiktionary.org/wiki/$1',1),
-('kn','http://kn.wiktionary.org/wiki/$1',1),
-('ko','http://ko.wiktionary.org/wiki/$1',1),
-('ks','http://ks.wiktionary.org/wiki/$1',1),
-('ku','http://ku.wiktionary.org/wiki/$1',1),
-('kw','http://kw.wiktionary.org/wiki/$1',1),
-('ky','http://ky.wiktionary.org/wiki/$1',1),
-('la','http://la.wiktionary.org/wiki/$1',1),
-('lb','http://lb.wiktionary.org/wiki/$1',1),
-('li','http://li.wiktionary.org/wiki/$1',1),
-('ln','http://ln.wiktionary.org/wiki/$1',1),
-('lo','http://lo.wiktionary.org/wiki/$1',1),
-('lt','http://lt.wiktionary.org/wiki/$1',1),
-('lv','http://lv.wiktionary.org/wiki/$1',1),
-('mg','http://mg.wiktionary.org/wiki/$1',1),
-('mh','http://mh.wiktionary.org/wiki/$1',1),
-('mi','http://mi.wiktionary.org/wiki/$1',1),
-('mk','http://mk.wiktionary.org/wiki/$1',1),
-('ml','http://ml.wiktionary.org/wiki/$1',1),
-('mn','http://mn.wiktionary.org/wiki/$1',1),
-('mo','http://mo.wiktionary.org/wiki/$1',1),
-('mr','http://mr.wiktionary.org/wiki/$1',1),
-('ms','http://ms.wiktionary.org/wiki/$1',1),
-('mt','http://mt.wiktionary.org/wiki/$1',1),
-('my','http://my.wiktionary.org/wiki/$1',1),
-('na','http://na.wiktionary.org/wiki/$1',1),
-('nah','http://nah.wiktionary.org/wiki/$1',1),
-('nb', 'http://no.wiktionary.org/wiki/$1',1),
-('nds','http://nds.wiktionary.org/wiki/$1',1),
-('ne','http://ne.wiktionary.org/wiki/$1',1),
-('nl','http://nl.wiktionary.org/wiki/$1',1),
-('nn','http://nn.wiktionary.org/wiki/$1',1),
-('no','http://no.wiktionary.org/wiki/$1',1),
-('oc','http://oc.wiktionary.org/wiki/$1',1),
-('om','http://om.wiktionary.org/wiki/$1',1),
-('or','http://or.wiktionary.org/wiki/$1',1),
-('pa','http://pa.wiktionary.org/wiki/$1',1),
-('pi','http://pi.wiktionary.org/wiki/$1',1),
-('pl','http://pl.wiktionary.org/wiki/$1',1),
-('ps','http://ps.wiktionary.org/wiki/$1',1),
-('pt','http://pt.wiktionary.org/wiki/$1',1),
-('qu','http://qu.wiktionary.org/wiki/$1',1),
-('rm','http://rm.wiktionary.org/wiki/$1',1),
-('rn','http://rn.wiktionary.org/wiki/$1',1),
-('ro','http://ro.wiktionary.org/wiki/$1',1),
-('roa-rup','http://roa-rup.wiktionary.org/wiki/$1',1),
-('ru','http://ru.wiktionary.org/wiki/$1',1),
-('rw','http://rw.wiktionary.org/wiki/$1',1),
-('sa','http://sa.wiktionary.org/wiki/$1',1),
-('sc','http://sc.wiktionary.org/wiki/$1',1),
-('scn','http://scn.wiktionary.org/wiki/$1',1),
-('sd','http://sd.wiktionary.org/wiki/$1',1),
-('sg','http://sg.wiktionary.org/wiki/$1',1),
-('sh','http://sh.wiktionary.org/wiki/$1',1),
-('si','http://si.wiktionary.org/wiki/$1',1),
-('sk','http://sk.wiktionary.org/wiki/$1',1),
-('sl','http://sl.wiktionary.org/wiki/$1',1),
-('sm','http://sm.wiktionary.org/wiki/$1',1),
-('sn','http://sn.wiktionary.org/wiki/$1',1),
-('so','http://so.wiktionary.org/wiki/$1',1),
-('sq','http://sq.wiktionary.org/wiki/$1',1),
-('sr','http://sr.wiktionary.org/wiki/$1',1),
-('ss','http://ss.wiktionary.org/wiki/$1',1),
-('st','http://st.wiktionary.org/wiki/$1',1),
-('su','http://su.wiktionary.org/wiki/$1',1),
-('sv','http://sv.wiktionary.org/wiki/$1',1),
-('sw','http://sw.wiktionary.org/wiki/$1',1),
-('ta','http://ta.wiktionary.org/wiki/$1',1),
-('te','http://te.wiktionary.org/wiki/$1',1),
-('tg','http://tg.wiktionary.org/wiki/$1',1),
-('th','http://th.wiktionary.org/wiki/$1',1),
-('ti','http://ti.wiktionary.org/wiki/$1',1),
-('tk','http://tk.wiktionary.org/wiki/$1',1),
-('tl','http://tl.wiktionary.org/wiki/$1',1),
-('tn','http://tn.wiktionary.org/wiki/$1',1),
-('to','http://to.wiktionary.org/wiki/$1',1),
-('tpi','http://tpi.wiktionary.org/wiki/$1',1),
-('tr','http://tr.wiktionary.org/wiki/$1',1),
-('ts','http://ts.wiktionary.org/wiki/$1',1),
-('tt','http://tt.wiktionary.org/wiki/$1',1),
-('tw','http://tw.wiktionary.org/wiki/$1',1),
-('ug','http://ug.wiktionary.org/wiki/$1',1),
-('uk','http://uk.wiktionary.org/wiki/$1',1),
-('ur','http://ur.wiktionary.org/wiki/$1',1),
-('uz','http://uz.wiktionary.org/wiki/$1',1),
-('vi','http://vi.wiktionary.org/wiki/$1',1),
-('vo','http://vo.wiktionary.org/wiki/$1',1),
-('wa','http://wa.wiktionary.org/wiki/$1',1),
-('wo','http://wo.wiktionary.org/wiki/$1',1),
-('xh','http://xh.wiktionary.org/wiki/$1',1),
-('yi','http://yi.wiktionary.org/wiki/$1',1),
-('yo','http://yo.wiktionary.org/wiki/$1',1),
-('za','http://za.wiktionary.org/wiki/$1',1),
-('zh','http://zh.wiktionary.org/wiki/$1',1),
-('zh-cn','http://zh.wiktionary.org/wiki/$1',1),
-('zh-min-nan','http://zh-min-nan.wiktionary.org/wiki/$1',1),
-('zh-tw','http://zh.wiktionary.org/wiki/$1',1),
-('zu','http://zu.wiktionary.org/wiki/$1',1);
-