feat: Mediawiki added, extensions added
This commit is contained in:
parent
f0d1fd3f58
commit
c0fb067595
|
|
@ -1,5 +1,4 @@
|
|||
node_modules/
|
||||
mediawiki/
|
||||
composer.phar
|
||||
mediawiki/cache/
|
||||
mediawiki/images/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
# local build artifacts that must not be included
|
||||
/composer.lock
|
||||
/node_modules
|
||||
/vendor
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = tab
|
||||
tab_width = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
# Ensure text editors don't turn leading spaces into tabs,
|
||||
# e.g. in multi-line bullet list items
|
||||
[*.md]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# Tabs may not be valid YAML
|
||||
# @see https://yaml.org/spec/1.2/spec.html#id2777534
|
||||
[*.{yml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[.git/**]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# Trailing whitespace is intended in parser test files
|
||||
# T278066
|
||||
[tests/parser/*.txt]
|
||||
trim_trailing_whitespace = false
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
# Upstream code
|
||||
/resources/lib/
|
||||
/resources/src/mediawiki.libs.jpegmeta/
|
||||
|
||||
# Skip functions
|
||||
/resources/src/skip-*
|
||||
|
||||
# Build tooling
|
||||
/docs/coverage/
|
||||
/docs/html/
|
||||
/docs/js/
|
||||
/docs/latex/
|
||||
/vendor/
|
||||
/tests/coverage/
|
||||
|
||||
# Test data
|
||||
/tests/phpunit/data/registration/duplicate_keys.json
|
||||
/tests/phpunit/data/resourceloader/codex/
|
||||
/tests/phpunit/data/resourceloader/codex-devmode/
|
||||
/tests/phpunit/data/SelserContext/*.json
|
||||
/tests/phpunit/unit/includes/Settings/Source/fixtures/bad.json
|
||||
/tests/phpunit/**/*malformed*.json
|
||||
/maintenance/benchmarks/data/
|
||||
|
||||
# Nested projects
|
||||
/extensions/
|
||||
/skins/
|
||||
|
||||
# Language files written automatically by TranslateWiki
|
||||
/**/i18n/**/*.json
|
||||
!/**/i18n/**/en.json
|
||||
!/**/i18n/**/qqq.json
|
||||
|
||||
# Ignore directories where MW may write internal files (T291674)
|
||||
# Ref $wgCacheDirectory (installer)
|
||||
# Ref $wgUploadDirectory (run-time default)
|
||||
/cache/
|
||||
/images/
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"wikimedia/server"
|
||||
],
|
||||
"rules": {
|
||||
"max-len": "warn"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
# This file declares MediaWiki scenarios for Fresnel, a web page performance
|
||||
# monitoring tool. See <https://wikitech.wikimedia.org/wiki/Performance/Fresnel>.
|
||||
|
||||
warmup: true
|
||||
runs: 7
|
||||
scenarios:
|
||||
Read a page:
|
||||
# The only page that exists by default is the main page.
|
||||
# But its actual name is configurable/unknown (T216791).
|
||||
# Omit 'title' to let MediaWiki show the default (which is the main page),
|
||||
# and a query string to prevent a normalization redirect.
|
||||
url: "{MW_SERVER}{MW_SCRIPT_PATH}/index.php?noredirectplz"
|
||||
viewport:
|
||||
width: 1100
|
||||
height: 700
|
||||
reports:
|
||||
- navtiming
|
||||
- paint
|
||||
- transfer
|
||||
probes:
|
||||
- screenshot
|
||||
- trace
|
||||
Load the editor:
|
||||
url: "{MW_SERVER}{MW_SCRIPT_PATH}/index.php?action=edit"
|
||||
viewport:
|
||||
width: 1100
|
||||
height: 700
|
||||
reports:
|
||||
- navtiming
|
||||
- paint
|
||||
- transfer
|
||||
probes:
|
||||
- screenshot
|
||||
- trace
|
||||
View history of a page:
|
||||
url: "{MW_SERVER}{MW_SCRIPT_PATH}/index.php?action=history"
|
||||
viewport:
|
||||
width: 1100
|
||||
height: 700
|
||||
reports:
|
||||
- navtiming
|
||||
- paint
|
||||
- transfer
|
||||
probes:
|
||||
- screenshot
|
||||
- trace
|
||||
View recent changes:
|
||||
url: "{MW_SERVER}{MW_SCRIPT_PATH}/index.php?title=Special:RecentChanges"
|
||||
viewport:
|
||||
width: 1100
|
||||
height: 700
|
||||
reports:
|
||||
- navtiming
|
||||
- paint
|
||||
- transfer
|
||||
probes:
|
||||
- screenshot
|
||||
- trace
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# mass code style changes - array syntax
|
||||
0077c5da15aab081125ee1c72cc4d95225e4ff5f
|
||||
110a5877e9e6ebe7a6ecd758f5812f32fc4ef57e
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
*.sh eol=lf
|
||||
*.icc binary
|
||||
*.webp binary
|
||||
*.mp3 binary
|
||||
*.map.json binary
|
||||
*~ export-ignore
|
||||
#*# export-ignore
|
||||
.* export-ignore
|
||||
*.htaccess -export-ignore
|
||||
package.json export-ignore
|
||||
package-lock.json export-ignore
|
||||
Gruntfile.js export-ignore
|
||||
Gemfile* export-ignore
|
||||
vendor/pear/net_smtp/README.rst export-ignore
|
||||
phpunit.xml.dist export-ignore
|
||||
DEVELOPERS.md export-ignore
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
# Repository management
|
||||
.svn
|
||||
|
||||
# git-deploy status file:
|
||||
/.deploy
|
||||
|
||||
# Editors
|
||||
*.kate-swp
|
||||
*~
|
||||
\#*#
|
||||
.#*
|
||||
.*.swp
|
||||
.project
|
||||
cscope.files
|
||||
cscope.out
|
||||
*.orig
|
||||
## NetBeans
|
||||
nbproject*
|
||||
project.index
|
||||
## Sublime
|
||||
sublime-*
|
||||
sftp-config.json
|
||||
## Visual Studio Code
|
||||
*.vscode/
|
||||
|
||||
# MediaWiki install & usage
|
||||
/cache
|
||||
/logs
|
||||
/docs/coverage
|
||||
/docs/js
|
||||
/docs/latex
|
||||
/images/[0-9a-f]
|
||||
/images/archive
|
||||
/images/cache
|
||||
/images/deleted
|
||||
/images/lockdir
|
||||
/images/temp
|
||||
/images/thumb
|
||||
## Extension:EasyTimeline
|
||||
/images/timeline
|
||||
## Extension:Score
|
||||
/images/lilypond
|
||||
## Extension:Phonos
|
||||
/images/phonos-render
|
||||
## Extension:TimedMediaHandler
|
||||
/images/transcoded
|
||||
/images/tmp
|
||||
/maintenance/.mweval_history
|
||||
/maintenance/.mwsql_history
|
||||
/LocalSettings.php
|
||||
/includes/PlatformSettings.php
|
||||
|
||||
# Building & testing
|
||||
npm-debug.log
|
||||
node_modules/
|
||||
/resources/lib/.foreign
|
||||
/tests/phpunit/phpunit.phar
|
||||
.phpunit.result.cache
|
||||
/tests/phpunit/.phpunit.result.cache
|
||||
phpunit.xml
|
||||
/tests/selenium/log
|
||||
.eslintcache
|
||||
.api-testing.config.json
|
||||
.phan/local-config.php
|
||||
|
||||
# Composer
|
||||
/composer.lock
|
||||
/composer.local.json
|
||||
/composer.phar
|
||||
|
||||
# Operating systems
|
||||
## Mac OS X
|
||||
.DS_Store
|
||||
## Windows
|
||||
Thumbs.db
|
||||
|
||||
# Misc
|
||||
.buildpath
|
||||
.classpath
|
||||
.idea
|
||||
*.iml
|
||||
.metadata*
|
||||
.settings
|
||||
/favicon.ico
|
||||
/static*
|
||||
/tags
|
||||
/.htaccess
|
||||
/.htpasswd
|
||||
*.rej
|
||||
|
||||
# Docker
|
||||
docker-compose.override.yml
|
||||
.env
|
||||
/.stylelintcache
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
component: Some awesome subject
|
||||
|
||||
Why:
|
||||
|
||||
- …
|
||||
|
||||
What:
|
||||
|
||||
- …
|
||||
|
||||
Bug: TXXXXX
|
||||
#
|
||||
# When in doubt, consult https://www.mediawiki.org/wiki/Gerrit/Commit_message_guidelines
|
||||
#
|
||||
# - Subject should be 50 characters or less
|
||||
# - Separate body from subject
|
||||
# - Use imperative mood, avoid passive voice
|
||||
# - Wrap the body text at 72 chars
|
||||
#
|
||||
# Explain "why" and "what". If it does not make sense to include
|
||||
# this in your commit message, then delete those sections.
|
||||
#
|
||||
# Don't forget the Bug: line
|
||||
# Don't leave a blank line after the Bug: line
|
||||
#
|
||||
# If you are unsure about what to use for component:
|
||||
# - "HookContainer" could work for changes to include/HookContainer
|
||||
# - "phpunit" for changes to PHPUnit tests
|
||||
# - "Authentication" for changes affecting multiple sections
|
||||
# relating to user authentication
|
||||
#
|
||||
# Hint: you can enable this to be used as a template for git commit
|
||||
# git config commit.template .gitmessage
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
[submodule "extensions/AbuseFilter"]
|
||||
path = extensions/AbuseFilter
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/AbuseFilter
|
||||
branch = REL1_43
|
||||
[submodule "extensions/CategoryTree"]
|
||||
path = extensions/CategoryTree
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/CategoryTree
|
||||
branch = REL1_43
|
||||
[submodule "extensions/Cite"]
|
||||
path = extensions/Cite
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/Cite
|
||||
branch = REL1_43
|
||||
[submodule "extensions/CiteThisPage"]
|
||||
path = extensions/CiteThisPage
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/CiteThisPage
|
||||
branch = REL1_43
|
||||
[submodule "extensions/CodeEditor"]
|
||||
path = extensions/CodeEditor
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/CodeEditor
|
||||
branch = REL1_43
|
||||
[submodule "extensions/ConfirmEdit"]
|
||||
path = extensions/ConfirmEdit
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/ConfirmEdit
|
||||
branch = REL1_43
|
||||
[submodule "extensions/DiscussionTools"]
|
||||
path = extensions/DiscussionTools
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/DiscussionTools
|
||||
branch = REL1_43
|
||||
[submodule "extensions/Echo"]
|
||||
path = extensions/Echo
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo
|
||||
branch = REL1_43
|
||||
[submodule "extensions/Gadgets"]
|
||||
path = extensions/Gadgets
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/Gadgets
|
||||
branch = REL1_43
|
||||
[submodule "extensions/ImageMap"]
|
||||
path = extensions/ImageMap
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/ImageMap
|
||||
branch = REL1_43
|
||||
[submodule "extensions/InputBox"]
|
||||
path = extensions/InputBox
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/InputBox
|
||||
branch = REL1_43
|
||||
[submodule "extensions/Interwiki"]
|
||||
path = extensions/Interwiki
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/Interwiki
|
||||
branch = REL1_43
|
||||
[submodule "extensions/Linter"]
|
||||
path = extensions/Linter
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/Linter
|
||||
branch = REL1_43
|
||||
[submodule "extensions/LoginNotify"]
|
||||
path = extensions/LoginNotify
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/LoginNotify
|
||||
branch = REL1_43
|
||||
[submodule "extensions/Math"]
|
||||
path = extensions/Math
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/Math
|
||||
branch = REL1_43
|
||||
[submodule "extensions/MultimediaViewer"]
|
||||
path = extensions/MultimediaViewer
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/MultimediaViewer
|
||||
branch = REL1_43
|
||||
[submodule "extensions/Nuke"]
|
||||
path = extensions/Nuke
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/Nuke
|
||||
branch = REL1_43
|
||||
[submodule "extensions/OATHAuth"]
|
||||
path = extensions/OATHAuth
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/OATHAuth
|
||||
branch = REL1_43
|
||||
[submodule "extensions/PageImages"]
|
||||
path = extensions/PageImages
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/PageImages
|
||||
branch = REL1_43
|
||||
[submodule "extensions/ParserFunctions"]
|
||||
path = extensions/ParserFunctions
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/ParserFunctions
|
||||
branch = REL1_43
|
||||
[submodule "extensions/PdfHandler"]
|
||||
path = extensions/PdfHandler
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/PdfHandler
|
||||
branch = REL1_43
|
||||
[submodule "extensions/Poem"]
|
||||
path = extensions/Poem
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/Poem
|
||||
branch = REL1_43
|
||||
[submodule "extensions/ReplaceText"]
|
||||
path = extensions/ReplaceText
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/ReplaceText
|
||||
branch = REL1_43
|
||||
[submodule "extensions/Scribunto"]
|
||||
path = extensions/Scribunto
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/Scribunto
|
||||
branch = REL1_43
|
||||
[submodule "extensions/SecureLinkFixer"]
|
||||
path = extensions/SecureLinkFixer
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/SecureLinkFixer
|
||||
branch = REL1_43
|
||||
[submodule "extensions/SpamBlacklist"]
|
||||
path = extensions/SpamBlacklist
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/SpamBlacklist
|
||||
branch = REL1_43
|
||||
[submodule "extensions/SyntaxHighlight_GeSHi"]
|
||||
path = extensions/SyntaxHighlight_GeSHi
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/SyntaxHighlight_GeSHi
|
||||
branch = REL1_43
|
||||
[submodule "extensions/TemplateData"]
|
||||
path = extensions/TemplateData
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/TemplateData
|
||||
branch = REL1_43
|
||||
[submodule "extensions/TextExtracts"]
|
||||
path = extensions/TextExtracts
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/TextExtracts
|
||||
branch = REL1_43
|
||||
[submodule "extensions/Thanks"]
|
||||
path = extensions/Thanks
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/Thanks
|
||||
branch = REL1_43
|
||||
[submodule "extensions/TitleBlacklist"]
|
||||
path = extensions/TitleBlacklist
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/TitleBlacklist
|
||||
branch = REL1_43
|
||||
[submodule "extensions/VisualEditor"]
|
||||
path = extensions/VisualEditor
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
|
||||
branch = REL1_43
|
||||
[submodule "extensions/WikiEditor"]
|
||||
path = extensions/WikiEditor
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/extensions/WikiEditor
|
||||
branch = REL1_43
|
||||
[submodule "skins/MinervaNeue"]
|
||||
path = skins/MinervaNeue
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/skins/MinervaNeue
|
||||
branch = REL1_43
|
||||
[submodule "skins/MonoBook"]
|
||||
path = skins/MonoBook
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/skins/MonoBook
|
||||
branch = REL1_43
|
||||
[submodule "skins/Timeless"]
|
||||
path = skins/Timeless
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/skins/Timeless
|
||||
branch = REL1_43
|
||||
[submodule "skins/Vector"]
|
||||
path = skins/Vector
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/skins/Vector
|
||||
branch = REL1_43
|
||||
[submodule "vendor"]
|
||||
path = vendor
|
||||
url = https://gerrit.wikimedia.org/r/mediawiki/vendor
|
||||
branch = REL1_43
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
[gerrit]
|
||||
host=gerrit.wikimedia.org
|
||||
port=29418
|
||||
project=mediawiki/core.git
|
||||
track=1
|
||||
defaultrebase=0
|
||||
|
|
@ -0,0 +1,588 @@
|
|||
# Map author and committer names and email addresses to canonical real names
|
||||
# and email addresses.
|
||||
#
|
||||
# To update the CREDITS file, run maintenance/updateCredits.php
|
||||
#
|
||||
# Two types of entries are useful here. The first sets a canonical author
|
||||
# name for a given email address:
|
||||
#
|
||||
# Canonical Author Name <author email>
|
||||
#
|
||||
# The second allows collecting alternate email addresses into a single
|
||||
# canonical author name and email address:
|
||||
#
|
||||
# Canonical Author Name <author email> <alternate email>
|
||||
#
|
||||
# Mappings are only needed for authors who have used multiple author names
|
||||
# and/or author emails for revisions over time. Author names beginning with
|
||||
# "[BOT]" will be omitted from the CREDITS file.
|
||||
#
|
||||
# See also: https://git-scm.com/docs/git-shortlog#_mapping_authors
|
||||
#
|
||||
[BOT] Gerrit Code Review <gerrit@wikimedia.org>
|
||||
[BOT] Gerrit Patch Uploader <gerritpatchuploader@gmail.com>
|
||||
[BOT] jenkins-bot <jenkins-bot@gerrit.wikimedia.org>
|
||||
[BOT] jenkins-bot <jenkins-bot@gerrit.wikimedia.org> <jenkins-bot@wikimedia.org>
|
||||
[BOT] Translation updater bot <l10n-bot@translatewiki.net>
|
||||
[BOT] libraryupgrader <tools.libraryupgrader@tools.wmflabs.org>
|
||||
Aaron Schulz <aschulz@wikimedia.org>
|
||||
Aaron Schulz <aschulz@wikimedia.org> <aaron@users.mediawiki.org>
|
||||
Abijeet Patro <apatro@wikimedia.org>
|
||||
Abijeet Patro <apatro@wikimedia.org> <abijeetpatro@gmail.com>
|
||||
Adam Roses Wight <adam.wight@wikimedia.de>
|
||||
Adam Roses Wight <adam.wight@wikimedia.de> <awight@wikimedia.org>
|
||||
Adam Roses Wight <adam.wight@wikimedia.de> <spam@ludd.net>
|
||||
addshore <addshorewiki@gmail.com>
|
||||
addshore <addshorewiki@gmail.com> <adamshorland@gmail.com>
|
||||
Aditya Sastry <ganeshaditya1@gmail.com>
|
||||
Adrian Heine <adrian.heine@wikimedia.de>
|
||||
Alangi Derick <alangiderick@gmail.com>
|
||||
Alangi Derick <alangiderick@gmail.com> <alangiderick@gmail.com>
|
||||
Alangi Derick <alangiderick@gmail.com> <xsavitar.wiki@aol.com>
|
||||
Alex Paskulin <apaskulin@wikimedia.org>
|
||||
Alex Z. <mrzmanwiki@gmail.com> <mrzman@users.mediawiki.org>
|
||||
Aleksey Bekh-Ivanov <aleksey.bekh-ivanov@wikimedia.de>
|
||||
Alexandre Emsenhuber <ialex.wiki@gmail.com>
|
||||
Alexandre Emsenhuber <ialex.wiki@gmail.com> <ialex@users.mediawiki.org>
|
||||
Alexandre Emsenhuber <ialex.wiki@gmail.com> <mediawiki@emsenhuber.ch>
|
||||
Alexander Mashin <alex.mashin@gmail.com>
|
||||
Alexander Monk <krenair@gmail.com>
|
||||
Alexander Monk <krenair@gmail.com> <alex@wikimedia.org>
|
||||
Alexander Monk <krenair@gmail.com> <krenair@wikimedia.org>
|
||||
Alexander Vorwerk <zabe@avorwerk.net>
|
||||
Alexander Vorwerk <zabe@avorwerk.net> <alec@vc-celle.de>
|
||||
Alexander Vorwerk <zabe@avorwerk.net> <alexander.vorwerk@stud.uni-goettingen.de>
|
||||
Alexia E. Smith <washuu@gmail.com>
|
||||
alistair3149 <alistair31494322@gmail.com>
|
||||
AlQaholic007 <soham.parekh1998@gmail.com>
|
||||
Amir E. Aharoni <amir.aharoni@mail.huji.ac.il>
|
||||
Amir E. Aharoni <amir.aharoni@mail.huji.ac.il> <amire80@users.mediawiki.org>
|
||||
Amir Sarabadani <ladsgroup@gmail.com> <Ladsgroup@gmail.com>
|
||||
Anders Wegge Jakobsen <awegge@gmail.com> <wegge@users.mediawiki.org>
|
||||
Andre Engels <andreengels@gmail.com> <a_engels@users.mediawiki.org>
|
||||
Andrew Garrett <agarrett@wikimedia.org>
|
||||
Andrew Garrett <agarrett@wikimedia.org> <werdna@users.mediawiki.org>
|
||||
Andrew Otto <aotto@wikimedia.org>
|
||||
Andrew Otto <aotto@wikimedia.org> <acotto@gmail.com>
|
||||
Angela Beesley Starling <wiki@nge.la> <angelab@users.mediawiki.org>
|
||||
Antoine Musso <hashar@free.fr>
|
||||
Antoine Musso <hashar@free.fr> <hashar@users.mediawiki.org>
|
||||
Aran Dunkley <aran@organicdesign.co.nz> <nad@users.mediawiki.org>
|
||||
Ariel Glenn <ariel@wikimedia.org> <ariel@users.mediawiki.org>
|
||||
Ariel Glenn <ariel@wikimedia.org> <ariel@wikimedia.org>
|
||||
Arlo Breault <abreault@wikimedia.org>
|
||||
ArtBaltai <art.baltai@speedandfunction.com>
|
||||
Arthur Richards <arichards@wikimedia.org>
|
||||
Arthur Richards <arichards@wikimedia.org> <awjrichards@users.mediawiki.org>
|
||||
Aryeh Gregor <ayg@aryeh.name>
|
||||
Aryeh Gregor <ayg@aryeh.name> <simetrical@users.mediawiki.org>
|
||||
Asher Feldman <afeldman@wikimedia.org>
|
||||
Asher Feldman <afeldman@wikimedia.org> <asher@users.mediawiki.org>
|
||||
aude <aude.wiki@gmail.com>
|
||||
Audrey Tang <audreyt@audreyt.org>
|
||||
Audrey Tang <audreyt@audreyt.org> <au@localhost>
|
||||
ayush_garg <ayush.ce13@iitp.ac.in>
|
||||
Bae Junehyeon <devunt@gmail.com>
|
||||
Bahodir Mansurov <bmansurov@wikimedia.org>
|
||||
Bartosz Dziewoński <dziewonski@fastmail.fm>
|
||||
Bartosz Dziewoński <dziewonski@fastmail.fm> <matma.rex@gmail.com>
|
||||
Bartosz Dziewoński <dziewonski@fastmail.fm> <bdziewonski@wikimedia.org>
|
||||
Bartosz Dziewoński <dziewonski@fastmail.fm> <matmarex@wikimedia.org>
|
||||
Ben Hartshorne <bhartshorne@wikimedia.org> <ben@users.mediawiki.org>
|
||||
Bene <benestar.wikimedia@gmail.com>
|
||||
Bene <benestar.wikimedia@gmail.com> <benestar.wikimedia@googlemail.com>
|
||||
Benny Situ <bsitu@wikimedia.org>
|
||||
Benny Situ <bsitu@wikimedia.org> <bsitu@users.mediawiki.org>
|
||||
Bernard Wang <bwang@wikimedia.org>
|
||||
Bertrand Grondin <bertrand.grondin@tiscali.fr> <grondin@users.mediawiki.org>
|
||||
Bill Pirkle <bpirkle@wikimedia.org>
|
||||
Bill Pirkle <bpirkle@wikimedia.org> <bpirkle@wikipedia.org>
|
||||
Brad Jorsch <bjorsch@wikimedia.org>
|
||||
Brad Jorsch <bjorsch@wikimedia.org> <anomie.wikipedia@gmail.com>
|
||||
Brandon Harris <bharris@wikimedia.org> <bharris@users.mediawiki.org>
|
||||
BrandonXLF <brandfowl@gmail.com>
|
||||
Brent Garber <overlordq@gmail.com>
|
||||
Brent Garber <overlordq@gmail.com> <wikipedia@thedarkcitadel.com>
|
||||
Brent Garber <overlordq@gmail.com> <overlordq@users.mediawiki.org>
|
||||
Brian Wolff <bawolff+wn@gmail.com>
|
||||
Brian Wolff <bawolff+wn@gmail.com> <bawolff+svn@gmail.com>
|
||||
Brian Wolff <bawolff+wn@gmail.com> <bawolff@users.mediawiki.org>
|
||||
Brooke Vibber <bvibber@wikimedia.org>
|
||||
Brooke Vibber <bvibber@wikimedia.org> <brion@wikimedia.org>
|
||||
Brooke Vibber <bvibber@wikimedia.org> <brion@pobox.com>
|
||||
Brooke Vibber <bvibber@wikimedia.org> <brion@users.mediawiki.org>
|
||||
Bryan Davis <bd808@wikimedia.org>
|
||||
Bryan Davis <bd808@wikimedia.org> <bd808@bd808.com>
|
||||
Bryan Tong Minh <bryan.tongminh@gmail.com>
|
||||
Bryan Tong Minh <bryan.tongminh@gmail.com> <btongminh@users.mediawiki.org>
|
||||
C. Scott Ananian <cscott@cscott.net>
|
||||
C. Scott Ananian <cscott@cscott.net> <cananian@wikimedia.org>
|
||||
Cacycle <cacyclewp@gmail.com>
|
||||
cenarium <cenarium.sysop@gmail.com>
|
||||
Chad Horohoe <chadh@wikimedia.org>
|
||||
Chad Horohoe <chadh@wikimedia.org> <demon@users.mediawiki.org>
|
||||
Charles Melbye <charlie@yourwiki.net> <charlie@users.mediawiki.org>
|
||||
Chiefwei <chiefwei1989@gmail.com>
|
||||
Chris Koerner <ckoerner@wikimedia.org>
|
||||
Chris McMahon <cmcmahon@wikimedia.org>
|
||||
Chris Steipp <csteipp@wikimedia.org>
|
||||
Christian Aistleitner <christian@quelltextlich.at>
|
||||
Christian Aistleitner <christian@quelltextlich.at> <qchris@users.mediawiki.org>
|
||||
Christian Williams <orbit@framezero.com>
|
||||
Christian Williams <orbit@framezero.com> <christian@localhost>
|
||||
Christian Williams <orbit@framezero.com> <christian@wikia-inc.com>
|
||||
Christoph Jauera <christoph.jauera@wikimedia.de>
|
||||
Christoph Jauera <christoph.jauera@wikimedia.de> <christoph.fischer@wikimedia.de>
|
||||
Christopher Johnson <root@bugzilla.wmde.de>
|
||||
church of emacs <churchofemacs@users.mediawiki.org>
|
||||
Clara Andrew-Wani <candrewwani@gmail.com>
|
||||
Clara Andrew-Wani <candrewwani@gmail.com> <candrewwani@gmail.com>
|
||||
Cindy Cicalese <ccicalese@wikimedia.org>
|
||||
Cindy Cicalese <ccicalese@wikimedia.org> <cicalese@mitre.org>
|
||||
Cindy Cicalese <ccicalese@wikimedia.org> <cindom@gmail.com>
|
||||
ckoerner <nobelx@gmail.com>
|
||||
Conrad Irwin <conrad.irwin+wiki@gmail.com> <conrad@users.mediawiki.org>
|
||||
Cyndy Simiyu <csimiyu@wikimedia.org>
|
||||
Dan Duvall <dduvall@wikimedia.org>
|
||||
dan-nl <d_entous@yahoo.com>
|
||||
Daniel A. R. Werner <daniel.a.r.werner@gmail.com>
|
||||
Daniel Cannon <cannon.danielc@gmail.com> <amidaniel@users.mediawiki.org>
|
||||
Daniel Friesen <mediawiki@danielfriesen.name>
|
||||
Daniel Friesen <mediawiki@danielfriesen.name> <daniel@nadir-seen-fire.com>
|
||||
Daniel Friesen <mediawiki@danielfriesen.name> <dantman@users.mediawiki.org>
|
||||
Daniel Friesen <mediawiki@danielfriesen.name> <pub-github@nadir-seen-fire.com>
|
||||
Daniel Kinzler <dkinzler@wikimedia.org>
|
||||
Daniel Kinzler <dkinzler@wikimedia.org> <daniel.kinzler@wikimedia.de>
|
||||
Daniel Kinzler <dkinzler@wikimedia.org> <daniel@users.mediawiki.org>
|
||||
Daniel Renfro <bluecurio@gmail.com> <drenfro@vistaprint.com>
|
||||
Danny B. <Wikipedia.Danny.B@email.cz>
|
||||
Danny B. <Wikipedia.Danny.B@email.cz> <danny.b@email.cz>
|
||||
Danny B. <Wikipedia.Danny.B@email.cz> <danny_b@users.mediawiki.org>
|
||||
Danny B. <Wikipedia.Danny.B@email.cz> <wikimedia.danny.b@email.cz>
|
||||
Darian Anthony Patrick <dpatrick@wikimedia.org>
|
||||
Darkdragon09 <ubuntu@ip-172-31-39-38.us-west-2.compute.internal>
|
||||
DatGuy <datguysteam@gmail.com>
|
||||
David Barratt <dbarratt@wikimedia.org>
|
||||
David Causse <dcausse@wikimedia.org>
|
||||
David Chan <david@sheetmusic.org.uk>
|
||||
Dayllan Maza <dmaza@wikimedia.org>
|
||||
Dayllan Maza <dmaza@wikimedia.org> <dayllan.maza@gmail.com>
|
||||
Denny Vrandečić <dvrandecic@wikimedia.org>
|
||||
Dereckson <dereckson@espace-win.org>
|
||||
Derk-Jan Hartman <hartman.wiki@gmail.com>
|
||||
Derk-Jan Hartman <hartman.wiki@gmail.com> <hartman@videolan.org>
|
||||
Derk-Jan Hartman <hartman.wiki@gmail.com> <hartman@users.mediawiki.org>
|
||||
Devi Krishnan <devikrishnan67@gmail.com>
|
||||
Diederik van Liere <dvanliere@gmail.com> <diederik@users.mediawiki.org>
|
||||
diesel kapasule <diesel.kapasule@speedandfunction.com>
|
||||
Domas Mituzas <domas.mituzas@gmail.com> <midom@users.mediawiki.org>
|
||||
Douglas Gardner <douglas@chippy.ch>
|
||||
Doğu Abaris <ydogu@wikimedia.org.tr>
|
||||
DPStokesNZ <duncan.stokes@gmail.com>
|
||||
Dreamy Jazz <dreamyjazzwikipedia@gmail.com>
|
||||
Dreamy Jazz <dreamyjazzwikipedia@gmail.com> <wbrown-ctr@wikimedia.org>
|
||||
Dreamy Jazz <dreamyjazzwikipedia@gmail.com> <wbrown@wikimedia.org>
|
||||
Dreamy Jazz <dreamyjazzwikipedia@gmail.com> <wpgbrown@wikimedia.org>
|
||||
Dylsss <dylssswp@gmail.com>
|
||||
Ebrahim Byagowi <ebrahim@gnu.org>
|
||||
Ed Sanders <esanders@wikimedia.org>
|
||||
Elliott Eggleston <eeggleston@wikimedia.org>
|
||||
Elliott Eggleston <eeggleston@wikimedia.org> <ejegg@ejegg.com>
|
||||
Emad Elwany <emadelwany@hotmail.com>
|
||||
Emmanuel Engelhart <kelson@kiwix.org> <kelson42@users.mediawiki.org>
|
||||
Emufarmers <emufarmers@gmail.com>
|
||||
Emufarmers <emufarmers@gmail.com> <emufarmers@users.mediawiki.org>
|
||||
Entlinkt <entlinkt@gmx-topmail.de>
|
||||
Eranroz <eranroz89@gmail.com>
|
||||
Erik Bernhardson <ebernhardson@wikimedia.org>
|
||||
Erik Moeller <erik@wikimedia.org>
|
||||
Erik Moeller <erik@wikimedia.org> <erik@users.mediawiki.org>
|
||||
Erwin Dokter <erwin@darcoury.nl>
|
||||
Evan McIntire <mcintire.evan@gmail.com>
|
||||
Evan Prodromou <evanprodromou@users.mediawiki.org> <evan@users.mediawiki.org>
|
||||
Federico Leva <federicoleva@tiscali.it>
|
||||
Ferran Tufan <southparkfan223@hotmail.com>
|
||||
Fenzik Joseph <fenzik@gmail.com> <fenzik@users.mediawiki.org>
|
||||
Florian Schmidt <florian.schmidt.welzow@t-online.de>
|
||||
Florian Schmidt <florian.schmidt.welzow@t-online.de> <florian.schmidt.stargatewissen@gmail.com>
|
||||
fomafix <fomafix@googlemail.com>
|
||||
Fran Rogers <fran@dumetella.net>
|
||||
Fran Rogers <fran@dumetella.net> <krimpet@users.mediawiki.org>
|
||||
Frances Goodwin <fgoodwin@wikimedia.org>
|
||||
freakolowsky <freak@drajv.si>
|
||||
Func <Funcer@outlook.com>
|
||||
FunPika <funpikawiki@gmail.com>
|
||||
Gabriel Wicke <gwicke@wikimedia.org>
|
||||
Gabriel Wicke <gwicke@wikimedia.org> <gwicke@users.mediawiki.org>
|
||||
Gabriel Wicke <gwicke@wikimedia.org> <wicke@wikidev.net>
|
||||
gengh <ggalarzaheredero@wikimedia.org>
|
||||
Geoffrey Mon <geofbot@gmail.com>
|
||||
Geoffrey Trang <geoffreytrang@gmail.com>
|
||||
Gergő Tisza <gtisza@wikimedia.org>
|
||||
Gergő Tisza <gtisza@wikimedia.org> <tgr.huwiki@gmail.com>
|
||||
Giftpflanze <gifti@tools.wmflabs.org>
|
||||
Gilles Dubuc <gdubuc@wikimedia.org> <gilles@wikimedia.org>
|
||||
Gilles Dubuc <gdubuc@wikimedia.org>
|
||||
gladoscc <admin@glados.cc>
|
||||
glaisher <glaisher.wiki@gmail.com>
|
||||
Greg Sabino Mullane <greg@turnstep.com>
|
||||
Greg Sabino Mullane <greg@turnstep.com> <greg@endpoint.com>
|
||||
Greg Sabino Mullane <greg@turnstep.com> <greg@users.mediawiki.org>
|
||||
Grunny <mwgrunny@gmail.com>
|
||||
Guy Van den Broeck <guyvdb@gmail.com> <guyvdb@users.mediawiki.org>
|
||||
HakanIST <ozdemir@gmail.com>
|
||||
Happy-melon <happy-melon@live.com> <happy-melon@users.mediawiki.org>
|
||||
Helder <he7d3r@gmail.com>
|
||||
Helder <he7d3r@gmail.com> <helder.wiki@gmail.com>
|
||||
Hoo man <hoo@online.de>
|
||||
Huji <huji.huji@gmail.com>
|
||||
Huji <huji.huji@gmail.com> <huji@users.mediawiki.org>
|
||||
Ian Baker <ibaker@wikimedia.org> <raindrift@users.mediawiki.org>
|
||||
Ilmari Karonen <nospam@vyznev.net> <vyznev@users.mediawiki.org>
|
||||
Inez Korczyński <inez@wikia-inc.com>
|
||||
Inez Korczyński <inez@wikia-inc.com> <inez@users.mediawiki.org>
|
||||
isarra <s@zaori.org>
|
||||
isarra <s@zaori.org> <zhorishna@gmail.com>
|
||||
Ivan Lanin <ivanlanin@gmail.com> <ivanlanin@users.mediawiki.org>
|
||||
Jack Phoenix <jack@countervandalism.net>
|
||||
Jack Phoenix <jack@countervandalism.net> <ashley@users.mediawiki.org>
|
||||
Jackmcbarn <jackmcbarn@gmail.com>
|
||||
Jackmcbarn <jackmcbarn@gmail.com> <jackmcbarn@users.noreply.github.com>
|
||||
jagori <jagori79@gmail.com>
|
||||
James D. Forrester <jforrester@wikimedia.org>
|
||||
Jan Drewniak <jdrewniak@wikimedia.org>
|
||||
Jan Drewniak <jdrewniak@wikimedia.org> <jan.drewniak@gmail.com>
|
||||
Jaime Crespo <jcrespo@wikimedia.org>
|
||||
Jan Gerber <j@thing.net> <j@users.mediawiki.org>
|
||||
Jan Luca Naumann <jan@jans-seite.de>
|
||||
Jan Luca Naumann <jan@jans-seite.de> <jan@users.mediawiki.org>
|
||||
Jan Paul Posma <jp.posma@gmail.com> <janpaul123@users.mediawiki.org>
|
||||
Jan Zerebecki <jan.wikimedia@zerebecki.de>
|
||||
Jared Flores <jaredflores2000@gmail.com>
|
||||
Jaroslav Škarvada <jskarvad@redhat.com>
|
||||
jarrettmunton <jmuntjmunt@gmail.com>
|
||||
Jason Richey <jasonr@wikia.com>
|
||||
Jason Richey <jasonr@wikia.com> <jasonr@users.mediawiki.org>
|
||||
Jason Richey <jasonr@wikia.com> <urichj00@users.mediawiki.org>
|
||||
Jeff Hall <jeffreyehall@gmail.com>
|
||||
Jeff Hall <jeffreyehall@gmail.com> <jhall@wikimedia.org>
|
||||
Jeff Hobson <jhobson@wikimedia.org>
|
||||
Jeff Janes <jeff.janes@gmail.com>
|
||||
Jeremy Baron <jeremy@tuxmachine.com>
|
||||
Jeremy Postlethwaite <jpostlethwaite@wikimedia.org> <jpostlethwaite@users.mediawiki.org>
|
||||
Jeroen De Dauw <jeroendedauw@gmail.com>
|
||||
Jeroen De Dauw <jeroendedauw@gmail.com> <jeroendedauw@users.mediawiki.org>
|
||||
Jesús Martínez Novo <martineznovo@gmail.com>
|
||||
Jiabao <jiabao.foss@gmail.com>
|
||||
Jimmy Collins <jimmy.collins@web.de> <collinj@users.mediawiki.org>
|
||||
Joel Sahleen <jsahleen@wikimedia.org>
|
||||
John Du Hart <john@compwhizii.net> <johnduhart@users.mediawiki.org>
|
||||
John Erling Blad <john.blad@wikimedia.de>
|
||||
Jon Harald Søby <jhsoby@gmail.com> <jhsoby@users.mediawiki.org>
|
||||
Jon Harald Søby <jhsoby@gmail.com>
|
||||
Jon Robson <jrobson@wikimedia.org>
|
||||
Jon Robson <jrobson@wikimedia.org> <jdlrobson@gmail.com>
|
||||
Jsn.sherman <jsherman@wikimedia.org>
|
||||
Juliusz Gonera <jgonera@gmail.com>
|
||||
Juliusz Gonera <jgonera@gmail.com> <jgonera@wikimedia.org>
|
||||
Jure Kajzer <freak@drajv.si>
|
||||
Jure Kajzer <freak@drajv.si> <freakolowsky@users.mediawiki.org>
|
||||
Justin Du <justin.d128@gmail.com>
|
||||
Kai Nissen <kai.nissen@wikimedia.de>
|
||||
Karun Dambiec <karun.84@gmx.de>
|
||||
Katie Filbert <aude.wiki@gmail.com>
|
||||
Katie Filbert <aude.wiki@gmail.com> <aude@users.mediawiki.org>
|
||||
Kevin Israel <pleasestand@live.com>
|
||||
Klein Muçi <kleinmuci@gmail.com>
|
||||
Kosta Harlan <kharlan@wikimedia.org>
|
||||
Kosta Harlan <kharlan@wikimedia.org> <kosta@fastmail.com>
|
||||
Kunal Grover <kunalgrover05@gmail.com>
|
||||
Kunal Mehta <legoktm@debian.org>
|
||||
Kunal Mehta <legoktm@debian.org> <legoktm@member.fsf.org>
|
||||
Kunal Mehta <legoktm@debian.org> <legoktm.wikipedia@gmail.com>
|
||||
Kunal Mehta <legoktm@debian.org> <legoktm@gmail.com>
|
||||
Kwan Ting Chan <ktc@ktchan.info> <ktchan@users.mediawiki.org>
|
||||
lekshmi <andnlnbn18@gmail.com>
|
||||
Lectrician1 <jayandseth@gmail.com>
|
||||
Leo Koppelkamm <diebuche@gmail.com> <diebuche@users.mediawiki.org>
|
||||
Leon Liesener <leon.liesener@wikipedia.de>
|
||||
Leon Weber <leon@vserver152.masterssystems.com> <leon@users.mediawiki.org>
|
||||
Leonardo Gregianin <leogregianin@googlemail.com> <leogregianin@users.mediawiki.org>
|
||||
Leons Petrazickis <leons.petrazickis.haveyouconsiderednotincludingthisphrase@gmail.com> <leonsp@users.mediawiki.org>
|
||||
liangent <liangent@gmail.com>
|
||||
Lisa Ridley <lhridley@gmail.com> <lhridley@users.mediawiki.org>
|
||||
Ljudusika <plo2000@i.ua>
|
||||
Lucas Werkmeister <lucas.werkmeister@wikimedia.de>
|
||||
Luis Felipe Schenone <schenonef@gmail.com>
|
||||
Luke Welling <lwelling@wikimedia.org>
|
||||
Lupo <lupo.bugzilla@gmail.com>
|
||||
lwatson <lwatson@wikimedia.org>
|
||||
m4tx <m4tx@m4tx.pl>
|
||||
Madman <madman.enwiki@gmail.com>
|
||||
Magnus Manske <magnusmanske@googlemail.com> <magnusmanske@users.mediawiki.org>
|
||||
Manuel Schneider <manuel.schneider@wikimedia.ch> <80686@users.mediawiki.org>
|
||||
Marc-André Pelletier <marc@uberbox.org>
|
||||
Marcin Cieślak <saper@saper.info>
|
||||
Marcin Cieślak <saper@saper.info> <saper@users.mediawiki.org>
|
||||
Marco Falke <maic23@live.de>
|
||||
MarcoAurelio <strigiwm@gmail.com>
|
||||
MarcoAurelio <strigiwm@gmail.com> <maurelio@tools.wmflabs.org>
|
||||
Marielle Volz <marielle.volz@gmail.com>
|
||||
Marius Hoch <hoo@online.de>
|
||||
Mark Clements <mediawiki@kennel17.co.uk> <happydog@users.mediawiki.org>
|
||||
Mark Hershberger <mah@everybody.org>
|
||||
Mark Hershberger <mah@everybody.org> <mah@nichework.com>
|
||||
Mark Hershberger <mah@everybody.org> <mah@users.mediawiki.org>
|
||||
Mark Hershberger <mah@everybody.org> <mhershberger@wikimedia.org>
|
||||
Mark Holmquist <mtraceur@member.fsf.org>
|
||||
Mark Holmquist <mtraceur@member.fsf.org> <mholmquist@wikimedia.org>
|
||||
Marko Obrovac <mobrovac@wikimedia.org>
|
||||
Markus Glaser <glaser@hallowelt.biz>
|
||||
Markus Glaser <glaser@hallowelt.biz> <mglaser@users.mediawiki.org>
|
||||
Martin Urbanec <martin.urbanec@wikimedia.cz>
|
||||
Martin Urbanec <martin.urbanec@wikimedia.cz> <murbanec@wikimedia.org>
|
||||
Matt Johnston <mattj@emazestudios.com> <mattj@users.mediawiki.org>
|
||||
Matthew Britton <hugglegurch@gmail.com> <gurch@users.mediawiki.org>
|
||||
Matthew Bowker <matthewrbowker.bugs@gmail.com>
|
||||
Matthew Flaschen <mflaschen@wikimedia.org>
|
||||
Matthew Walker <mwalker@wikimedia.org>
|
||||
MatthiasDD <Matthias_K2@gmx.de>
|
||||
Matthias Mullie <git@mullie.eu>
|
||||
Matthias Mullie <git@mullie.eu> <mmullie@wikimedia.org>
|
||||
Matěj Grabovský <mgrabovsky@yahoo.com> <mgrabovsky@users.mediawiki.org>
|
||||
Matěj Suchánek <matejsuchanek97@gmail.com>
|
||||
Max Semenik <maxsem.wiki@gmail.com>
|
||||
Max Semenik <maxsem.wiki@gmail.com> <maxsem@users.mediawiki.org>
|
||||
Max Semenik <maxsem.wiki@gmail.com> <semenik@gmail.com>
|
||||
mbsantos <msantos@wikimedia.org>
|
||||
mgooley <g0013y@gmail.com>
|
||||
Michael Dale <mdale@wikimedia.org> <dale@users.mediawiki.org>
|
||||
Mikko Miettinen <miki@jedipedia.fi>
|
||||
Mikko Miettinen <miki@jedipedia.fi> <97.mikko.miettinen@gmail.com>
|
||||
mjbmr <mjbmri@gmail.com>
|
||||
Mohamed Magdy <mohamedmk@gmail.com> <alnokta@users.mediawiki.org>
|
||||
Moriel Schottlender <mschottlender@wikimedia.org>
|
||||
Moriel Schottlender <mschottlender@wikimedia.org> <moriel@gmail.com>
|
||||
Mormegil <mormegil@centrum.cz>
|
||||
MrBlueSky <mrbluesky@wikipedia.be>
|
||||
MrBlueSky <mrbluesky@wikipedia.be> <mrbluesky@localhost>
|
||||
Mukunda Modell <mmodell@wikimedia.org>
|
||||
MZMcBride <g@mzmcbride.com>
|
||||
Máté Szabó <mszabo@fandom.com>
|
||||
Máté Szabó <mszabo@fandom.com> <mszabo@wikia-inc.com>
|
||||
Máté Szabó <mszabo@fandom.com> <tk.999.wikia@gmail.com>
|
||||
nadeesha <nadeesha@calcey.com> <nadeesha@users.mediawiki.org>
|
||||
Namit <namit.ohri@gmail.com>
|
||||
Nathan Larson <nathanlarson3141@gmail.com>
|
||||
Nathan Larson <nathanlarson3141@gmail.com> <tjlsangria@gmail.com>
|
||||
Nathaniel Herman <redwwjd@yahoo.com> <pinky@users.mediawiki.org>
|
||||
Neil Kandalgaonkar <neilk@wikimedia.org> <neilk@users.mediawiki.org>
|
||||
Nemo bis <federicoleva@tiscali.it>
|
||||
nephele <nephele@skyhighway.com> <nephele@users.mediawiki.org>
|
||||
Nick Jenkins <nickpj@gmail.com> <nickj@users.mediawiki.org>
|
||||
Niharika Kohli <nkohli@wikimedia.org>
|
||||
Nik Everett <neverett@wikimedia.org>
|
||||
Niklas Laxström <niklas.laxstrom@gmail.com>
|
||||
Niklas Laxström <niklas.laxstrom@gmail.com> <nikerabbit@users.mediawiki.org>
|
||||
Nimish Gautam <nimishg@wikimedia.org> <nimishg@users.mediawiki.org>
|
||||
Novem Linguae <novemlinguae@gmail.com>
|
||||
Nuria Ruiz <nuria@wikimedia.org>
|
||||
Ori Livneh <ori@wikimedia.org>
|
||||
Ori Livneh <ori@wikimedia.org> <ori.livneh@gmail.com>
|
||||
Oskar Jauch <oskar.jauch@gmail.com>
|
||||
Owen Davis <owen@wikia-inc.com>
|
||||
Owen Davis <owen@wikia-inc.com> <owen@users.mediawiki.org>
|
||||
paladox <thomasmulhall410@yahoo.com>
|
||||
Patricio Molina <patriciomolina@gmail.com>
|
||||
Patrick Reilly <preilly@wikimedia.org>
|
||||
Patrick Reilly <preilly@wikimedia.org> <preilly@users.mediawiki.org>
|
||||
Patrick Westerhoff <PatrickWesterhoff@gmail.com>
|
||||
Paul Copperman <paul.copperman@gmail.com> <pcopp@users.mediawiki.org>
|
||||
Petar Petković <ppetkovic@wikimedia.org>
|
||||
Peter Coombe <pcoombe@wikimedia.org>
|
||||
Peter Coti <petercoti@gmail.com>
|
||||
Peter Potrowl <peter017@gmail.com> <peter17@users.mediawiki.org>
|
||||
Petr Kadlec <mormegil@centrum.cz>
|
||||
Philip Tzou <philip.npc@gmail.com> <philip@users.mediawiki.org>
|
||||
physikerwelt (Moritz Schubotz) <wiki@physikerwelt.de>
|
||||
Piotr Miazga <piotr@polishdeveloper.pl>
|
||||
PiRSquared17 <pirsquared@tools.wmflabs.org>
|
||||
Platonides <platonides@gmail.com> <platonides@users.mediawiki.org>
|
||||
pppery <mapreader@olum.org>
|
||||
PranavK <pranavmk98@gmail.com>
|
||||
Prateek Saxena <psaxena@wikimedia.org>
|
||||
Prateek Saxena <psaxena@wikimedia.org> <prtksxna@gmail.com>
|
||||
Priyanka Dhanda <pdhanda@wikimedia.org> <pdhanda@users.mediawiki.org>
|
||||
Purodha Blissenbach <purodha@blissenbach.org>
|
||||
Purodha Blissenbach <purodha@blissenbach.org> <publi@web.de>
|
||||
Purodha Blissenbach <purodha@blissenbach.org> <purodha@users.mediawiki.org>
|
||||
Pwirth <wirth@hallowelt.biz>
|
||||
Raimond Spekking <raimond.spekking@gmail.com>
|
||||
Raimond Spekking <raimond.spekking@gmail.com> <raymond@users.mediawiki.org>
|
||||
Remember the dot <rememberthedot@gmail.com> <rememberthedot@users.mediawiki.org>
|
||||
Reza <reza.energy@gmail.com>
|
||||
Ricordisamoa <ricordisamoa@openmailbox.org>
|
||||
rillke <rillke@wikipedia.de>
|
||||
rillke <rillke@wikipedia.de> <rainerrillke@hotmail.com>
|
||||
River Tarnell <river@wikimedia.org> <kateturner@users.mediawiki.org>
|
||||
River Tarnell <river@wikimedia.org> <river@users.mediawiki.org>
|
||||
Roan Kattouw <roan.kattouw@gmail.com>
|
||||
Roan Kattouw <roan.kattouw@gmail.com> <catrope@users.mediawiki.org>
|
||||
Roan Kattouw <roan.kattouw@gmail.com> <roan@wikimedia.org>
|
||||
Rob Church <robchur@gmail.com> <robchurch@users.mediawiki.org>
|
||||
Rob Lanphier <robla@robla.net>
|
||||
Rob Lanphier <robla@robla.net> <robla@users.mediawiki.org>
|
||||
Rob Lanphier <robla@robla.net> <robla@wikimedia.org>
|
||||
Rob Moen <rmoen@mediawiki.org>
|
||||
Rob Moen <rmoen@mediawiki.org> <rmoen@users.mediawiki.org>
|
||||
Rob Moen <rmoen@mediawiki.org> <rmoen@wikimedia.org>
|
||||
Robert Hoenig <indielives010@gmail.com>
|
||||
Robert Leverington <robert@rhl.me.uk> <roberthl@users.mediawiki.org>
|
||||
Robert Rohde <rarohde@gmail.com> <rarohde@users.mediawiki.org>
|
||||
Robert Stojnić <rainmansr@gmail.com> <rainman@users.mediawiki.org>
|
||||
Robert Vogel <vogel@hallowelt.biz>
|
||||
Robin Pepermans <robinp.1273@gmail.com>
|
||||
Robin Pepermans <robinp.1273@gmail.com> <robin@users.mediawiki.org>
|
||||
robinhood701 <robinhood70@live.ca>
|
||||
Rohan <rohan1395@yahoo.com>
|
||||
Rotem Liss <rotemliss@gmail.com> <rotem@users.mediawiki.org>
|
||||
Rummana Yasmeen <ryasmeen@wikimedia.org>
|
||||
Russ Nelson <russnelson@gmail.com> <nelson@users.mediawiki.org>
|
||||
Ryan Kaldari <rkaldari@wikimedia.org>
|
||||
Ryan Kaldari <rkaldari@wikimedia.org> <kaldari@gmail.com>
|
||||
Ryan Kaldari <rkaldari@wikimedia.org> <kaldari@users.mediawiki.org>
|
||||
Ryan Lane <rlane32@gmail.com>
|
||||
Ryan Lane <rlane32@gmail.com> <laner@users.mediawiki.org>
|
||||
Ryan Lane <rlane32@gmail.com> <rlane@wikimedia.org>
|
||||
Ryan Schmidt <skizzerz@gmail.com>
|
||||
Ryan Schmidt <skizzerz@gmail.com> <skizzerz@skizzerz.net>
|
||||
Ryan Schmidt <skizzerz@gmail.com> <skizzerz@users.mediawiki.org>
|
||||
S Page <spage@wikimedia.org>
|
||||
SBassett <sbassett@wikimedia.org>
|
||||
Sakretsu <sakretsu.wiki@gmail.com>
|
||||
Sam Reed <reedy@wikimedia.org>
|
||||
Sam Reed <reedy@wikimedia.org> <sam@reedyboy.net>
|
||||
Sam Reed <reedy@wikimedia.org> <Reedy reedy@wikimedia.org>
|
||||
Sam Reed <reedy@wikimedia.org> <reedy@formey.wikimedia.org>
|
||||
Sam Reed <reedy@wikimedia.org> <reedy@users.mediawiki.org>
|
||||
Sam Smith <git@samsmith.io>
|
||||
Sammy Tarling <sam@theresnotime.co.uk>
|
||||
Sammy Tarling <starling@wikimedia.org>
|
||||
Sammy Tarling <starling@wikimedia.org> <theresnotime@wikimedia.org>
|
||||
Sammy Tarling <starling@wikimedia.org> <starling-ctr@wikimedia.org>
|
||||
Santhosh Thottingal <santhosh.thottingal@gmail.com>
|
||||
Santhosh Thottingal <santhosh.thottingal@gmail.com> <santhosh@users.mediawiki.org>
|
||||
Schnark (Michael M.) <listenleser@gmail.com>
|
||||
Scimonster <tehalmightyscimonster@gmail.com>
|
||||
Sean Colombo <sean.colombo@gmail.com> <sean_colombo@users.mediawiki.org>
|
||||
Sean Pringle <springle@wikimedia.org>
|
||||
Seb35 <seb35wikipedia@gmail.com>
|
||||
Sergio Santoro <santoro.srg@gmail.com>
|
||||
Shahyar <shahyar@gmail.com>
|
||||
Shinjiman <shinjiman@gmail.com>
|
||||
Shinjiman <shinjiman@gmail.com> <shinjiman@users.mediawiki.org>
|
||||
shirayuki <shirayuking@gmail.com>
|
||||
Siebrand Mazeland <s.mazeland@xs4all.nl>
|
||||
Siebrand Mazeland <s.mazeland@xs4all.nl> <siebrand@kitano.nl>
|
||||
Siebrand Mazeland <s.mazeland@xs4all.nl> <siebrand@users.mediawiki.org>
|
||||
Siebrand Mazeland <s.mazeland@xs4all.nl> <siebrand@wikimedia.org>
|
||||
Simone Cuomo <simone@thisdot.co>
|
||||
sjoerddebruin <sjoerddebruin@me.com>
|
||||
Smriti Singh <smritis.31095@gmail.com>
|
||||
Sohom Datta <sohom.datta@learner.manipal.edu>
|
||||
Sohom Datta <sohom.datta@learner.manipal.edu> <sohomdatta1+git@gmail.com>
|
||||
Sorawee Porncharoenwase <nullzero.free@gmail.com>
|
||||
SQL <sxwiki@gmail.com> <sql@users.mediawiki.org>
|
||||
ST47 <en.wp.st47@gmail.com>
|
||||
stang <pmx42@live.cn>
|
||||
stang <pmx42@live.cn> <stang@toolforge.org>
|
||||
Stanislav Malyshev <smalyshev@gmail.com>
|
||||
Stephan Gambke <s7eph4n@gmail.com>
|
||||
Stephane Bisson <sbisson@wikimedia.org>
|
||||
Stephen Liang <github@stephenliang.pw>
|
||||
Steve Sanbeg <ffnaort@jro.qr> <sanbeg@users.mediawiki.org>
|
||||
Steven Roddis <StevenRoddis@users.noreply.github.com>
|
||||
Steven Walling <swalling@wikimedia.org>
|
||||
Stevie Beth Mhaol <sbmhaol@wikimedia.org>
|
||||
Stevie Beth Mhaol <sbmhaol@wikimedia.org> <sshirley@wikimedia.org>
|
||||
Subramanya Sastry <ssastry@wikimedia.org>
|
||||
Sucheta Ghoshal <sghoshal@wikimedia.org>
|
||||
Sumit Asthana <asthana.sumit23@gmail.com>
|
||||
Taavi Väänänen <hi@taavi.wtf>
|
||||
Taavi Väänänen <hi@taavi.wtf> <hi@tassu.me>
|
||||
Taavi Väänänen <hi@taavi.wtf> <taavi@wikimedia.org>
|
||||
tacsipacsi <tacsipacsi@jnet.hu>
|
||||
TerraCodes <terracodes@tools.wmflabs.org>
|
||||
Thalia Chan <thalia@cantorion.org>
|
||||
Thalia Chan <thalia@cantorion.org> <thalia.e.chan@googlemail.com>
|
||||
Thiemo Kreuz <thiemo.kreuz@wikimedia.de>
|
||||
Thiemo Kreuz <thiemo.kreuz@wikimedia.de> <thiemo.maettig@wikimedia.de>
|
||||
Thiemo Kreuz <thiemo.kreuz@wikimedia.de> <mr.heat@gmx.de>
|
||||
This, that and the other <at.light@live.com.au>
|
||||
tholam <t.lam@lamsinfosystem.com>
|
||||
Thomas Bleher <ThomasBleher@gmx.de> <tbleher@users.mediawiki.org>
|
||||
Thomas Chin <tchin@wikimedia.org>
|
||||
Thomas Dalton <thomas.dalton@gmail.com> <tango@users.mediawiki.org>
|
||||
Thomas Gries <mail@tgries.de> <wikinaut@users.mediawiki.org>
|
||||
Tim Landscheidt <tim@tim-landscheidt.de>
|
||||
Tim Laqua <t.laqua@gmail.com> <tlaqua@users.mediawiki.org>
|
||||
Tim Starling <tstarling@wikimedia.org>
|
||||
Tim Starling <tstarling@wikimedia.org> <tstarling@users.mediawiki.org>
|
||||
Timo Tijhof <krinkle@fastmail.com>
|
||||
Timo Tijhof <krinkle@fastmail.com> <krinkle@users.mediawiki.org>
|
||||
Timo Tijhof <krinkle@fastmail.com> <timo@wikimedia.org>
|
||||
Timo Tijhof <krinkle@fastmail.com> <ttijhof@wikimedia.org>
|
||||
Timo Tijhof <krinkle@fastmail.com> <krinklemail@gmail.com>
|
||||
Tina Johnson <tinajohnson.1234@gmail.com>
|
||||
Tobi_406 <tobim406@gmail.com>
|
||||
Tom Maaswinkel <tom.maaswinkel@12wiki.eu> <thedevilonline@users.mediawiki.org>
|
||||
Tomasz Finc <tfinc@wikimedia.org> <tomasz@users.mediawiki.org>
|
||||
Tomasz W. Kozlowski <tomasz@twkozlowski.com>
|
||||
Tomasz W. Kozlowski <tomasz@twkozlowski.com> <tomasz@twkozlowski.net>
|
||||
Tomasz W. Kozlowski <tomasz@twkozlowski.com> <twkozlowski@gmail.com>
|
||||
Tony Thomas <01tonythomas@gmail.com>
|
||||
Tpt <thomaspt@hotmail.fr>
|
||||
Trevor Parscal <trevorparscal@gmail.com>
|
||||
Trevor Parscal <trevorparscal@gmail.com> <tparscal@users.mediawiki.org>
|
||||
Trevor Parscal <trevorparscal@gmail.com> <tparscal@wikimedia.org>
|
||||
Trey Jones <tjones@wikimedia.org>
|
||||
Tyler Cipriani <tcipriani@wikimedia.org>
|
||||
Tyler Romeo <tylerromeo@gmail.com>
|
||||
Umherirrender <umherirrender_de.wp@web.de>
|
||||
Victor Barbu <victorbarbu08@gmail.com>
|
||||
Victor Vasiliev <vasilvv@mit.edu>
|
||||
Victor Vasiliev <vasilvv@mit.edu> <vasilievvv@users.mediawiki.org>
|
||||
Victor Vasiliev <vasilvv@mit.edu> <vasilvv@gmail.com>
|
||||
Vlad Shapik <vlad.shapik@speedandfunction.com>
|
||||
Vikas S Yaligar <vikasyaligar.it@gmail.com>
|
||||
Vinitha <vinithacse@gmail.com>
|
||||
Vivek Ghaisas <v.a.ghaisas@gmail.com>
|
||||
Volker E <volker.e@wikimedia.org>
|
||||
Wendy Quarshie <wquarshie@wikimedia.org>
|
||||
wctaiwan <wctaiwan@gmail.com>
|
||||
withoutaname <drevitchi@gmail.com>
|
||||
X! <soxred93@gmail.com> <soxred93@users.mediawiki.org>
|
||||
Yaron Koren <yaron57@gmail.com>
|
||||
Yaron Koren <yaron57@gmail.com> <yaron@users.mediawiki.org>
|
||||
Yaroslav Melnychuk <yaroslavmelnuchuk@gmail.com>
|
||||
Yongmin Hong <revi@pobox.com>
|
||||
Yongmin Hong <revi@pobox.com> <revi@member.fsf.org>
|
||||
Yongmin Hong <revi@pobox.com> <reviwiki@gmail.com>
|
||||
Yuri Astrakhan <yurik@wikimedia.org>
|
||||
Yuri Astrakhan <yurik@wikimedia.org> <yuriastrakhan@gmail.com>
|
||||
Yuri Astrakhan <yurik@wikimedia.org> <yurik@users.mediawiki.org>
|
||||
Yuriy Shnitkovskiy <bmp2558@gmail.com>
|
||||
Yusuke Matsubara <whym@whym.org>
|
||||
Yuvi Panda <yuvipanda@gmail.com>
|
||||
Zak Greant <zak+mediawiki@fooassociates.com> <zak@users.mediawiki.org>
|
||||
Zhengzhu Feng <zhengzhu@gmail.com>
|
||||
Zhengzhu Feng <zhengzhu@gmail.com> <zhengzhu@users.mediawiki.org>
|
||||
Zoranzoki21 <zorandori4444@gmail.com>
|
||||
Zppix <support@zppixballee.com>
|
||||
Ævar Arnfjörð Bjarmason <avarab@gmail.com> <avar@users.mediawiki.org>
|
||||
Étienne Beaulé <beauleetienne0@gmail.com>
|
||||
Željko Filipin <zeljko.filipin@gmail.com>
|
||||
Željko Filipin <zeljko.filipin@gmail.com> <zfilipin@wikimedia.org>
|
||||
星耀晨曦 <razesoldier@outlook.com>
|
||||
星耀晨曦 <razesoldier@outlook.com> <liguangjie4399@hotmail.com>
|
||||
沈澄心 <dringsim@qq.com>
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
<?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
|
||||
*/
|
||||
|
||||
$cfg = require __DIR__ . '/../vendor/mediawiki/mediawiki-phan-config/src/config.php';
|
||||
|
||||
// This value should match the PHP version specified in composer.json,
|
||||
// PHPVersionCheck.php, and ScopeStructureTest.php
|
||||
$cfg['minimum_target_php_version'] = '8.1.0';
|
||||
|
||||
$cfg['file_list'] = array_merge(
|
||||
$cfg['file_list'],
|
||||
class_exists( Socket::class ) ? [] : [ '.phan/stubs/Socket.php' ],
|
||||
class_exists( AllowDynamicProperties::class ) ? [] : [ '.phan/stubs/AllowDynamicProperties.php' ],
|
||||
[
|
||||
// This makes constants and globals known to Phan before processing all other files.
|
||||
// You can check the parser order with --dump-parsed-file-list
|
||||
'includes/Defines.php',
|
||||
// @todo This isn't working yet, see globals_type_map below
|
||||
// 'includes/Setup.php',
|
||||
'tests/phpunit/MediaWikiIntegrationTestCase.php',
|
||||
'tests/phpunit/includes/TestUser.php',
|
||||
]
|
||||
);
|
||||
|
||||
$cfg['exclude_file_list'] = array_merge(
|
||||
$cfg['exclude_file_list'],
|
||||
[
|
||||
// Avoid microsoft/tolerant-php-parser dependency
|
||||
'maintenance/findDeprecated.php',
|
||||
'maintenance/CodeCleanerGlobalsPass.php',
|
||||
// Avoid nikic/php-parser dependency
|
||||
'maintenance/shell.php',
|
||||
]
|
||||
);
|
||||
|
||||
$cfg['autoload_internal_extension_signatures'] = [
|
||||
'excimer' => '.phan/internal_stubs/excimer.phan_php',
|
||||
'imagick' => '.phan/internal_stubs/imagick.phan_php',
|
||||
'memcached' => '.phan/internal_stubs/memcached.phan_php',
|
||||
'pcntl' => '.phan/internal_stubs/pcntl.phan_php',
|
||||
'pgsql' => '.phan/internal_stubs/pgsql.phan_php',
|
||||
'redis' => '.phan/internal_stubs/redis.phan_php',
|
||||
'sockets' => '.phan/internal_stubs/sockets.phan_php',
|
||||
'tideways_xhprof' => '.phan/internal_stubs/tideways_xhprof.phan_php',
|
||||
'wikidiff2' => '.phan/internal_stubs/wikidiff.php'
|
||||
];
|
||||
|
||||
$cfg['directory_list'] = [
|
||||
'includes/',
|
||||
'languages/',
|
||||
'maintenance/',
|
||||
'mw-config/',
|
||||
'resources/',
|
||||
'tests/common/',
|
||||
'tests/parser/',
|
||||
'tests/phan',
|
||||
'tests/phpunit/mocks/',
|
||||
// Do NOT add .phan/stubs/ here: stubs are conditionally loaded in file_list
|
||||
];
|
||||
|
||||
// Include only direct production dependencies in vendor/
|
||||
// Omit dev dependencies and most indirect dependencies
|
||||
|
||||
$composerJson = json_decode(
|
||||
file_get_contents( __DIR__ . '/../composer.json' ),
|
||||
true
|
||||
);
|
||||
|
||||
$directDeps = [];
|
||||
foreach ( $composerJson['require'] as $dep => $version ) {
|
||||
$parts = explode( '/', $dep );
|
||||
if ( count( $parts ) === 2 ) {
|
||||
$directDeps[] = $dep;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a list of all composer packages that are referenced by core but
|
||||
// are not listed as requirements in composer.json.
|
||||
$indirectDeps = [
|
||||
'composer/spdx-licenses',
|
||||
'doctrine/dbal',
|
||||
'doctrine/sql-formatter',
|
||||
'guzzlehttp/psr7',
|
||||
'pear/net_url2',
|
||||
'pear/pear-core-minimal',
|
||||
'phpunit/phpunit',
|
||||
'psr/http-client',
|
||||
'psr/http-factory',
|
||||
'psr/http-message',
|
||||
'seld/jsonlint',
|
||||
'wikimedia/testing-access-wrapper',
|
||||
'wikimedia/zest-css',
|
||||
];
|
||||
|
||||
foreach ( [ ...$directDeps, ...$indirectDeps ] as $dep ) {
|
||||
$cfg['directory_list'][] = "vendor/$dep";
|
||||
}
|
||||
|
||||
$cfg['exclude_analysis_directory_list'] = [
|
||||
'vendor/',
|
||||
'.phan/',
|
||||
'tests/phpunit/',
|
||||
// The referenced classes are not available in vendor, only when
|
||||
// included from composer.
|
||||
'includes/composer/',
|
||||
// Directly references classes that only exist in Translate extension
|
||||
'maintenance/language/',
|
||||
// External class
|
||||
'includes/libs/objectcache/utils/MemcachedClient.php',
|
||||
// File may be valid, but may contain numerous "errors" such as iterating over an
|
||||
// empty array due to the version checking in T246594 not being currently used.
|
||||
'includes/PHPVersionCheck.php',
|
||||
];
|
||||
|
||||
// TODO: Ideally we'd disable this in core, given we don't need backwards compatibility here and aliases
|
||||
// should not be used. However, that would have unwanted side effects such as being unable to test
|
||||
// taint-check (T321806).
|
||||
$cfg['enable_class_alias_support'] = true;
|
||||
// Exclude Parsoid's src/DOM in favor of .phan/stubs/DomImpl.php
|
||||
$cfg['exclude_file_list'] = array_merge(
|
||||
$cfg['exclude_file_list'],
|
||||
array_map( fn ( $f ) => "vendor/wikimedia/parsoid/src/DOM/{$f}.php", [
|
||||
'Attr', 'CharacterData', 'Comment', 'Document', 'DocumentFragment',
|
||||
'DocumentType', 'Element', 'Node', 'ProcessingInstruction', 'Text',
|
||||
] )
|
||||
);
|
||||
$cfg['file_list'][] = '.phan/stubs/DomImpl.php';
|
||||
|
||||
$cfg['ignore_undeclared_variables_in_global_scope'] = true;
|
||||
// @todo It'd be great if we could just make phan read these from config-schema.php, to avoid
|
||||
// duplicating the types. config-schema.php has JSON types though, not PHP types.
|
||||
// @todo As we are removing access to global variables from the code base,
|
||||
// remove them from here as well, so phan complains when something tries to use them.
|
||||
$cfg['globals_type_map'] = array_merge( $cfg['globals_type_map'], [
|
||||
'IP' => 'string',
|
||||
'wgTitle' => \MediaWiki\Title\Title::class,
|
||||
'wgGalleryOptions' => 'array',
|
||||
'wgDirectoryMode' => 'int',
|
||||
'wgDummyLanguageCodes' => 'string[]',
|
||||
'wgNamespaceProtection' => 'array<int,string|string[]>',
|
||||
'wgNamespaceAliases' => 'array<string,int>',
|
||||
'wgLockManagers' => 'array[]',
|
||||
'wgForeignFileRepos' => 'array[]',
|
||||
'wgDefaultUserOptions' => 'array',
|
||||
'wgSkipSkins' => 'string[]',
|
||||
'wgLogTypes' => 'string[]',
|
||||
'wgLogNames' => 'array<string,string>',
|
||||
'wgLogHeaders' => 'array<string,string>',
|
||||
'wgLogActionsHandlers' => 'array<string,class-string>',
|
||||
'wgPasswordPolicy' => 'array<string,array<string,string|array>>',
|
||||
'wgVirtualRestConfig' => 'array<string,array>',
|
||||
'wgLocalInterwikis' => 'string[]',
|
||||
'wgDebugLogGroups' => 'string|false|array{destination:string,sample?:int,level:int}',
|
||||
'wgCookiePrefix' => 'string|false',
|
||||
'wgOut' => \MediaWiki\Output\OutputPage::class,
|
||||
'wgExtraNamespaces' => 'string[]',
|
||||
'wgRequest' => \MediaWiki\Request\WebRequest::class,
|
||||
] );
|
||||
|
||||
// Include a local config file if it exists
|
||||
if ( file_exists( __DIR__ . '/local-config.php' ) ) {
|
||||
require __DIR__ . '/local-config.php';
|
||||
}
|
||||
|
||||
return $cfg;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
See <https://github.com/phan/phan/wiki/How-To-Use-Stubs#generating-stubs> for
|
||||
how to generate internal stubs for phan.
|
||||
|
||||
The stubs should be generated using the PHP version that is our lowest
|
||||
requirement.
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
// These stubs were generated by the phan stub generator.
|
||||
// @phan-stub-for-extension excimer@1.1.1
|
||||
|
||||
namespace {
|
||||
class ExcimerLog implements \Iterator, \Traversable, \Countable, \ArrayAccess {
|
||||
|
||||
// methods
|
||||
final private function __construct() {}
|
||||
public function formatCollapsed() {}
|
||||
public function getSpeedscopeData() {}
|
||||
public function aggregateByFunction() : array {}
|
||||
public function getEventCount() {}
|
||||
public function current() : mixed {}
|
||||
public function key() : mixed {}
|
||||
public function next() : void {}
|
||||
public function rewind() : void {}
|
||||
public function valid() : bool {}
|
||||
public function count() : int {}
|
||||
public function offsetExists($offset) : bool {}
|
||||
public function offsetGet($offset) : mixed {}
|
||||
public function offsetSet($offset, $value) : void {}
|
||||
public function offsetUnset($offset) : void {}
|
||||
}
|
||||
|
||||
class ExcimerLogEntry {
|
||||
|
||||
// methods
|
||||
final private function __construct() {}
|
||||
public function getTimestamp() {}
|
||||
public function getEventCount() {}
|
||||
public function getTrace() {}
|
||||
}
|
||||
|
||||
class ExcimerProfiler {
|
||||
|
||||
// methods
|
||||
public function setPeriod($period) {}
|
||||
public function setEventType($event_type) {}
|
||||
public function setMaxDepth($max_depth) {}
|
||||
public function setFlushCallback($callback, $max_samples) {}
|
||||
public function clearFlushCallback() {}
|
||||
public function start() {}
|
||||
public function stop() {}
|
||||
public function getLog() : \ExcimerLog {}
|
||||
public function flush() {}
|
||||
}
|
||||
|
||||
class ExcimerTimer {
|
||||
|
||||
// methods
|
||||
public function setEventType($event_type) {}
|
||||
public function setInterval($interval) {}
|
||||
public function setPeriod($period) {}
|
||||
public function setCallback($callback) {}
|
||||
public function start() {}
|
||||
public function stop() {}
|
||||
public function getTime() {}
|
||||
}
|
||||
|
||||
function excimer_set_timeout($callback, $interval) {}
|
||||
const EXCIMER_CPU = 1;
|
||||
const EXCIMER_REAL = 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,180 @@
|
|||
<?php
|
||||
// These stubs were generated by the phan stub generator.
|
||||
// @phan-stub-for-extension memcached@3.0.1
|
||||
|
||||
namespace {
|
||||
class Memcached {
|
||||
|
||||
// constants
|
||||
const LIBMEMCACHED_VERSION_HEX = 16777240;
|
||||
const OPT_COMPRESSION = -1001;
|
||||
const OPT_COMPRESSION_TYPE = -1004;
|
||||
const OPT_PREFIX_KEY = -1002;
|
||||
const OPT_SERIALIZER = -1003;
|
||||
const OPT_USER_FLAGS = -1006;
|
||||
const OPT_STORE_RETRY_COUNT = -1005;
|
||||
const HAVE_IGBINARY = true;
|
||||
const HAVE_JSON = true;
|
||||
const HAVE_MSGPACK = true;
|
||||
const HAVE_SESSION = true;
|
||||
const HAVE_SASL = true;
|
||||
const OPT_HASH = 2;
|
||||
const HASH_DEFAULT = 0;
|
||||
const HASH_MD5 = 1;
|
||||
const HASH_CRC = 2;
|
||||
const HASH_FNV1_64 = 3;
|
||||
const HASH_FNV1A_64 = 4;
|
||||
const HASH_FNV1_32 = 5;
|
||||
const HASH_FNV1A_32 = 6;
|
||||
const HASH_HSIEH = 7;
|
||||
const HASH_MURMUR = 8;
|
||||
const OPT_DISTRIBUTION = 9;
|
||||
const DISTRIBUTION_MODULA = 0;
|
||||
const DISTRIBUTION_CONSISTENT = 1;
|
||||
const DISTRIBUTION_VIRTUAL_BUCKET = 6;
|
||||
const OPT_LIBKETAMA_COMPATIBLE = 16;
|
||||
const OPT_LIBKETAMA_HASH = 17;
|
||||
const OPT_TCP_KEEPALIVE = 32;
|
||||
const OPT_BUFFER_WRITES = 10;
|
||||
const OPT_BINARY_PROTOCOL = 18;
|
||||
const OPT_NO_BLOCK = 0;
|
||||
const OPT_TCP_NODELAY = 1;
|
||||
const OPT_SOCKET_SEND_SIZE = 4;
|
||||
const OPT_SOCKET_RECV_SIZE = 5;
|
||||
const OPT_CONNECT_TIMEOUT = 14;
|
||||
const OPT_RETRY_TIMEOUT = 15;
|
||||
const OPT_DEAD_TIMEOUT = 36;
|
||||
const OPT_SEND_TIMEOUT = 19;
|
||||
const OPT_RECV_TIMEOUT = 20;
|
||||
const OPT_POLL_TIMEOUT = 8;
|
||||
const OPT_CACHE_LOOKUPS = 6;
|
||||
const OPT_SERVER_FAILURE_LIMIT = 21;
|
||||
const OPT_AUTO_EJECT_HOSTS = 28;
|
||||
const OPT_HASH_WITH_PREFIX_KEY = 25;
|
||||
const OPT_NOREPLY = 26;
|
||||
const OPT_SORT_HOSTS = 12;
|
||||
const OPT_VERIFY_KEY = 13;
|
||||
const OPT_USE_UDP = 27;
|
||||
const OPT_NUMBER_OF_REPLICAS = 29;
|
||||
const OPT_RANDOMIZE_REPLICA_READ = 30;
|
||||
const OPT_REMOVE_FAILED_SERVERS = 35;
|
||||
const OPT_SERVER_TIMEOUT_LIMIT = 37;
|
||||
const RES_SUCCESS = 0;
|
||||
const RES_FAILURE = 1;
|
||||
const RES_HOST_LOOKUP_FAILURE = 2;
|
||||
const RES_UNKNOWN_READ_FAILURE = 7;
|
||||
const RES_PROTOCOL_ERROR = 8;
|
||||
const RES_CLIENT_ERROR = 9;
|
||||
const RES_SERVER_ERROR = 10;
|
||||
const RES_WRITE_FAILURE = 5;
|
||||
const RES_DATA_EXISTS = 12;
|
||||
const RES_NOTSTORED = 14;
|
||||
const RES_NOTFOUND = 16;
|
||||
const RES_PARTIAL_READ = 18;
|
||||
const RES_SOME_ERRORS = 19;
|
||||
const RES_NO_SERVERS = 20;
|
||||
const RES_END = 21;
|
||||
const RES_ERRNO = 26;
|
||||
const RES_BUFFERED = 32;
|
||||
const RES_TIMEOUT = 31;
|
||||
const RES_BAD_KEY_PROVIDED = 33;
|
||||
const RES_STORED = 15;
|
||||
const RES_DELETED = 22;
|
||||
const RES_STAT = 24;
|
||||
const RES_ITEM = 25;
|
||||
const RES_NOT_SUPPORTED = 28;
|
||||
const RES_FETCH_NOTFINISHED = 30;
|
||||
const RES_SERVER_MARKED_DEAD = 35;
|
||||
const RES_UNKNOWN_STAT_KEY = 36;
|
||||
const RES_INVALID_HOST_PROTOCOL = 34;
|
||||
const RES_MEMORY_ALLOCATION_FAILURE = 17;
|
||||
const RES_CONNECTION_SOCKET_CREATE_FAILURE = 11;
|
||||
const RES_E2BIG = 37;
|
||||
const RES_KEY_TOO_BIG = 39;
|
||||
const RES_SERVER_TEMPORARILY_DISABLED = 47;
|
||||
const RES_SERVER_MEMORY_ALLOCATION_FAILURE = 48;
|
||||
const RES_AUTH_PROBLEM = 40;
|
||||
const RES_AUTH_FAILURE = 41;
|
||||
const RES_AUTH_CONTINUE = 42;
|
||||
const RES_PAYLOAD_FAILURE = -1001;
|
||||
const SERIALIZER_PHP = 1;
|
||||
const SERIALIZER_IGBINARY = 2;
|
||||
const SERIALIZER_JSON = 3;
|
||||
const SERIALIZER_JSON_ARRAY = 4;
|
||||
const SERIALIZER_MSGPACK = 5;
|
||||
const COMPRESSION_FASTLZ = 2;
|
||||
const COMPRESSION_ZLIB = 1;
|
||||
const GET_PRESERVE_ORDER = 1;
|
||||
const GET_EXTENDED = 2;
|
||||
const GET_ERROR_RETURN_VALUE = false;
|
||||
|
||||
// methods
|
||||
public function __construct($persistent_id = null, $callback = null) {}
|
||||
public function getResultCode() {}
|
||||
public function getResultMessage() {}
|
||||
public function get($key, $cache_cb = null, $get_flags = null) {}
|
||||
public function getByKey($server_key, $key, $cache_cb = null, $get_flags = null) {}
|
||||
public function getMulti(array $keys, $get_flags = null) {}
|
||||
public function getMultiByKey($server_key, array $keys, $get_flags = null) {}
|
||||
public function getDelayed(array $keys, $with_cas = null, $value_cb = null) {}
|
||||
public function getDelayedByKey($server_key, array $keys, $with_cas = null, $value_cb = null) {}
|
||||
public function fetch() {}
|
||||
public function fetchAll() {}
|
||||
public function set($key, $value, $expiration = null) {}
|
||||
public function setByKey($server_key, $key, $value, $expiration = null) {}
|
||||
public function touch($key, $expiration) {}
|
||||
public function touchByKey($server_key, $key, $expiration) {}
|
||||
public function setMulti(array $items, $expiration = null) {}
|
||||
public function setMultiByKey($server_key, array $items, $expiration = null) {}
|
||||
public function cas($cas_token, $key, $value, $expiration = null) {}
|
||||
public function casByKey($cas_token, $server_key, $key, $value, $expiration = null) {}
|
||||
public function add($key, $value, $expiration = null) {}
|
||||
public function addByKey($server_key, $key, $value, $expiration = null) {}
|
||||
public function append($key, $value, $expiration = null) {}
|
||||
public function appendByKey($server_key, $key, $value, $expiration = null) {}
|
||||
public function prepend($key, $value, $expiration = null) {}
|
||||
public function prependByKey($server_key, $key, $value, $expiration = null) {}
|
||||
public function replace($key, $value, $expiration = null) {}
|
||||
public function replaceByKey($server_key, $key, $value, $expiration = null) {}
|
||||
public function delete($key, $time = null) {}
|
||||
public function deleteMulti($keys, $time = null) {}
|
||||
public function deleteByKey($server_key, $key, $time = null) {}
|
||||
public function deleteMultiByKey($server_key, $keys, $time = null) {}
|
||||
public function increment($key, $offset = null, $initial_value = null, $expiry = null) {}
|
||||
public function decrement($key, $offset = null, $initial_value = null, $expiry = null) {}
|
||||
public function incrementByKey($server_key, $key, $offset = null, $initial_value = null, $expiry = null) {}
|
||||
public function decrementByKey($server_key, $key, $offset = null, $initial_value = null, $expiry = null) {}
|
||||
public function addServer($host, $port, $weight = null) {}
|
||||
public function addServers(array $servers) {}
|
||||
public function getServerList() {}
|
||||
public function getServerByKey($server_key) {}
|
||||
public function resetServerList() {}
|
||||
public function quit() {}
|
||||
public function flushBuffers() {}
|
||||
public function getLastErrorMessage() {}
|
||||
public function getLastErrorCode() {}
|
||||
public function getLastErrorErrno() {}
|
||||
public function getLastDisconnectedServer() {}
|
||||
public function getStats($args) {}
|
||||
public function getVersion() {}
|
||||
public function getAllKeys() {}
|
||||
public function flush($delay = null) {}
|
||||
public function getOption($option) {}
|
||||
public function setOption($option, $value) {}
|
||||
public function setOptions($options) {}
|
||||
public function setBucket($host_map, $forward_map, $replicas) {}
|
||||
public function setSaslAuthData($username, $password) {}
|
||||
public function isPersistent() {}
|
||||
public function isPristine() {}
|
||||
}
|
||||
|
||||
class MemcachedException extends \RuntimeException {
|
||||
|
||||
// properties
|
||||
protected $message;
|
||||
protected $code;
|
||||
protected $file;
|
||||
protected $line;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
// These stubs were generated by the phan stub generator.
|
||||
// @phan-stub-for-extension pcntl@7.0.33-0+deb9u3
|
||||
|
||||
namespace {
|
||||
function pcntl_alarm($seconds) {}
|
||||
function pcntl_errno() {}
|
||||
function pcntl_exec($path, $args = null, $envs = null) {}
|
||||
function pcntl_fork() {}
|
||||
function pcntl_get_last_error() {}
|
||||
function pcntl_getpriority($pid = null, $process_identifier = null) {}
|
||||
function pcntl_setpriority($priority, $pid = null, $process_identifier = null) {}
|
||||
function pcntl_signal($signo, $handler, $restart_syscalls = null) {}
|
||||
function pcntl_signal_dispatch() {}
|
||||
function pcntl_sigprocmask($how, $set, &$oldset = null) {}
|
||||
function pcntl_sigtimedwait($set, &$info = null, $seconds = null, $nanoseconds = null) {}
|
||||
function pcntl_sigwaitinfo($set, &$info = null) {}
|
||||
function pcntl_strerror($errno) {}
|
||||
function pcntl_wait(&$status, $options = null, &$rusage = null) {}
|
||||
function pcntl_waitpid($pid, &$status, $options = null, &$rusage = null) {}
|
||||
function pcntl_wexitstatus($status) {}
|
||||
function pcntl_wifcontinued($status) {}
|
||||
function pcntl_wifexited($status) {}
|
||||
function pcntl_wifsignaled($status) {}
|
||||
function pcntl_wifstopped($status) {}
|
||||
function pcntl_wstopsig($status) {}
|
||||
function pcntl_wtermsig($status) {}
|
||||
const BUS_ADRALN = 1;
|
||||
const BUS_ADRERR = 2;
|
||||
const BUS_OBJERR = 3;
|
||||
const CLD_CONTINUED = 6;
|
||||
const CLD_DUMPED = 3;
|
||||
const CLD_EXITED = 1;
|
||||
const CLD_KILLED = 2;
|
||||
const CLD_STOPPED = 5;
|
||||
const CLD_TRAPPED = 4;
|
||||
const FPE_FLTDIV = 3;
|
||||
const FPE_FLTINV = 7;
|
||||
const FPE_FLTOVF = 4;
|
||||
const FPE_FLTRES = 6;
|
||||
const FPE_FLTSUB = 8;
|
||||
const FPE_FLTUND = 7;
|
||||
const FPE_INTDIV = 1;
|
||||
const FPE_INTOVF = 2;
|
||||
const ILL_BADSTK = 8;
|
||||
const ILL_COPROC = 7;
|
||||
const ILL_ILLADR = 3;
|
||||
const ILL_ILLOPC = 1;
|
||||
const ILL_ILLOPN = 2;
|
||||
const ILL_ILLTRP = 4;
|
||||
const ILL_PRVOPC = 5;
|
||||
const ILL_PRVREG = 6;
|
||||
const PCNTL_E2BIG = 7;
|
||||
const PCNTL_EACCES = 13;
|
||||
const PCNTL_EAGAIN = 11;
|
||||
const PCNTL_ECHILD = 10;
|
||||
const PCNTL_EFAULT = 14;
|
||||
const PCNTL_EINTR = 4;
|
||||
const PCNTL_EINVAL = 22;
|
||||
const PCNTL_EIO = 5;
|
||||
const PCNTL_EISDIR = 21;
|
||||
const PCNTL_ELIBBAD = 80;
|
||||
const PCNTL_ELOOP = 40;
|
||||
const PCNTL_EMFILE = 24;
|
||||
const PCNTL_ENAMETOOLONG = 36;
|
||||
const PCNTL_ENFILE = 23;
|
||||
const PCNTL_ENOENT = 2;
|
||||
const PCNTL_ENOEXEC = 8;
|
||||
const PCNTL_ENOMEM = 12;
|
||||
const PCNTL_ENOTDIR = 20;
|
||||
const PCNTL_EPERM = 1;
|
||||
const PCNTL_ESRCH = 3;
|
||||
const PCNTL_ETXTBSY = 26;
|
||||
const POLL_ERR = 4;
|
||||
const POLL_HUP = 6;
|
||||
const POLL_IN = 1;
|
||||
const POLL_MSG = 3;
|
||||
const POLL_OUT = 2;
|
||||
const POLL_PRI = 5;
|
||||
const PRIO_PGRP = 1;
|
||||
const PRIO_PROCESS = 0;
|
||||
const PRIO_USER = 2;
|
||||
const SEGV_ACCERR = 2;
|
||||
const SEGV_MAPERR = 1;
|
||||
const SIGABRT = 6;
|
||||
const SIGALRM = 14;
|
||||
const SIGBABY = 31;
|
||||
const SIGBUS = 7;
|
||||
const SIGCHLD = 17;
|
||||
const SIGCLD = 17;
|
||||
const SIGCONT = 18;
|
||||
const SIGFPE = 8;
|
||||
const SIGHUP = 1;
|
||||
const SIGILL = 4;
|
||||
const SIGINT = 2;
|
||||
const SIGIO = 29;
|
||||
const SIGIOT = 6;
|
||||
const SIGKILL = 9;
|
||||
const SIGPIPE = 13;
|
||||
const SIGPOLL = 29;
|
||||
const SIGPROF = 27;
|
||||
const SIGPWR = 30;
|
||||
const SIGQUIT = 3;
|
||||
const SIGSEGV = 11;
|
||||
const SIGSTKFLT = 16;
|
||||
const SIGSTOP = 19;
|
||||
const SIGSYS = 31;
|
||||
const SIGTERM = 15;
|
||||
const SIGTRAP = 5;
|
||||
const SIGTSTP = 20;
|
||||
const SIGTTIN = 21;
|
||||
const SIGTTOU = 22;
|
||||
const SIGURG = 23;
|
||||
const SIGUSR1 = 10;
|
||||
const SIGUSR2 = 12;
|
||||
const SIGVTALRM = 26;
|
||||
const SIGWINCH = 28;
|
||||
const SIGXCPU = 24;
|
||||
const SIGXFSZ = 25;
|
||||
const SIG_BLOCK = 0;
|
||||
const SIG_DFL = 0;
|
||||
const SIG_ERR = -1;
|
||||
const SIG_IGN = 1;
|
||||
const SIG_SETMASK = 2;
|
||||
const SIG_UNBLOCK = 1;
|
||||
const SI_ASYNCIO = -4;
|
||||
const SI_KERNEL = 128;
|
||||
const SI_MESGQ = -3;
|
||||
const SI_QUEUE = -1;
|
||||
const SI_SIGIO = -5;
|
||||
const SI_TIMER = -2;
|
||||
const SI_TKILL = -6;
|
||||
const SI_USER = 0;
|
||||
const TRAP_BRKPT = 1;
|
||||
const TRAP_TRACE = 2;
|
||||
const WCONTINUED = 8;
|
||||
const WNOHANG = 1;
|
||||
const WUNTRACED = 2;
|
||||
}
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
<?php
|
||||
// These stubs were generated by the phan stub generator.
|
||||
// @phan-stub-for-extension pgsql@7.3.4
|
||||
|
||||
namespace {
|
||||
function pg_affected_rows($result) {}
|
||||
function pg_cancel_query($connection) {}
|
||||
function pg_client_encoding($connection = null) {}
|
||||
function pg_clientencoding($connection = null) {}
|
||||
function pg_close($connection = null) {}
|
||||
function pg_cmdtuples($result) {}
|
||||
function pg_connect($connection_string, $connect_type = null, $host = null, $port = null, $options = null, $tty = null, $database = null) {}
|
||||
function pg_connect_poll($connection = null) {}
|
||||
function pg_connection_busy($connection) {}
|
||||
function pg_connection_reset($connection) {}
|
||||
function pg_connection_status($connection) {}
|
||||
function pg_consume_input($connection) {}
|
||||
function pg_convert($db, $table, $values, $options = null) {}
|
||||
function pg_copy_from($connection, $table_name, $rows, $delimiter = null, $null_as = null) {}
|
||||
function pg_copy_to($connection, $table_name, $delimiter = null, $null_as = null) {}
|
||||
function pg_dbname($connection = null) {}
|
||||
function pg_delete($db, $table, $ids, $options = null) {}
|
||||
function pg_end_copy($connection = null) {}
|
||||
function pg_errormessage($connection = null) {}
|
||||
function pg_escape_bytea($connection = null, $data = null) {}
|
||||
function pg_escape_identifier($connection = null, $data = null) {}
|
||||
function pg_escape_literal($connection = null, $data = null) {}
|
||||
function pg_escape_string($connection = null, $data = null) {}
|
||||
function pg_exec($connection = null, $query = null) {}
|
||||
function pg_execute($connection = null, $stmtname = null, $params = null) {}
|
||||
function pg_fetch_all($result, $result_type = null) {}
|
||||
function pg_fetch_all_columns($result, $column_number = null) {}
|
||||
function pg_fetch_array($result, $row = null, $result_type = null) {}
|
||||
function pg_fetch_assoc($result, $row = null) {}
|
||||
function pg_fetch_object($result, $row = null, $class_name = null, $l = null, $ctor_params = null) {}
|
||||
function pg_fetch_result($result, $row_number = null, $field_name = null) {}
|
||||
function pg_fetch_row($result, $row = null, $result_type = null) {}
|
||||
function pg_field_is_null($result, $row = null, $field_name_or_number = null) {}
|
||||
function pg_field_name($result, $field_number) {}
|
||||
function pg_field_num($result, $field_name) {}
|
||||
function pg_field_prtlen($result, $row = null, $field_name_or_number = null) {}
|
||||
function pg_field_size($result, $field_number) {}
|
||||
function pg_field_table($result, $field_number, $oid_only = null) {}
|
||||
function pg_field_type($result, $field_number) {}
|
||||
function pg_field_type_oid($result, $field_number) {}
|
||||
function pg_fieldisnull($result, $row = null, $field_name_or_number = null) {}
|
||||
function pg_fieldname($result, $field_number) {}
|
||||
function pg_fieldnum($result, $field_name) {}
|
||||
function pg_fieldprtlen($result, $row = null, $field_name_or_number = null) {}
|
||||
function pg_fieldsize($result, $field_number) {}
|
||||
function pg_fieldtype($result, $field_number) {}
|
||||
function pg_flush($connection) {}
|
||||
function pg_free_result($result) {}
|
||||
function pg_freeresult($result) {}
|
||||
function pg_get_notify($connection = null, $e = null) {}
|
||||
function pg_get_pid($connection = null) {}
|
||||
function pg_get_result($connection) {}
|
||||
function pg_getlastoid($result) {}
|
||||
function pg_host($connection = null) {}
|
||||
function pg_insert($db, $table, $values, $options = null) {}
|
||||
function pg_last_error($connection = null) {}
|
||||
function pg_last_notice($connection, $option = null) {}
|
||||
function pg_last_oid($result) {}
|
||||
function pg_lo_close($large_object) {}
|
||||
function pg_lo_create($connection = null, $large_object_id = null) {}
|
||||
function pg_lo_export($connection = null, $objoid = null, $filename = null) {}
|
||||
function pg_lo_import($connection = null, $filename = null, $large_object_oid = null) {}
|
||||
function pg_lo_open($connection = null, $large_object_oid = null, $mode = null) {}
|
||||
function pg_lo_read($large_object, $len = null) {}
|
||||
function pg_lo_read_all($large_object) {}
|
||||
function pg_lo_seek($large_object, $offset, $whence = null) {}
|
||||
function pg_lo_tell($large_object) {}
|
||||
function pg_lo_truncate($large_object, $size = null) {}
|
||||
function pg_lo_unlink($connection = null, $large_object_oid = null) {}
|
||||
function pg_lo_write($large_object, $buf, $len = null) {}
|
||||
function pg_loclose($large_object) {}
|
||||
function pg_locreate($connection = null, $large_object_id = null) {}
|
||||
function pg_loexport($connection = null, $objoid = null, $filename = null) {}
|
||||
function pg_loimport($connection = null, $filename = null, $large_object_oid = null) {}
|
||||
function pg_loopen($connection = null, $large_object_oid = null, $mode = null) {}
|
||||
function pg_loread($large_object, $len = null) {}
|
||||
function pg_loreadall($large_object) {}
|
||||
function pg_lounlink($connection = null, $large_object_oid = null) {}
|
||||
function pg_lowrite($large_object, $buf, $len = null) {}
|
||||
function pg_meta_data($db, $table) {}
|
||||
function pg_num_fields($result) {}
|
||||
function pg_num_rows($result) {}
|
||||
function pg_numfields($result) {}
|
||||
function pg_numrows($result) {}
|
||||
function pg_options($connection = null) {}
|
||||
function pg_parameter_status($connection, $param_name = null) {}
|
||||
function pg_pconnect($connection_string, $host = null, $port = null, $options = null, $tty = null, $database = null) {}
|
||||
function pg_ping($connection = null) {}
|
||||
function pg_port($connection = null) {}
|
||||
function pg_prepare($connection = null, $stmtname = null, $query = null) {}
|
||||
function pg_put_line($connection = null, $query = null) {}
|
||||
function pg_query($connection = null, $query = null) {}
|
||||
function pg_query_params($connection = null, $query = null, $params = null) {}
|
||||
function pg_result($connection) {}
|
||||
function pg_result_error($result) {}
|
||||
function pg_result_error_field($result, $fieldcode) {}
|
||||
function pg_result_seek($result, $offset) {}
|
||||
function pg_result_status($result, $result_type = null) {}
|
||||
function pg_select($db, $table, $ids, $options = null, $result_type = null) {}
|
||||
function pg_send_execute($connection, $stmtname, $params) {}
|
||||
function pg_send_prepare($connection, $stmtname, $query) {}
|
||||
function pg_send_query($connection, $query) {}
|
||||
function pg_send_query_params($connection, $query, $params) {}
|
||||
function pg_set_client_encoding($connection = null, $encoding = null) {}
|
||||
function pg_set_error_verbosity($connection = null, $verbosity = null) {}
|
||||
function pg_setclientencoding($connection = null, $encoding = null) {}
|
||||
function pg_socket($connection) {}
|
||||
function pg_trace($filename, $mode = null, $connection = null) {}
|
||||
function pg_transaction_status($connection) {}
|
||||
function pg_tty($connection = null) {}
|
||||
function pg_unescape_bytea($data) {}
|
||||
function pg_untrace($connection = null) {}
|
||||
function pg_update($db, $table, $fields, $ids, $options = null) {}
|
||||
function pg_version($connection = null) {}
|
||||
const PGSQL_ASSOC = 1;
|
||||
const PGSQL_BAD_RESPONSE = 5;
|
||||
const PGSQL_BOTH = 3;
|
||||
const PGSQL_COMMAND_OK = 1;
|
||||
const PGSQL_CONNECTION_AUTH_OK = 5;
|
||||
const PGSQL_CONNECTION_AWAITING_RESPONSE = 4;
|
||||
const PGSQL_CONNECTION_BAD = 1;
|
||||
const PGSQL_CONNECTION_MADE = 3;
|
||||
const PGSQL_CONNECTION_OK = 0;
|
||||
const PGSQL_CONNECTION_SETENV = 6;
|
||||
const PGSQL_CONNECTION_STARTED = 2;
|
||||
const PGSQL_CONNECT_ASYNC = 4;
|
||||
const PGSQL_CONNECT_FORCE_NEW = 2;
|
||||
const PGSQL_CONV_FORCE_NULL = 4;
|
||||
const PGSQL_CONV_IGNORE_DEFAULT = 2;
|
||||
const PGSQL_CONV_IGNORE_NOT_NULL = 8;
|
||||
const PGSQL_COPY_IN = 4;
|
||||
const PGSQL_COPY_OUT = 3;
|
||||
const PGSQL_DIAG_COLUMN_NAME = 99;
|
||||
const PGSQL_DIAG_CONSTRAINT_NAME = 110;
|
||||
const PGSQL_DIAG_CONTEXT = 87;
|
||||
const PGSQL_DIAG_DATATYPE_NAME = 100;
|
||||
const PGSQL_DIAG_INTERNAL_POSITION = 112;
|
||||
const PGSQL_DIAG_INTERNAL_QUERY = 113;
|
||||
const PGSQL_DIAG_MESSAGE_DETAIL = 68;
|
||||
const PGSQL_DIAG_MESSAGE_HINT = 72;
|
||||
const PGSQL_DIAG_MESSAGE_PRIMARY = 77;
|
||||
const PGSQL_DIAG_SCHEMA_NAME = 115;
|
||||
const PGSQL_DIAG_SEVERITY = 83;
|
||||
const PGSQL_DIAG_SEVERITY_NONLOCALIZED = 86;
|
||||
const PGSQL_DIAG_SOURCE_FILE = 70;
|
||||
const PGSQL_DIAG_SOURCE_FUNCTION = 82;
|
||||
const PGSQL_DIAG_SOURCE_LINE = 76;
|
||||
const PGSQL_DIAG_SQLSTATE = 67;
|
||||
const PGSQL_DIAG_STATEMENT_POSITION = 80;
|
||||
const PGSQL_DIAG_TABLE_NAME = 116;
|
||||
const PGSQL_DML_ASYNC = 1024;
|
||||
const PGSQL_DML_ESCAPE = 4096;
|
||||
const PGSQL_DML_EXEC = 512;
|
||||
const PGSQL_DML_NO_CONV = 256;
|
||||
const PGSQL_DML_STRING = 2048;
|
||||
const PGSQL_EMPTY_QUERY = 0;
|
||||
const PGSQL_ERRORS_DEFAULT = 1;
|
||||
const PGSQL_ERRORS_TERSE = 0;
|
||||
const PGSQL_ERRORS_VERBOSE = 2;
|
||||
const PGSQL_FATAL_ERROR = 7;
|
||||
const PGSQL_LIBPQ_VERSION = '9.6.9';
|
||||
const PGSQL_LIBPQ_VERSION_STR = 'PostgreSQL 9.6.9 (win32)';
|
||||
const PGSQL_NONFATAL_ERROR = 6;
|
||||
const PGSQL_NOTICE_ALL = 2;
|
||||
const PGSQL_NOTICE_CLEAR = 3;
|
||||
const PGSQL_NOTICE_LAST = 1;
|
||||
const PGSQL_NUM = 2;
|
||||
const PGSQL_POLLING_ACTIVE = 4;
|
||||
const PGSQL_POLLING_FAILED = 0;
|
||||
const PGSQL_POLLING_OK = 3;
|
||||
const PGSQL_POLLING_READING = 1;
|
||||
const PGSQL_POLLING_WRITING = 2;
|
||||
const PGSQL_SEEK_CUR = 1;
|
||||
const PGSQL_SEEK_END = 2;
|
||||
const PGSQL_SEEK_SET = 0;
|
||||
const PGSQL_STATUS_LONG = 1;
|
||||
const PGSQL_STATUS_STRING = 2;
|
||||
const PGSQL_TRANSACTION_ACTIVE = 1;
|
||||
const PGSQL_TRANSACTION_IDLE = 0;
|
||||
const PGSQL_TRANSACTION_INERROR = 3;
|
||||
const PGSQL_TRANSACTION_INTRANS = 2;
|
||||
const PGSQL_TRANSACTION_UNKNOWN = 4;
|
||||
const PGSQL_TUPLES_OK = 2;
|
||||
}
|
||||
|
|
@ -0,0 +1,549 @@
|
|||
<?php
|
||||
// These stubs were generated by the phan stub generator.
|
||||
// @phan-stub-for-extension redis@5.1.1
|
||||
|
||||
namespace {
|
||||
class Redis {
|
||||
|
||||
// constants
|
||||
const REDIS_NOT_FOUND = 0;
|
||||
const REDIS_STRING = 1;
|
||||
const REDIS_SET = 2;
|
||||
const REDIS_LIST = 3;
|
||||
const REDIS_ZSET = 4;
|
||||
const REDIS_HASH = 5;
|
||||
const REDIS_STREAM = 6;
|
||||
const PIPELINE = 2;
|
||||
const ATOMIC = 0;
|
||||
const MULTI = 1;
|
||||
const OPT_SERIALIZER = 1;
|
||||
const OPT_PREFIX = 2;
|
||||
const OPT_READ_TIMEOUT = 3;
|
||||
const OPT_TCP_KEEPALIVE = 6;
|
||||
const OPT_COMPRESSION = 7;
|
||||
const OPT_REPLY_LITERAL = 8;
|
||||
const OPT_COMPRESSION_LEVEL = 9;
|
||||
const SERIALIZER_NONE = 0;
|
||||
const SERIALIZER_PHP = 1;
|
||||
const SERIALIZER_IGBINARY = 2;
|
||||
const SERIALIZER_JSON = 4;
|
||||
const COMPRESSION_NONE = 0;
|
||||
const OPT_SCAN = 4;
|
||||
const SCAN_RETRY = 1;
|
||||
const SCAN_NORETRY = 0;
|
||||
const AFTER = 'after';
|
||||
const BEFORE = 'before';
|
||||
|
||||
// methods
|
||||
public function __construct() {}
|
||||
public function __destruct() {}
|
||||
public function _prefix($key) {}
|
||||
public function _serialize($value) {}
|
||||
public function _unserialize($value) {}
|
||||
public function append($key, $value) {}
|
||||
public function auth($password) {}
|
||||
public function bgSave() {}
|
||||
public function bgrewriteaof() {}
|
||||
public function bitcount($key) {}
|
||||
public function bitop($operation, $ret_key, $key, ...$other_keys) {}
|
||||
public function bitpos($key, $bit, $start = null, $end = null) {}
|
||||
public function blPop($key, $timeout_or_key, ...$extra_args) {}
|
||||
public function brPop($key, $timeout_or_key, ...$extra_args) {}
|
||||
public function brpoplpush($src, $dst, $timeout) {}
|
||||
public function bzPopMax($key, $timeout_or_key, ...$extra_args) {}
|
||||
public function bzPopMin($key, $timeout_or_key, ...$extra_args) {}
|
||||
public function clearLastError() {}
|
||||
public function client($cmd, ...$args) {}
|
||||
public function close() {}
|
||||
public function command(...$args) {}
|
||||
public function config($cmd, $key, $value = null) {}
|
||||
public function connect($host, $port = null, $timeout = null, $retry_interval = null) {}
|
||||
public function dbSize() {}
|
||||
public function debug($key) {}
|
||||
public function decr($key) {}
|
||||
public function decrBy($key, $value) {}
|
||||
public function del($key, ...$other_keys) {}
|
||||
public function discard() {}
|
||||
public function dump($key) {}
|
||||
public function echo($msg) {}
|
||||
public function eval($script, $args = null, $num_keys = null) {}
|
||||
public function evalsha($script_sha, $args = null, $num_keys = null) {}
|
||||
public function exec() {}
|
||||
public function exists($key, ...$other_keys) {}
|
||||
public function expire($key, $timeout) {}
|
||||
public function expireAt($key, $timestamp) {}
|
||||
public function flushAll($async = null) {}
|
||||
public function flushDB($async = null) {}
|
||||
public function geoadd($key, $lng, $lat, $member, ...$other_triples) {}
|
||||
public function geodist($key, $src, $dst, $unit = null) {}
|
||||
public function geohash($key, $member, ...$other_members) {}
|
||||
public function geopos($key, $member, ...$other_members) {}
|
||||
public function georadius($key, $lng, $lan, $radius, $unit, array $opts = null) {}
|
||||
public function georadius_ro($key, $lng, $lan, $radius, $unit, array $opts = null) {}
|
||||
public function georadiusbymember($key, $member, $radius, $unit, array $opts = null) {}
|
||||
public function georadiusbymember_ro($key, $member, $radius, $unit, array $opts = null) {}
|
||||
public function get($key) {}
|
||||
public function getAuth() {}
|
||||
public function getBit($key, $offset) {}
|
||||
public function getDBNum() {}
|
||||
public function getHost() {}
|
||||
public function getLastError() {}
|
||||
public function getMode() {}
|
||||
public function getOption($option) {}
|
||||
public function getPersistentID() {}
|
||||
public function getPort() {}
|
||||
public function getRange($key, $start, $end) {}
|
||||
public function getReadTimeout() {}
|
||||
public function getSet($key, $value) {}
|
||||
public function getTimeout() {}
|
||||
public function hDel($key, $member, ...$other_members) {}
|
||||
public function hExists($key, $member) {}
|
||||
public function hGet($key, $member) {}
|
||||
public function hGetAll($key) {}
|
||||
public function hIncrBy($key, $member, $value) {}
|
||||
public function hIncrByFloat($key, $member, $value) {}
|
||||
public function hKeys($key) {}
|
||||
public function hLen($key) {}
|
||||
public function hMget($key, array $keys) {}
|
||||
public function hMset($key, array $pairs) {}
|
||||
public function hSet($key, $member, $value) {}
|
||||
public function hSetNx($key, $member, $value) {}
|
||||
public function hStrLen($key, $member) {}
|
||||
public function hVals($key) {}
|
||||
public function hscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) {}
|
||||
public function incr($key) {}
|
||||
public function incrBy($key, $value) {}
|
||||
public function incrByFloat($key, $value) {}
|
||||
public function info($option = null) {}
|
||||
public function isConnected() {}
|
||||
public function keys($pattern) {}
|
||||
public function lInsert($key, $position, $pivot, $value) {}
|
||||
public function lLen($key) {}
|
||||
public function lPop($key) {}
|
||||
public function lPush($key, $value) {}
|
||||
public function lPushx($key, $value) {}
|
||||
public function lSet($key, $index, $value) {}
|
||||
public function lastSave() {}
|
||||
public function lindex($key, $index) {}
|
||||
public function lrange($key, $start, $end) {}
|
||||
public function lrem($key, $value, $count) {}
|
||||
public function ltrim($key, $start, $stop) {}
|
||||
public function mget(array $keys) {}
|
||||
public function migrate($host, $port, $key, $db, $timeout, $copy = null, $replace = null) {}
|
||||
public function move($key, $dbindex) {}
|
||||
public function mset(array $pairs) {}
|
||||
public function msetnx(array $pairs) {}
|
||||
public function multi($mode = null) {}
|
||||
public function object($field, $key) {}
|
||||
public function pconnect($host, $port = null, $timeout = null) {}
|
||||
public function persist($key) {}
|
||||
public function pexpire($key, $timestamp) {}
|
||||
public function pexpireAt($key, $timestamp) {}
|
||||
public function pfadd($key, array $elements) {}
|
||||
public function pfcount($key) {}
|
||||
public function pfmerge($dstkey, array $keys) {}
|
||||
public function ping() {}
|
||||
public function pipeline() {}
|
||||
public function psetex($key, $expire, $value) {}
|
||||
public function psubscribe(array $patterns, $callback) {}
|
||||
public function pttl($key) {}
|
||||
public function publish($channel, $message) {}
|
||||
public function pubsub($cmd, ...$args) {}
|
||||
public function punsubscribe($pattern, ...$other_patterns) {}
|
||||
public function rPop($key) {}
|
||||
public function rPush($key, $value) {}
|
||||
public function rPushx($key, $value) {}
|
||||
public function randomKey() {}
|
||||
public function rawcommand($cmd, ...$args) {}
|
||||
public function rename($key, $newkey) {}
|
||||
public function renameNx($key, $newkey) {}
|
||||
public function restore($ttl, $key, $value) {}
|
||||
public function role() {}
|
||||
public function rpoplpush($src, $dst) {}
|
||||
public function sAdd($key, $value) {}
|
||||
public function sAddArray($key, array $options) {}
|
||||
public function sDiff($key, ...$other_keys) {}
|
||||
public function sDiffStore($dst, $key, ...$other_keys) {}
|
||||
public function sInter($key, ...$other_keys) {}
|
||||
public function sInterStore($dst, $key, ...$other_keys) {}
|
||||
public function sMembers($key) {}
|
||||
public function sMove($src, $dst, $value) {}
|
||||
public function sPop($key) {}
|
||||
public function sRandMember($key, $count = null) {}
|
||||
public function sUnion($key, ...$other_keys) {}
|
||||
public function sUnionStore($dst, $key, ...$other_keys) {}
|
||||
public function save() {}
|
||||
public function scan(&$i_iterator, $str_pattern = null, $i_count = null) {}
|
||||
public function scard($key) {}
|
||||
public function script($cmd, ...$args) {}
|
||||
public function select($dbindex) {}
|
||||
public function set($key, $value, $opts = null) {}
|
||||
public function setBit($key, $offset, $value) {}
|
||||
public function setOption($option, $value) {}
|
||||
public function setRange($key, $offset, $value) {}
|
||||
public function setex($key, $expire, $value) {}
|
||||
public function setnx($key, $value) {}
|
||||
public function sismember($key, $value) {}
|
||||
public function slaveof($host = null, $port = null) {}
|
||||
public function slowlog($arg, $option = null) {}
|
||||
public function sort($key, array $options = null) {}
|
||||
public function sortAsc($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) {}
|
||||
public function sortAscAlpha($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) {}
|
||||
public function sortDesc($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) {}
|
||||
public function sortDescAlpha($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null) {}
|
||||
public function srem($key, $member, ...$other_members) {}
|
||||
public function sscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) {}
|
||||
public function strlen($key) {}
|
||||
public function subscribe(array $channels, $callback) {}
|
||||
public function swapdb($srcdb, $dstdb) {}
|
||||
public function time() {}
|
||||
public function ttl($key) {}
|
||||
public function type($key) {}
|
||||
public function unlink($key, ...$other_keys) {}
|
||||
public function unsubscribe($channel, ...$other_channels) {}
|
||||
public function unwatch() {}
|
||||
public function wait($numslaves, $timeout) {}
|
||||
public function watch($key, ...$other_keys) {}
|
||||
public function xack($str_key, $str_group, array $arr_ids) {}
|
||||
public function xadd($str_key, $str_id, array $arr_fields, $i_maxlen = null, $boo_approximate = null) {}
|
||||
public function xclaim($str_key, $str_group, $str_consumer, $i_min_idle, array $arr_ids, array $arr_opts = null) {}
|
||||
public function xdel($str_key, array $arr_ids) {}
|
||||
public function xgroup($str_operation, $str_key = null, $str_arg1 = null, $str_arg2 = null, $str_arg3 = null) {}
|
||||
public function xinfo($str_cmd, $str_key = null, $str_group = null) {}
|
||||
public function xlen($key) {}
|
||||
public function xpending($str_key, $str_group, $str_start = null, $str_end = null, $i_count = null, $str_consumer = null) {}
|
||||
public function xrange($str_key, $str_start, $str_end, $i_count = null) {}
|
||||
public function xread(array $arr_streams, $i_count = null, $i_block = null) {}
|
||||
public function xreadgroup($str_group, $str_consumer, array $arr_streams, $i_count = null, $i_block = null) {}
|
||||
public function xrevrange($str_key, $str_start, $str_end, $i_count = null) {}
|
||||
public function xtrim($str_key, $i_maxlen, $boo_approximate = null) {}
|
||||
public function zAdd($key, $score, $value) {}
|
||||
public function zCard($key) {}
|
||||
public function zCount($key, $min, $max) {}
|
||||
public function zIncrBy($key, $value, $member) {}
|
||||
public function zLexCount($key, $min, $max) {}
|
||||
public function zPopMax($key) {}
|
||||
public function zPopMin($key) {}
|
||||
public function zRange($key, $start, $end, $scores = null) {}
|
||||
public function zRangeByLex($key, $min, $max, $offset = null, $limit = null) {}
|
||||
public function zRangeByScore($key, $start, $end, array $options = null) {}
|
||||
public function zRank($key, $member) {}
|
||||
public function zRem($key, $member, ...$other_members) {}
|
||||
public function zRemRangeByLex($key, $min, $max) {}
|
||||
public function zRemRangeByRank($key, $start, $end) {}
|
||||
public function zRemRangeByScore($key, $min, $max) {}
|
||||
public function zRevRange($key, $start, $end, $scores = null) {}
|
||||
public function zRevRangeByLex($key, $min, $max, $offset = null, $limit = null) {}
|
||||
public function zRevRangeByScore($key, $start, $end, array $options = null) {}
|
||||
public function zRevRank($key, $member) {}
|
||||
public function zScore($key, $member) {}
|
||||
public function zinterstore($key, array $keys, ?array $weights = null, $aggregate = null) {}
|
||||
public function zscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) {}
|
||||
public function zunionstore($key, array $keys, ?array $weights = null, $aggregate = null) {}
|
||||
public function delete($key, ...$other_keys) {}
|
||||
public function evaluate($script, $args = null, $num_keys = null) {}
|
||||
public function evaluateSha($script_sha, $args = null, $num_keys = null) {}
|
||||
public function getKeys($pattern) {}
|
||||
public function getMultiple(array $keys) {}
|
||||
public function lGet($key, $index) {}
|
||||
public function lGetRange($key, $start, $end) {}
|
||||
public function lRemove($key, $value, $count) {}
|
||||
public function lSize($key) {}
|
||||
public function listTrim($key, $start, $stop) {}
|
||||
public function open($host, $port = null, $timeout = null, $retry_interval = null) {}
|
||||
public function popen($host, $port = null, $timeout = null) {}
|
||||
public function renameKey($key, $newkey) {}
|
||||
public function sContains($key, $value) {}
|
||||
public function sGetMembers($key) {}
|
||||
public function sRemove($key, $member, ...$other_members) {}
|
||||
public function sSize($key) {}
|
||||
public function sendEcho($msg) {}
|
||||
public function setTimeout($key, $timeout) {}
|
||||
public function substr($key, $start, $end) {}
|
||||
public function zDelete($key, $member, ...$other_members) {}
|
||||
public function zDeleteRangeByRank($key, $min, $max) {}
|
||||
public function zDeleteRangeByScore($key, $min, $max) {}
|
||||
public function zInter($key, array $keys, ?array $weights = null, $aggregate = null) {}
|
||||
public function zRemove($key, $member, ...$other_members) {}
|
||||
public function zRemoveRangeByScore($key, $min, $max) {}
|
||||
public function zReverseRange($key, $start, $end, $scores = null) {}
|
||||
public function zSize($key) {}
|
||||
public function zUnion($key, array $keys, ?array $weights = null, $aggregate = null) {}
|
||||
}
|
||||
|
||||
class RedisArray {
|
||||
|
||||
// methods
|
||||
public function __call($function_name, $arguments) {}
|
||||
public function __construct($name_or_hosts, array $options = null) {}
|
||||
public function _continuum() {}
|
||||
public function _distributor() {}
|
||||
public function _function() {}
|
||||
public function _hosts() {}
|
||||
public function _instance($host) {}
|
||||
public function _rehash($callable = null) {}
|
||||
public function _target($key) {}
|
||||
public function bgsave() {}
|
||||
public function del($keys) {}
|
||||
public function discard() {}
|
||||
public function exec() {}
|
||||
public function flushall($async = null) {}
|
||||
public function flushdb($async = null) {}
|
||||
public function getOption($opt) {}
|
||||
public function info() {}
|
||||
public function keys($pattern) {}
|
||||
public function mget($keys) {}
|
||||
public function mset($pairs) {}
|
||||
public function multi($host, $mode = null) {}
|
||||
public function ping() {}
|
||||
public function save() {}
|
||||
public function select($index) {}
|
||||
public function setOption($opt, $value) {}
|
||||
public function unlink() {}
|
||||
public function unwatch() {}
|
||||
public function delete($keys) {}
|
||||
public function getMultiple($keys) {}
|
||||
}
|
||||
|
||||
class RedisCluster {
|
||||
|
||||
// constants
|
||||
const REDIS_NOT_FOUND = 0;
|
||||
const REDIS_STRING = 1;
|
||||
const REDIS_SET = 2;
|
||||
const REDIS_LIST = 3;
|
||||
const REDIS_ZSET = 4;
|
||||
const REDIS_HASH = 5;
|
||||
const REDIS_STREAM = 6;
|
||||
const ATOMIC = 0;
|
||||
const MULTI = 1;
|
||||
const OPT_SERIALIZER = 1;
|
||||
const OPT_PREFIX = 2;
|
||||
const OPT_READ_TIMEOUT = 3;
|
||||
const OPT_TCP_KEEPALIVE = 6;
|
||||
const OPT_COMPRESSION = 7;
|
||||
const OPT_REPLY_LITERAL = 8;
|
||||
const OPT_COMPRESSION_LEVEL = 9;
|
||||
const SERIALIZER_NONE = 0;
|
||||
const SERIALIZER_PHP = 1;
|
||||
const SERIALIZER_IGBINARY = 2;
|
||||
const SERIALIZER_JSON = 4;
|
||||
const COMPRESSION_NONE = 0;
|
||||
const OPT_SCAN = 4;
|
||||
const SCAN_RETRY = 1;
|
||||
const SCAN_NORETRY = 0;
|
||||
const OPT_SLAVE_FAILOVER = 5;
|
||||
const FAILOVER_NONE = 0;
|
||||
const FAILOVER_ERROR = 1;
|
||||
const FAILOVER_DISTRIBUTE = 2;
|
||||
const FAILOVER_DISTRIBUTE_SLAVES = 3;
|
||||
const AFTER = 'after';
|
||||
const BEFORE = 'before';
|
||||
|
||||
// methods
|
||||
public function __construct($name, array $seeds = null, $timeout = null, $read_timeout = null, $persistent = null, $auth = null) {}
|
||||
public function _masters() {}
|
||||
public function _prefix($key) {}
|
||||
public function _redir() {}
|
||||
public function _serialize($value) {}
|
||||
public function _unserialize($value) {}
|
||||
public function append($key, $value) {}
|
||||
public function bgrewriteaof($key_or_address) {}
|
||||
public function bgsave($key_or_address) {}
|
||||
public function bitcount($key) {}
|
||||
public function bitop($operation, $ret_key, $key, ...$other_keys) {}
|
||||
public function bitpos($key, $bit, $start = null, $end = null) {}
|
||||
public function blpop($key, $timeout_or_key, ...$extra_args) {}
|
||||
public function brpop($key, $timeout_or_key, ...$extra_args) {}
|
||||
public function brpoplpush($src, $dst, $timeout) {}
|
||||
public function clearlasterror() {}
|
||||
public function bzpopmax($key, $timeout_or_key, ...$extra_args) {}
|
||||
public function bzpopmin($key, $timeout_or_key, ...$extra_args) {}
|
||||
public function client($key_or_address, $arg = null, ...$other_args) {}
|
||||
public function close() {}
|
||||
public function cluster($key_or_address, $arg = null, ...$other_args) {}
|
||||
public function command(...$args) {}
|
||||
public function config($key_or_address, $arg = null, ...$other_args) {}
|
||||
public function dbsize($key_or_address) {}
|
||||
public function decr($key) {}
|
||||
public function decrby($key, $value) {}
|
||||
public function del($key, ...$other_keys) {}
|
||||
public function discard() {}
|
||||
public function dump($key) {}
|
||||
public function echo($msg) {}
|
||||
public function eval($script, $args = null, $num_keys = null) {}
|
||||
public function evalsha($script_sha, $args = null, $num_keys = null) {}
|
||||
public function exec() {}
|
||||
public function exists($key) {}
|
||||
public function expire($key, $timeout) {}
|
||||
public function expireat($key, $timestamp) {}
|
||||
public function flushall($key_or_address, $async = null) {}
|
||||
public function flushdb($key_or_address, $async = null) {}
|
||||
public function geoadd($key, $lng, $lat, $member, ...$other_triples) {}
|
||||
public function geodist($key, $src, $dst, $unit = null) {}
|
||||
public function geohash($key, $member, ...$other_members) {}
|
||||
public function geopos($key, $member, ...$other_members) {}
|
||||
public function georadius($key, $lng, $lan, $radius, $unit, array $opts = null) {}
|
||||
public function georadius_ro($key, $lng, $lan, $radius, $unit, array $opts = null) {}
|
||||
public function georadiusbymember($key, $member, $radius, $unit, array $opts = null) {}
|
||||
public function georadiusbymember_ro($key, $member, $radius, $unit, array $opts = null) {}
|
||||
public function get($key) {}
|
||||
public function getbit($key, $offset) {}
|
||||
public function getlasterror() {}
|
||||
public function getmode() {}
|
||||
public function getoption($option) {}
|
||||
public function getrange($key, $start, $end) {}
|
||||
public function getset($key, $value) {}
|
||||
public function hdel($key, $member, ...$other_members) {}
|
||||
public function hexists($key, $member) {}
|
||||
public function hget($key, $member) {}
|
||||
public function hgetall($key) {}
|
||||
public function hincrby($key, $member, $value) {}
|
||||
public function hincrbyfloat($key, $member, $value) {}
|
||||
public function hkeys($key) {}
|
||||
public function hlen($key) {}
|
||||
public function hmget($key, array $keys) {}
|
||||
public function hmset($key, array $pairs) {}
|
||||
public function hscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) {}
|
||||
public function hset($key, $member, $value) {}
|
||||
public function hsetnx($key, $member, $value) {}
|
||||
public function hstrlen($key, $member) {}
|
||||
public function hvals($key) {}
|
||||
public function incr($key) {}
|
||||
public function incrby($key, $value) {}
|
||||
public function incrbyfloat($key, $value) {}
|
||||
public function info($key_or_address, $option = null) {}
|
||||
public function keys($pattern) {}
|
||||
public function lastsave($key_or_address) {}
|
||||
public function lget($key, $index) {}
|
||||
public function lindex($key, $index) {}
|
||||
public function linsert($key, $position, $pivot, $value) {}
|
||||
public function llen($key) {}
|
||||
public function lpop($key) {}
|
||||
public function lpush($key, $value) {}
|
||||
public function lpushx($key, $value) {}
|
||||
public function lrange($key, $start, $end) {}
|
||||
public function lrem($key, $value) {}
|
||||
public function lset($key, $index, $value) {}
|
||||
public function ltrim($key, $start, $stop) {}
|
||||
public function mget(array $keys) {}
|
||||
public function mset(array $pairs) {}
|
||||
public function msetnx(array $pairs) {}
|
||||
public function multi() {}
|
||||
public function object($field, $key) {}
|
||||
public function persist($key) {}
|
||||
public function pexpire($key, $timestamp) {}
|
||||
public function pexpireat($key, $timestamp) {}
|
||||
public function pfadd($key, array $elements) {}
|
||||
public function pfcount($key) {}
|
||||
public function pfmerge($dstkey, array $keys) {}
|
||||
public function ping($key_or_address) {}
|
||||
public function psetex($key, $expire, $value) {}
|
||||
public function psubscribe(array $patterns, $callback) {}
|
||||
public function pttl($key) {}
|
||||
public function publish($channel, $message) {}
|
||||
public function pubsub($key_or_address, $arg = null, ...$other_args) {}
|
||||
public function punsubscribe($pattern, ...$other_patterns) {}
|
||||
public function randomkey($key_or_address) {}
|
||||
public function rawcommand($cmd, ...$args) {}
|
||||
public function rename($key, $newkey) {}
|
||||
public function renamenx($key, $newkey) {}
|
||||
public function restore($ttl, $key, $value) {}
|
||||
public function role() {}
|
||||
public function rpop($key) {}
|
||||
public function rpoplpush($src, $dst) {}
|
||||
public function rpush($key, $value) {}
|
||||
public function rpushx($key, $value) {}
|
||||
public function sadd($key, $value) {}
|
||||
public function saddarray($key, array $options) {}
|
||||
public function save($key_or_address) {}
|
||||
public function scan(&$i_iterator, $str_node, $str_pattern = null, $i_count = null) {}
|
||||
public function scard($key) {}
|
||||
public function script($key_or_address, $arg = null, ...$other_args) {}
|
||||
public function sdiff($key, ...$other_keys) {}
|
||||
public function sdiffstore($dst, $key, ...$other_keys) {}
|
||||
public function set($key, $value, $opts = null) {}
|
||||
public function setbit($key, $offset, $value) {}
|
||||
public function setex($key, $expire, $value) {}
|
||||
public function setnx($key, $value) {}
|
||||
public function setoption($option, $value) {}
|
||||
public function setrange($key, $offset, $value) {}
|
||||
public function sinter($key, ...$other_keys) {}
|
||||
public function sinterstore($dst, $key, ...$other_keys) {}
|
||||
public function sismember($key, $value) {}
|
||||
public function slowlog($key_or_address, $arg = null, ...$other_args) {}
|
||||
public function smembers($key) {}
|
||||
public function smove($src, $dst, $value) {}
|
||||
public function sort($key, array $options = null) {}
|
||||
public function spop($key) {}
|
||||
public function srandmember($key, $count = null) {}
|
||||
public function srem($key, $value) {}
|
||||
public function sscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) {}
|
||||
public function strlen($key) {}
|
||||
public function subscribe(array $channels, $callback) {}
|
||||
public function sunion($key, ...$other_keys) {}
|
||||
public function sunionstore($dst, $key, ...$other_keys) {}
|
||||
public function time() {}
|
||||
public function ttl($key) {}
|
||||
public function type($key) {}
|
||||
public function unsubscribe($channel, ...$other_channels) {}
|
||||
public function unlink($key, ...$other_keys) {}
|
||||
public function unwatch() {}
|
||||
public function watch($key, ...$other_keys) {}
|
||||
public function xack($str_key, $str_group, array $arr_ids) {}
|
||||
public function xadd($str_key, $str_id, array $arr_fields, $i_maxlen = null, $boo_approximate = null) {}
|
||||
public function xclaim($str_key, $str_group, $str_consumer, $i_min_idle, array $arr_ids, array $arr_opts = null) {}
|
||||
public function xdel($str_key, array $arr_ids) {}
|
||||
public function xgroup($str_operation, $str_key = null, $str_arg1 = null, $str_arg2 = null, $str_arg3 = null) {}
|
||||
public function xinfo($str_cmd, $str_key = null, $str_group = null) {}
|
||||
public function xlen($key) {}
|
||||
public function xpending($str_key, $str_group, $str_start = null, $str_end = null, $i_count = null, $str_consumer = null) {}
|
||||
public function xrange($str_key, $str_start, $str_end, $i_count = null) {}
|
||||
public function xread(array $arr_streams, $i_count = null, $i_block = null) {}
|
||||
public function xreadgroup($str_group, $str_consumer, array $arr_streams, $i_count = null, $i_block = null) {}
|
||||
public function xrevrange($str_key, $str_start, $str_end, $i_count = null) {}
|
||||
public function xtrim($str_key, $i_maxlen, $boo_approximate = null) {}
|
||||
public function zadd($key, $score, $value) {}
|
||||
public function zcard($key) {}
|
||||
public function zcount($key, $min, $max) {}
|
||||
public function zincrby($key, $value, $member) {}
|
||||
public function zinterstore($key, array $keys, ?array $weights = null, $aggregate = null) {}
|
||||
public function zlexcount($key, $min, $max) {}
|
||||
public function zpopmax($key) {}
|
||||
public function zpopmin($key) {}
|
||||
public function zrange($key, $start, $end, $scores = null) {}
|
||||
public function zrangebylex($key, $min, $max, $offset = null, $limit = null) {}
|
||||
public function zrangebyscore($key, $start, $end, array $options = null) {}
|
||||
public function zrank($key, $member) {}
|
||||
public function zrem($key, $member, ...$other_members) {}
|
||||
public function zremrangebylex($key, $min, $max) {}
|
||||
public function zremrangebyrank($key, $min, $max) {}
|
||||
public function zremrangebyscore($key, $min, $max) {}
|
||||
public function zrevrange($key, $start, $end, $scores = null) {}
|
||||
public function zrevrangebylex($key, $min, $max, $offset = null, $limit = null) {}
|
||||
public function zrevrangebyscore($key, $start, $end, array $options = null) {}
|
||||
public function zrevrank($key, $member) {}
|
||||
public function zscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null) {}
|
||||
public function zscore($key, $member) {}
|
||||
public function zunionstore($key, array $keys, ?array $weights = null, $aggregate = null) {}
|
||||
}
|
||||
|
||||
class RedisClusterException extends \Exception {
|
||||
|
||||
// properties
|
||||
protected $message;
|
||||
protected $code;
|
||||
protected $file;
|
||||
protected $line;
|
||||
}
|
||||
|
||||
class RedisException extends \Exception {
|
||||
|
||||
// properties
|
||||
protected $message;
|
||||
protected $code;
|
||||
protected $file;
|
||||
protected $line;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
<?php
|
||||
// These stubs were generated by the phan stub generator.
|
||||
// @phan-stub-for-extension sockets@7.0.33-0+deb9u3
|
||||
|
||||
namespace {
|
||||
function socket_accept($socket) {}
|
||||
function socket_bind($socket, $addr, $port = null) {}
|
||||
function socket_clear_error($socket = null) {}
|
||||
function socket_close($socket) {}
|
||||
function socket_cmsg_space($level, $type) {}
|
||||
function socket_connect($socket, $addr, $port = null) {}
|
||||
function socket_create($domain, $type, $protocol) {}
|
||||
function socket_create_listen($port, $backlog = null) {}
|
||||
function socket_create_pair($domain, $type, $protocol, &$fd) {}
|
||||
function socket_export_stream($socket) {}
|
||||
function socket_get_option($socket, $level, $optname) {}
|
||||
function socket_getopt($socket, $level, $optname) {}
|
||||
function socket_getpeername($socket, &$addr, &$port = null) {}
|
||||
function socket_getsockname($socket, &$addr, &$port = null) {}
|
||||
function socket_import_stream($stream) {}
|
||||
function socket_last_error($socket = null) {}
|
||||
function socket_listen($socket, $backlog = null) {}
|
||||
function socket_read($socket, $length, $type = null) {}
|
||||
function socket_recv($socket, &$buf, $len, $flags) {}
|
||||
function socket_recvfrom($socket, &$buf, $len, $flags, &$name, &$port = null) {}
|
||||
function socket_recvmsg($socket, &$msghdr, $flags) {}
|
||||
function socket_select(&$read_fds, &$write_fds, &$except_fds, $tv_sec, $tv_usec = null) {}
|
||||
function socket_send($socket, $buf, $len, $flags) {}
|
||||
function socket_sendmsg($socket, $msghdr, $flags) {}
|
||||
function socket_sendto($socket, $buf, $len, $flags, $addr, $port = null) {}
|
||||
function socket_set_block($socket) {}
|
||||
function socket_set_nonblock($socket) {}
|
||||
function socket_set_option($socket, $level, $optname, $optval) {}
|
||||
function socket_setopt($socket, $level, $optname, $optval) {}
|
||||
function socket_shutdown($socket, $how = null) {}
|
||||
function socket_strerror($errno) {}
|
||||
function socket_write($socket, $buf, $length = null) {}
|
||||
const AF_INET = 2;
|
||||
const AF_INET6 = 10;
|
||||
const AF_UNIX = 1;
|
||||
const IPPROTO_IP = 0;
|
||||
const IPPROTO_IPV6 = 41;
|
||||
const IPV6_HOPLIMIT = 52;
|
||||
const IPV6_MULTICAST_HOPS = 18;
|
||||
const IPV6_MULTICAST_IF = 17;
|
||||
const IPV6_MULTICAST_LOOP = 19;
|
||||
const IPV6_PKTINFO = 50;
|
||||
const IPV6_RECVHOPLIMIT = 51;
|
||||
const IPV6_RECVPKTINFO = 49;
|
||||
const IPV6_RECVTCLASS = 66;
|
||||
const IPV6_TCLASS = 67;
|
||||
const IPV6_UNICAST_HOPS = 16;
|
||||
const IPV6_V6ONLY = 26;
|
||||
const IP_MULTICAST_IF = 32;
|
||||
const IP_MULTICAST_LOOP = 34;
|
||||
const IP_MULTICAST_TTL = 33;
|
||||
const MCAST_BLOCK_SOURCE = 43;
|
||||
const MCAST_JOIN_GROUP = 42;
|
||||
const MCAST_JOIN_SOURCE_GROUP = 46;
|
||||
const MCAST_LEAVE_GROUP = 45;
|
||||
const MCAST_LEAVE_SOURCE_GROUP = 47;
|
||||
const MCAST_UNBLOCK_SOURCE = 44;
|
||||
const MSG_CMSG_CLOEXEC = 1073741824;
|
||||
const MSG_CONFIRM = 2048;
|
||||
const MSG_CTRUNC = 8;
|
||||
const MSG_DONTROUTE = 4;
|
||||
const MSG_DONTWAIT = 64;
|
||||
const MSG_EOF = 512;
|
||||
const MSG_EOR = 128;
|
||||
const MSG_ERRQUEUE = 8192;
|
||||
const MSG_MORE = 32768;
|
||||
const MSG_NOSIGNAL = 16384;
|
||||
const MSG_OOB = 1;
|
||||
const MSG_PEEK = 2;
|
||||
const MSG_TRUNC = 32;
|
||||
const MSG_WAITALL = 256;
|
||||
const MSG_WAITFORONE = 65536;
|
||||
const PHP_BINARY_READ = 2;
|
||||
const PHP_NORMAL_READ = 1;
|
||||
const SCM_CREDENTIALS = 2;
|
||||
const SCM_RIGHTS = 1;
|
||||
const SOCKET_E2BIG = 7;
|
||||
const SOCKET_EACCES = 13;
|
||||
const SOCKET_EADDRINUSE = 98;
|
||||
const SOCKET_EADDRNOTAVAIL = 99;
|
||||
const SOCKET_EADV = 68;
|
||||
const SOCKET_EAFNOSUPPORT = 97;
|
||||
const SOCKET_EAGAIN = 11;
|
||||
const SOCKET_EALREADY = 114;
|
||||
const SOCKET_EBADE = 52;
|
||||
const SOCKET_EBADF = 9;
|
||||
const SOCKET_EBADFD = 77;
|
||||
const SOCKET_EBADMSG = 74;
|
||||
const SOCKET_EBADR = 53;
|
||||
const SOCKET_EBADRQC = 56;
|
||||
const SOCKET_EBADSLT = 57;
|
||||
const SOCKET_EBUSY = 16;
|
||||
const SOCKET_ECHRNG = 44;
|
||||
const SOCKET_ECOMM = 70;
|
||||
const SOCKET_ECONNABORTED = 103;
|
||||
const SOCKET_ECONNREFUSED = 111;
|
||||
const SOCKET_ECONNRESET = 104;
|
||||
const SOCKET_EDESTADDRREQ = 89;
|
||||
const SOCKET_EDQUOT = 122;
|
||||
const SOCKET_EEXIST = 17;
|
||||
const SOCKET_EFAULT = 14;
|
||||
const SOCKET_EHOSTDOWN = 112;
|
||||
const SOCKET_EHOSTUNREACH = 113;
|
||||
const SOCKET_EIDRM = 43;
|
||||
const SOCKET_EINPROGRESS = 115;
|
||||
const SOCKET_EINTR = 4;
|
||||
const SOCKET_EINVAL = 22;
|
||||
const SOCKET_EIO = 5;
|
||||
const SOCKET_EISCONN = 106;
|
||||
const SOCKET_EISDIR = 21;
|
||||
const SOCKET_EISNAM = 120;
|
||||
const SOCKET_EL2HLT = 51;
|
||||
const SOCKET_EL2NSYNC = 45;
|
||||
const SOCKET_EL3HLT = 46;
|
||||
const SOCKET_EL3RST = 47;
|
||||
const SOCKET_ELNRNG = 48;
|
||||
const SOCKET_ELOOP = 40;
|
||||
const SOCKET_EMEDIUMTYPE = 124;
|
||||
const SOCKET_EMFILE = 24;
|
||||
const SOCKET_EMLINK = 31;
|
||||
const SOCKET_EMSGSIZE = 90;
|
||||
const SOCKET_EMULTIHOP = 72;
|
||||
const SOCKET_ENAMETOOLONG = 36;
|
||||
const SOCKET_ENETDOWN = 100;
|
||||
const SOCKET_ENETRESET = 102;
|
||||
const SOCKET_ENETUNREACH = 101;
|
||||
const SOCKET_ENFILE = 23;
|
||||
const SOCKET_ENOANO = 55;
|
||||
const SOCKET_ENOBUFS = 105;
|
||||
const SOCKET_ENOCSI = 50;
|
||||
const SOCKET_ENODATA = 61;
|
||||
const SOCKET_ENODEV = 19;
|
||||
const SOCKET_ENOENT = 2;
|
||||
const SOCKET_ENOLCK = 37;
|
||||
const SOCKET_ENOLINK = 67;
|
||||
const SOCKET_ENOMEDIUM = 123;
|
||||
const SOCKET_ENOMEM = 12;
|
||||
const SOCKET_ENOMSG = 42;
|
||||
const SOCKET_ENONET = 64;
|
||||
const SOCKET_ENOPROTOOPT = 92;
|
||||
const SOCKET_ENOSPC = 28;
|
||||
const SOCKET_ENOSR = 63;
|
||||
const SOCKET_ENOSTR = 60;
|
||||
const SOCKET_ENOSYS = 38;
|
||||
const SOCKET_ENOTBLK = 15;
|
||||
const SOCKET_ENOTCONN = 107;
|
||||
const SOCKET_ENOTDIR = 20;
|
||||
const SOCKET_ENOTEMPTY = 39;
|
||||
const SOCKET_ENOTSOCK = 88;
|
||||
const SOCKET_ENOTTY = 25;
|
||||
const SOCKET_ENOTUNIQ = 76;
|
||||
const SOCKET_ENXIO = 6;
|
||||
const SOCKET_EOPNOTSUPP = 95;
|
||||
const SOCKET_EPERM = 1;
|
||||
const SOCKET_EPFNOSUPPORT = 96;
|
||||
const SOCKET_EPIPE = 32;
|
||||
const SOCKET_EPROTO = 71;
|
||||
const SOCKET_EPROTONOSUPPORT = 93;
|
||||
const SOCKET_EPROTOTYPE = 91;
|
||||
const SOCKET_EREMCHG = 78;
|
||||
const SOCKET_EREMOTE = 66;
|
||||
const SOCKET_EREMOTEIO = 121;
|
||||
const SOCKET_ERESTART = 85;
|
||||
const SOCKET_EROFS = 30;
|
||||
const SOCKET_ESHUTDOWN = 108;
|
||||
const SOCKET_ESOCKTNOSUPPORT = 94;
|
||||
const SOCKET_ESPIPE = 29;
|
||||
const SOCKET_ESRMNT = 69;
|
||||
const SOCKET_ESTRPIPE = 86;
|
||||
const SOCKET_ETIME = 62;
|
||||
const SOCKET_ETIMEDOUT = 110;
|
||||
const SOCKET_ETOOMANYREFS = 109;
|
||||
const SOCKET_EUNATCH = 49;
|
||||
const SOCKET_EUSERS = 87;
|
||||
const SOCKET_EWOULDBLOCK = 11;
|
||||
const SOCKET_EXDEV = 18;
|
||||
const SOCKET_EXFULL = 54;
|
||||
const SOCK_DGRAM = 2;
|
||||
const SOCK_RAW = 3;
|
||||
const SOCK_RDM = 4;
|
||||
const SOCK_SEQPACKET = 5;
|
||||
const SOCK_STREAM = 1;
|
||||
const SOL_SOCKET = 1;
|
||||
const SOL_TCP = 6;
|
||||
const SOL_UDP = 17;
|
||||
const SOMAXCONN = 128;
|
||||
const SO_BINDTODEVICE = 25;
|
||||
const SO_BROADCAST = 6;
|
||||
const SO_DEBUG = 1;
|
||||
const SO_DONTROUTE = 5;
|
||||
const SO_ERROR = 4;
|
||||
const SO_KEEPALIVE = 9;
|
||||
const SO_LINGER = 13;
|
||||
const SO_OOBINLINE = 10;
|
||||
const SO_PASSCRED = 16;
|
||||
const SO_RCVBUF = 8;
|
||||
const SO_RCVLOWAT = 18;
|
||||
const SO_RCVTIMEO = 20;
|
||||
const SO_REUSEADDR = 2;
|
||||
const SO_REUSEPORT = 15;
|
||||
const SO_SNDBUF = 7;
|
||||
const SO_SNDLOWAT = 19;
|
||||
const SO_SNDTIMEO = 21;
|
||||
const SO_TYPE = 3;
|
||||
const TCP_NODELAY = 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
// These stubs were generated by the phan stub generator.
|
||||
// @phan-stub-for-extension tideways_xhprof@5.0.4
|
||||
|
||||
namespace {
|
||||
function tideways_xhprof_disable() {}
|
||||
function tideways_xhprof_enable($options = null) {}
|
||||
const TIDEWAYS_XHPROF_FLAGS_CPU = 1;
|
||||
const TIDEWAYS_XHPROF_FLAGS_MEMORY = 6;
|
||||
const TIDEWAYS_XHPROF_FLAGS_MEMORY_ALLOC = 16;
|
||||
const TIDEWAYS_XHPROF_FLAGS_MEMORY_ALLOC_AS_MU = 48;
|
||||
const TIDEWAYS_XHPROF_FLAGS_MEMORY_MU = 2;
|
||||
const TIDEWAYS_XHPROF_FLAGS_MEMORY_PMU = 4;
|
||||
const TIDEWAYS_XHPROF_FLAGS_NO_BUILTINS = 8;
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?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
|
||||
*/
|
||||
|
||||
// phpcs:ignoreFile
|
||||
|
||||
/**
|
||||
* @param string $text1
|
||||
* @param string $text2
|
||||
* @param int $numContextLines
|
||||
* @param int $movedParagraphDetectionCutoff
|
||||
* @return string
|
||||
*/
|
||||
function wikidiff2_do_diff( $text1, $text2, $numContextLines, $movedParagraphDetectionCutoff = 0 ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $text1
|
||||
* @param string $text2
|
||||
* @param int $numContextLines
|
||||
* @return string
|
||||
*/
|
||||
function wikidiff2_inline_diff( $text1, $text2, $numContextLines ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $text1
|
||||
* @param string $text2
|
||||
* @param int $numContextLines
|
||||
* @return string
|
||||
*/
|
||||
function wikidiff2_inline_json_diff( $text1, $text2, $numContextLines ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $text1
|
||||
* @param string $text2
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
function wikidiff2_multi_format_diff( $text1, $text2, $options ) {
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
// Stub for PHP 8.2's AllowDynamicProperties class
|
||||
#[Attribute]
|
||||
class AllowDynamicProperties {
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
# For the purpose of phan, we're always core's DOM implementation.
|
||||
|
||||
class_alias( "DOMAttr", "Wikimedia\\Parsoid\\DOM\\Attr" );
|
||||
class_alias( "DOMCharacterData", "Wikimedia\\Parsoid\\DOM\\CharacterData" );
|
||||
class_alias( "DOMComment", "Wikimedia\\Parsoid\\DOM\\Comment" );
|
||||
class_alias( "DOMDocument", "Wikimedia\\Parsoid\\DOM\\Document" );
|
||||
class_alias( "DOMDocumentFragment", "Wikimedia\\Parsoid\\DOM\\DocumentFragment" );
|
||||
class_alias( "DOMDocumentType", "Wikimedia\\Parsoid\\DOM\\DocumentType" );
|
||||
class_alias( "DOMElement", "Wikimedia\\Parsoid\\DOM\\Element" );
|
||||
class_alias( "DOMNode", "Wikimedia\\Parsoid\\DOM\\Node" );
|
||||
class_alias( "DOMProcessingInstruction", "Wikimedia\\Parsoid\\DOM\\ProcessingInstruction" );
|
||||
class_alias( "DOMText", "Wikimedia\\Parsoid\\DOM\\Text" );
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
These stubs describe how code that is not available at analysis time should be
|
||||
used. No implementations are necessary, just define the classes and their
|
||||
methods and use phpdoc to describe what arguments are allowed.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
// Stub for PHP 8.1's Socket class
|
||||
final class Socket {
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
<?xml version="1.0"?>
|
||||
<ruleset name="MediaWiki">
|
||||
<rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki">
|
||||
<exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationPrivate" />
|
||||
<exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationProtected" />
|
||||
<exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationPublic" />
|
||||
<exclude name="MediaWiki.Commenting.FunctionComment.WrongStyle" />
|
||||
<exclude name="MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName" />
|
||||
<exclude name="MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment" />
|
||||
</rule>
|
||||
<rule ref="MediaWiki.NamingConventions.ValidGlobalName">
|
||||
<properties>
|
||||
<property name="ignoreList" type="array" value="$IP" />
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="MediaWiki.NamingConventions.ValidGlobalName.allowedPrefix">
|
||||
<exclude-pattern>*/maintenance/doMaintenance\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/CommandLineInc\.php</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="Generic.Files.LineLength">
|
||||
<exclude-pattern>*/languages/messages/*</exclude-pattern>
|
||||
<exclude-pattern>*/tests/*</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="MediaWiki.Files.ClassMatchesFilename.NotMatch">
|
||||
<!--
|
||||
Continue to allow existing violations, but enable the sniff to prevent
|
||||
any new occurrences.
|
||||
-->
|
||||
<exclude-pattern>*/maintenance/cleanupTitles\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/edit\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/findDeprecated\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/getText\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/importDump\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/install\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/jsparse\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/lag\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/language/StatOutputs\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/language/date-formats\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/mysql\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/parse\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/rebuildImages\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/renderDump\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/shell\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/sql\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/update\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/userOptions\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/view\.php</exclude-pattern>
|
||||
<!-- Skip violations in some tests for now -->
|
||||
<exclude-pattern>*/tests/parser/*</exclude-pattern>
|
||||
<exclude-pattern>*/tests/phpunit/maintenance/*</exclude-pattern>
|
||||
<exclude-pattern>*/tests/phpunit/bootstrap\.php</exclude-pattern>
|
||||
<exclude-pattern>*/tests/phpunit/phpunit\.php</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="MediaWiki.Files.ClassMatchesFilename.WrongCase">
|
||||
<!--
|
||||
Continue to allow existing violations, but enable the sniff to prevent
|
||||
any new occurrences.
|
||||
-->
|
||||
<exclude-pattern>*/maintenance/language/alltrans\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/language/digit2html\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/language/langmemusage\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/mctest\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/mwdocgen\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/rebuildall\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/rebuildmessages\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/rebuildrecentchanges\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/rebuildtextindex\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/storage/checkStorage\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/storage/recompressTracked\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/storage/trackBlobs\.php</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="Generic.PHP.NoSilencedErrors.Discouraged">
|
||||
<exclude-pattern>*/tests/*</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="Generic.Files.OneObjectStructurePerFile.MultipleFound">
|
||||
<!--
|
||||
Continue to allow existing violations, but enable the sniff to prevent
|
||||
any new occurrences.
|
||||
-->
|
||||
<exclude-pattern>*/maintenance/dumpIterator\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/findDeprecated\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/storage/recompressTracked\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/language/StatOutputs\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/language/generateCollationData\.php</exclude-pattern>
|
||||
<!-- We don't care that much about violations in tests -->
|
||||
<exclude-pattern>*/tests/*</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="MediaWiki.Usage.AssignmentInReturn.AssignmentInReturn">
|
||||
<exclude-pattern>*/tests/phpunit/*</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="MediaWiki.Usage.ForbiddenFunctions.popen">
|
||||
<!--
|
||||
Continue to allow existing violations, but enable the sniff to prevent
|
||||
any new occurrences.
|
||||
-->
|
||||
<exclude-pattern>*/includes/GlobalFunctions\.php</exclude-pattern>
|
||||
<exclude-pattern>*/includes/libs/filebackend/FSFileBackend\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/includes/SevenZipStream\.php</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="MediaWiki.Usage.ForbiddenFunctions.proc_open">
|
||||
<!--
|
||||
Continue to allow existing violations, but enable the sniff to prevent
|
||||
any new occurrences.
|
||||
-->
|
||||
<exclude-pattern>*/includes/export/DumpPipeOutput\.php</exclude-pattern>
|
||||
<exclude-pattern>*/includes/ResourceLoader/Image\.php</exclude-pattern>
|
||||
<exclude-pattern>*/includes/shell/Command\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/includes/TextPassDumper\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/mysql\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/storage/recompressTracked\.php</exclude-pattern>
|
||||
<exclude-pattern>*/tests/parser/editTests\.php</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="MediaWiki.Usage.ForbiddenFunctions.shell_exec">
|
||||
<!--
|
||||
Continue to allow existing violations, but enable the sniff to prevent
|
||||
any new occurrences.
|
||||
-->
|
||||
<exclude-pattern>*/maintenance/mwdocgen\.php</exclude-pattern>
|
||||
<exclude-pattern>*/maintenance/updateCredits\.php</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="MediaWiki.Usage.ForbiddenFunctions.system">
|
||||
<!--
|
||||
Continue to allow existing violations, but enable the sniff to prevent
|
||||
any new occurrences.
|
||||
-->
|
||||
<exclude-pattern>*/maintenance/mwdocgen\.php</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="Generic.Arrays.DisallowShortArraySyntax">
|
||||
<!--
|
||||
T273340: Rule not to be enabled on any other file.
|
||||
PHPVersionCheck.php requires syntax to be old PHP compatible.
|
||||
The rest should therefore use [] rather than array() as per the
|
||||
MediaWiki style guide.
|
||||
-->
|
||||
<include-pattern>includes/PHPVersionCheck\.php</include-pattern>
|
||||
</rule>
|
||||
<file>.</file>
|
||||
<arg name="encoding" value="UTF-8"/>
|
||||
<arg name="extensions" value="php"/>
|
||||
<exclude-pattern type="relative">^(extensions|skins)/*</exclude-pattern>
|
||||
<exclude-pattern type="relative">^docs/(coverage|html|js|latex)/*</exclude-pattern>
|
||||
<exclude-pattern>LocalSettings(-installer)?\.php</exclude-pattern>
|
||||
</ruleset>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": [
|
||||
"stylelint-config-wikimedia/support-basic",
|
||||
"stylelint-config-wikimedia/mediawiki"
|
||||
],
|
||||
"rules": {
|
||||
"selector-class-pattern": "^((mw|oo-ui|cdx)-|(wikitable|(toc(|toggle|hidden))|client-(no)?js)$)",
|
||||
"no-descending-specificity": null,
|
||||
"selector-max-id": null
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* SVGO Configuration
|
||||
* Compatible to v3.0.0+
|
||||
* Recommended options from:
|
||||
* https://www.mediawiki.org/wiki/Manual:Coding_conventions/SVG#Exemplified_safe_configuration
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
{
|
||||
// Set of built-in plugins enabled by default.
|
||||
name: 'preset-default',
|
||||
params: {
|
||||
overrides: {
|
||||
cleanupIds: false,
|
||||
removeDesc: false,
|
||||
removeTitle: false,
|
||||
removeViewBox: false,
|
||||
// If the SVG doesn't start with an XML declaration, then its MIME type will
|
||||
// be detected as "text/plain" rather than "image/svg+xml" by libmagic and,
|
||||
// consequently, MediaWiki's CSSMin CSS minifier. libmagic's default database
|
||||
// currently requires that SVGs contain an XML declaration:
|
||||
// https://github.com/threatstack/libmagic/blob/master/magic/Magdir/sgml#L5
|
||||
removeXMLProcInst: false
|
||||
}
|
||||
}
|
||||
},
|
||||
'removeRasterImages',
|
||||
'sortAttrs'
|
||||
],
|
||||
// Set whitespace according to Wikimedia Coding Conventions.
|
||||
// @see https://github.com/svg/svgo/blob/main/lib/stringifier.js#L39 for available options.
|
||||
js2svg: {
|
||||
eol: 'lf',
|
||||
finalNewline: true,
|
||||
// Configure the indent to tabs (default 4 spaces) used by `--pretty` here.
|
||||
indent: '\t',
|
||||
pretty: true
|
||||
},
|
||||
multipass: true
|
||||
};
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"$schema": "http://json.schemastore.org/vsls",
|
||||
"gitignore": "hide",
|
||||
"excludeFiles": [
|
||||
"!node_modules",
|
||||
"!vendor"
|
||||
],
|
||||
"hideFiles": [
|
||||
"!node_modules",
|
||||
"!vendor"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Code of Conduct
|
||||
===============
|
||||
|
||||
The development of this software is covered by a [Code of Conduct](https://www.mediawiki.org/wiki/Special:MyLanguage/Code_of_Conduct).
|
||||
|
|
@ -0,0 +1,378 @@
|
|||
== License and copyright information ==
|
||||
|
||||
=== License ===
|
||||
|
||||
MediaWiki is licensed under the terms of the GNU General Public License,
|
||||
version 2 or later. Derivative works and later versions of the code must be
|
||||
free software licensed under the same or a compatible license. This includes
|
||||
"extensions" that use MediaWiki functions or variables; see
|
||||
https://www.gnu.org/licenses/gpl-faq.html#GPLAndPlugins for details.
|
||||
|
||||
For the full text of version 2 of the license, see
|
||||
https://www.gnu.org/licenses/gpl-2.0.html or '''GNU General Public License'''
|
||||
below.
|
||||
|
||||
=== Copyright owners ===
|
||||
|
||||
MediaWiki contributors, including those listed in the CREDITS file, hold the
|
||||
copyright to this work.
|
||||
|
||||
=== Additional license information ===
|
||||
|
||||
Some components of MediaWiki imported from other projects may be under other
|
||||
Free and Open Source, or Free Culture, licenses. Specific details of their
|
||||
licensing information can be found in those components.
|
||||
|
||||
Sections of code written exclusively by Lee Crocker or Erik Moeller are also
|
||||
released into the public domain, which does not impair the obligations of users
|
||||
under the GPL for use of the whole code or other sections thereof.
|
||||
|
||||
MediaWiki uses the following Creative Commons icons to illustrate links to the
|
||||
CC licenses:
|
||||
|
||||
* resources/assets/licenses/cc-0.png
|
||||
* resources/assets/licenses/cc-by-nc-sa.png
|
||||
* resources/assets/licenses/cc-by-sa.png
|
||||
* resources/assets/licenses/cc-by.png
|
||||
|
||||
These icons are trademarked, and used subject to the CC trademark license,
|
||||
available at https://creativecommons.org/policies#trademark
|
||||
|
||||
== GNU GENERAL PUBLIC LICENSE ==
|
||||
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
<https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
=== Preamble ===
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
== TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ==
|
||||
|
||||
'''0.''' This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
'''1.''' You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
'''2.''' You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
'''a)''' You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
'''b)''' You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
'''c)''' If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
'''3.''' You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
'''a)''' Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
'''b)''' Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
'''c)''' Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
'''4.''' You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
'''5.''' You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
'''6.''' Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
'''7.''' If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
'''8.''' If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
'''9.''' The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
'''10.''' If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
=== NO WARRANTY ===
|
||||
|
||||
'''11.''' BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
'''12.''' IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
'''END OF TERMS AND CONDITIONS'''
|
||||
|
||||
== How to Apply These Terms to Your New Programs ==
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Moe Ghoul>, 1 April 1989
|
||||
Moe Ghoul, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,464 @@
|
|||
# MediaWiki Developers
|
||||
|
||||
Welcome to the MediaWiki community! Please see [How to become a MediaWiki
|
||||
hacker](https://www.mediawiki.org/wiki/How_to_become_a_MediaWiki_hacker) for
|
||||
general information on contributing to MediaWiki.
|
||||
|
||||
## Development environment
|
||||
|
||||
MediaWiki provides an extendable local development environment based on Docker Compose. This environment provides PHP,
|
||||
Apache, Xdebug and a SQLite database.
|
||||
|
||||
**Do not use the development environment to serve a public website! Bad things would happen!**
|
||||
|
||||
More documentation, examples, and configuration recipes are available at [mediawiki.org/wiki/MediaWiki-Docker][mw-docker].
|
||||
|
||||
Support is available on the [Libera IRC network][libera-home] in the [#mediawiki channel][libera-webchat], and on
|
||||
Phabricator by creating tasks with the [MediaWiki-Docker][mw-docker-phab] tag.
|
||||
|
||||
[mw-docker]: https://www.mediawiki.org/wiki/MediaWiki-Docker
|
||||
[mw-docker-phab]: https://phabricator.wikimedia.org/tag/mediawiki-docker/
|
||||
[libera-home]: https://libera.chat/
|
||||
[libera-webchat]: https://web.libera.chat/#mediawiki
|
||||
|
||||
## Quickstart
|
||||
|
||||
### 1. Requirements
|
||||
|
||||
You'll need to have Docker installed:
|
||||
|
||||
* [Docker Desktop][docker-install] for macOS or Windows.
|
||||
* [Docker engine][docker-linux] for Linux.
|
||||
|
||||
[docker-install]: https://docs.docker.com/get-docker/
|
||||
[docker-linux]: https://docs.docker.com/engine/install/
|
||||
|
||||
**Linux users**:
|
||||
|
||||
* We recommend installing `docker-ce`, `docker-ce-cli`, `containerd.io`, and `docker-compose-plugin` by [downloading the server
|
||||
releases][dc-release] for your distribution rather than Docker Desktop. You can also install the [binaries][dc-binaries].
|
||||
* Follow the instructions to ["Manage Docker as a non-root user"][dc-non-root]
|
||||
|
||||
[dc-release]: https://docs.docker.com/engine/install/
|
||||
[dc-binaries]: https://docs.docker.com/engine/install/binaries/
|
||||
[dc-non-root]: https://docs.docker.com/install/linux/linux-postinstall/#manage-docker-as-a-non-root-user
|
||||
|
||||
**Windows users**:
|
||||
|
||||
Running Docker from a Windows terminal and using the Windows file system will result in MediaWiki being very slow. For Windows 10 and higher, we recommend configuring Docker and Windows to use the [Windows Subsystem for Linux (WSL)](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux). Turn on WSL in your Windows settings, then run the following commands: `wsl --install -d ubuntu` and `wsl --set-version ubuntu 2`. Then go into Docker -> Settings -> General -> tick "Use the WSL 2 based engine", then go into Docker -> Settings -> Resources -> WSL Integration -> tick "Ubuntu". `git clone` the mediawiki repository into a WSL folder such as `home/yourusername/mediawiki` so that the files are inside WSL. Then you can run most of the commands in this tutorial outside of WSL, by opening PowerShell, navigating to the WSL directory with `cd \\wsl.localhost\Ubuntu\home\yourusername\mediawiki`, and executing shell commands as normal. To access WSL from PowerShell (rare but may be needed sometimes), you can use the command `ubuntu` to turn a PowerShell console into a WSL console. To navigate to WSL folders in [File Explorer](https://en.wikipedia.org/wiki/File_Explorer), show the Navigation Pane, then towards the bottom, look for "Linux" (it will be close to "This PC").
|
||||
|
||||
**Mac users**:
|
||||
|
||||
If you're using Docker Desktop and have the `Use Rosetta for x86/amd64 emulation on Apple Silicon` setting enabled, you may encounter an issue where loading the wiki results in a blank page or a 503 error. To resolve this, disable the setting and restart Docker Desktop. See [this page](https://phabricator.wikimedia.org/P49617) for more information.
|
||||
|
||||
### 2. Download MediaWiki files
|
||||
|
||||
Download the latest MediaWiki files to your computer. One way to download the latest alpha version of MediaWiki is to
|
||||
[install git](https://git-scm.com/), open a shell, navigate to the directory where you want to save the files, then type
|
||||
`git clone https://gerrit.wikimedia.org/r/mediawiki/core.git mediawiki`.
|
||||
|
||||
Optional: If you plan to submit patches to this repository, you will probably want to [create a Gerrit account](https://wikitech.wikimedia.org/wiki/Help:Create_a_Wikimedia_developer_account),
|
||||
then type `git remote set-url origin ssh://YOUR-GERRIT-USERNAME-HERE@gerrit.wikimedia.org:29418/mediawiki/core`,
|
||||
replacing YOUR-GERRIT-USERNAME-HERE with your Gerrit username. Please see the official
|
||||
[MediaWiki Gerrit tutorial](https://www.mediawiki.org/wiki/Gerrit/Tutorial) for more information.
|
||||
|
||||
### 3. Prepare `.env` file
|
||||
|
||||
Using a text editor, create a `.env` file in the root of the MediaWiki core repository, and copy these contents into
|
||||
that file:
|
||||
|
||||
```sh
|
||||
MW_SCRIPT_PATH=/w
|
||||
MW_SERVER=http://localhost:8080
|
||||
MW_DOCKER_PORT=8080
|
||||
MEDIAWIKI_USER=Admin
|
||||
MEDIAWIKI_PASSWORD=dockerpass
|
||||
XDEBUG_CONFIG=
|
||||
XDEBUG_ENABLE=true
|
||||
XHPROF_ENABLE=true
|
||||
```
|
||||
|
||||
Windows users: Run the following command to add a blank user ID and group ID to your `.env` file:
|
||||
|
||||
```sh
|
||||
echo "
|
||||
MW_DOCKER_UID=
|
||||
MW_DOCKER_GID=" >> .env
|
||||
```
|
||||
|
||||
Non-Windows users: Run the following command to add your user ID and group ID to your `.env` file:
|
||||
|
||||
```sh
|
||||
echo "MW_DOCKER_UID=$(id -u)
|
||||
MW_DOCKER_GID=$(id -g)" >> .env
|
||||
```
|
||||
|
||||
Linux users: If you'd like to use Xdebug features inside your IDE, then create a `docker-compose.override.yml` file as
|
||||
well:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
mediawiki:
|
||||
# For Linux: This extra_hosts section enables Xdebug-IDE communication:
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
```
|
||||
|
||||
### 4. Create the environment
|
||||
|
||||
* Start the containers:
|
||||
```sh
|
||||
docker compose up -d
|
||||
```
|
||||
The "up" command makes sure that the PHP and webserver containers are running (and any others in the
|
||||
`docker-compose.yml` file). It is safe to run at any time, and will do nothing if the containers are already running.
|
||||
|
||||
The first time, it may take a few minutes to download new Docker images.
|
||||
|
||||
The `-d` argument stands for "detached" mode, which run the services in the background. If you suspect a problem with
|
||||
one of the services, you can run it without `-d` to follow the server logs directly from your terminal. You don't have
|
||||
to stop the services first, if you ran it with `-d` and then without, you'll get connected to the already running
|
||||
containers including a decent back scroll of server logs.
|
||||
|
||||
Note that MediaWiki debug logs go to `/cache/*.log` files (not sent to docker).
|
||||
|
||||
* Install PHP dependencies from Composer:
|
||||
```sh
|
||||
docker compose exec mediawiki composer update
|
||||
```
|
||||
|
||||
* Install MediaWiki:
|
||||
```sh
|
||||
docker compose exec mediawiki /bin/bash /docker/install.sh
|
||||
```
|
||||
Windows users: make sure you run the above command in PowerShell as it does not work in Bash.
|
||||
|
||||
* Windows users: Make sure to set the SQLite directory to be writable.
|
||||
```sh
|
||||
docker compose exec mediawiki chmod -R o+rwx cache/sqlite
|
||||
```
|
||||
|
||||
Done! The wiki should now be available for you at <http://localhost:8080>.
|
||||
|
||||
## Usage
|
||||
|
||||
### Running commands
|
||||
|
||||
You can use `docker compose exec mediawiki bash` to open a Bash shell in the
|
||||
MediaWiki container. You can then run one or more commands as needed and stay
|
||||
within the container shell.
|
||||
|
||||
You can also run a single command in the container directly from your host
|
||||
shell, for example: `docker compose exec mediawiki php maintenance/run.php update`.
|
||||
|
||||
### PHPUnit
|
||||
|
||||
Run a single PHPUnit file or directory:
|
||||
|
||||
```sh
|
||||
docker compose exec mediawiki bash
|
||||
instance:/w$ cd tests/phpunit
|
||||
instance:/w/tests/phpunit$ composer phpunit -- path/to/my/test/
|
||||
```
|
||||
|
||||
See [PHPUnit on mediawiki.org][phpunit-testing] for more examples.
|
||||
|
||||
[phpunit-testing]: https://www.mediawiki.org/wiki/Manual:PHP_unit_testing/Running_the_tests
|
||||
|
||||
### Selenium
|
||||
|
||||
You can use [Fresh][fresh] to run [Selenium in a dedicated
|
||||
container][selenium-dedicated]. Example usage:
|
||||
|
||||
```sh
|
||||
fresh-node -env -net
|
||||
npm ci
|
||||
npm run selenium-test
|
||||
```
|
||||
|
||||
[selenium-dedicated]: https://www.mediawiki.org/wiki/Selenium/Getting_Started/Run_tests_using_Fresh
|
||||
|
||||
### API Testing
|
||||
|
||||
You can use [Fresh][fresh] to run [API tests in a dedicated
|
||||
container][api-dedicated]. Example usage:
|
||||
|
||||
```sh
|
||||
export MW_SERVER=http://localhost:8080/
|
||||
export MW_SCRIPT_PATH=/w
|
||||
export MEDIAWIKI_USER=Admin
|
||||
export MEDIAWIKI_PASSWORD=dockerpass
|
||||
fresh-node -env -net
|
||||
# Create .api-testing.config.json as documented on
|
||||
# https://www.mediawiki.org/wiki/MediaWiki_API_integration_tests
|
||||
npm ci
|
||||
npm run api-testing
|
||||
```
|
||||
|
||||
[fresh]: https://github.com/wikimedia/fresh
|
||||
[api-dedicated]: https://www.mediawiki.org/wiki/MediaWiki_API_integration_tests
|
||||
|
||||
## Modify the development environment
|
||||
|
||||
You can override the default services from a `docker-compose.override.yml`
|
||||
file, and make use of those overrides by changing `LocalSettings.php`.
|
||||
|
||||
Example overrides and configurations can be found under
|
||||
[MediaWiki-Docker on mediawiki.org][mw-docker].
|
||||
|
||||
After updating `docker-compose.override.yml`, run `docker compose down`
|
||||
followed by `docker compose up -d` for changes to take effect.
|
||||
|
||||
### Install extra packages
|
||||
|
||||
If you need root on the container to install system packages with `apt-get` for
|
||||
troubleshooting, you can open a shell as root with
|
||||
`docker compose exec --user root mediawiki bash`.
|
||||
|
||||
### Install extensions and skins
|
||||
|
||||
To install an extension or skin, follow the instructions of the mediawiki.org
|
||||
page for the extension or skin in question, and look for any dependencies
|
||||
or additional steps that may be needed.
|
||||
|
||||
For most extensions, only two steps are needed: download the code to the
|
||||
right directory, and then enable the component from `LocalSettings.php`.
|
||||
|
||||
To install the Vector skin:
|
||||
|
||||
1. Clone the skin:
|
||||
```sh
|
||||
cd skins/
|
||||
git clone https://gerrit.wikimedia.org/r/mediawiki/skins/Vector
|
||||
```
|
||||
|
||||
2. Enable the skin, by adding the following to `LocalSettings.php`:
|
||||
```php
|
||||
wfLoadSkin( 'Vector' );
|
||||
```
|
||||
|
||||
To install the EventLogging extension:
|
||||
|
||||
1. Clone the extension repository:
|
||||
|
||||
```sh
|
||||
cd extensions/
|
||||
git clone https://gerrit.wikimedia.org/r/mediawiki/extensions/EventLogging
|
||||
```
|
||||
|
||||
Alternatively, if you have extension repositories elsewhere on disk, mount each one as an overlapping volume in
|
||||
`docker-compose.override.yml`. This is comparable to a symlink, but those are not well-supported in Docker.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
mediawiki:
|
||||
volumes:
|
||||
- ~/Code/EventLogging:/var/www/html/w/extensions/EventLogging:cached
|
||||
```
|
||||
|
||||
2. Enable the extension, by adding the following to `LocalSettings.php`:
|
||||
```php
|
||||
wfLoadExtension( 'EventLogging' );
|
||||
```
|
||||
|
||||
### Xdebug
|
||||
|
||||
By default, you will need to set `XDEBUG_TRIGGER=1` in the GET/POST, or as an
|
||||
environment variable, to turn on Xdebug for a request.
|
||||
|
||||
You can also install a browser extension for controlling whether Xdebug is
|
||||
active. See the [official Xdebug Step Debugging][step-debug], particularly the
|
||||
"Activating Step Debugging" section, for more details.
|
||||
|
||||
[step-debug]: https://xdebug.org/docs/step_debug
|
||||
|
||||
If you wish to run Xdebug on every request, you can set
|
||||
`start_with_request=yes` in `XDEBUG_CONFIG` in your .env file:
|
||||
|
||||
```
|
||||
XDEBUG_CONFIG=start_with_request=yes
|
||||
```
|
||||
|
||||
You can pass any of Xdebug's configuration values in this variable. For example:
|
||||
|
||||
```
|
||||
XDEBUG_CONFIG=client_host=192.168.42.34 client_port=9000 log=/tmp/xdebug.log
|
||||
```
|
||||
|
||||
This shouldn't be necessary for basic use cases, but see [the Xdebug settings
|
||||
documentation](https://xdebug.org/docs/all_settings) for available settings.
|
||||
|
||||
### Codex
|
||||
|
||||
You can use your local version of Codex instead of the one bundled with MediaWiki. This is useful
|
||||
when testing how changes in Codex affect Codex-based features in MediaWiki.
|
||||
|
||||
1. Clone the Codex repository and build Codex, if you haven't done this already:
|
||||
```sh
|
||||
cd ../
|
||||
git clone https://gerrit.wikimedia.org/r/design/codex
|
||||
cd codex
|
||||
npm run build-all
|
||||
```
|
||||
2. If your clone of the Codex repository is outside of the MediaWiki directory (this is common),
|
||||
add the following to your `docker-compose.override.yml`. Replace `~/git/codex` with the path to
|
||||
your Codex clone.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
mediawiki:
|
||||
volumes:
|
||||
- ~/git/codex:/var/www/html/w/codex:cached
|
||||
```
|
||||
3. To apply the change to `docker-compose.override.yml`, you have to recreate the environment:
|
||||
```sh
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
4. Enable Codex development mode by adding the following to the bottom of `LocalSettings.php`:
|
||||
|
||||
```php
|
||||
$wgCodexDevelopmentDir = MW_INSTALL_PATH . '/codex';
|
||||
```
|
||||
|
||||
To disable Codex development mode and use the regular version of Codex, delete or comment out
|
||||
this line.
|
||||
5. Every time you make a change to your local copy of Codex (or download a Gerrit change), you
|
||||
have to rerun Codex's build process for these changes to take effect. To do this, run
|
||||
`npm run build-all` in the Codex directory.
|
||||
|
||||
### Stop or recreate environment
|
||||
|
||||
Stop the environment, perhaps to reduce the load when working on something
|
||||
else. This preserves the containers, to be restarted later quickly with
|
||||
the `docker compose up -d` command.
|
||||
|
||||
```sh
|
||||
docker compose stop
|
||||
```
|
||||
|
||||
Destroy and re-create the environment. This will delete the containers,
|
||||
including any logs, caches, and other modifications you may have made
|
||||
via the shell.
|
||||
|
||||
```sh
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Re-install the database
|
||||
|
||||
To empty the wiki database and re-install it:
|
||||
|
||||
* Remove or rename the `LocalSettings.php` file.
|
||||
* Delete the `cache/sqlite` directory.
|
||||
* Re-run the "Install MediaWiki database" command.
|
||||
|
||||
You can now restore or copy over any modifications you had in your previous `LocalSettings.php` file.
|
||||
And if you have any additional extensions installed that required a database table, then also run:
|
||||
`docker compose exec mediawiki php maintenance/run.php update`.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Caching
|
||||
|
||||
If you suspect a change is not applying due to caching, start by [hard
|
||||
refreshing](https://en.wikipedia.org/wiki/Wikipedia:Bypass_your_cache) the browser.
|
||||
|
||||
If that doesn't work, you can narrow it down by disabling various server-side
|
||||
caching layers in `LocalSettings.php`, as follows:
|
||||
|
||||
```php
|
||||
$wgMainCacheType = CACHE_NONE;
|
||||
$wgMessageCacheType = CACHE_NONE;
|
||||
$wgParserCacheType = CACHE_NONE;
|
||||
$wgResourceLoaderMaxage = [
|
||||
'versioned' => 0,
|
||||
'unversioned' => 0
|
||||
];
|
||||
```
|
||||
|
||||
The default settings of MediaWiki are such that caching is smart and changes
|
||||
propagate immediately. Using the above settings may slow down your wiki
|
||||
significantly. Especially on macOS and Windows, where Docker Desktop uses
|
||||
a VM internally and thus has longer file access times.
|
||||
|
||||
See [Manual:Caching][manual-caching] on mediawiki.org for more information.
|
||||
|
||||
[manual-caching]: https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Caching
|
||||
|
||||
### Xdebug ports
|
||||
|
||||
Older versions of Xdebug used port 9000, which could conflict with php-fpm
|
||||
running on the host. This document used to recommend a workaround of telling
|
||||
your IDE to listen on a different port (e.g., 9009) and setting
|
||||
`XDEBUG_CONFIG=remote_port=9009` in your `.env`.
|
||||
|
||||
Xdebug 3.x now uses the `client_port` value, which defaults to 9003. This
|
||||
should no longer conflict with local php-fpm installations, but you may need
|
||||
to change the settings in your IDE or debugger.
|
||||
|
||||
### Linux desktop, host not found
|
||||
|
||||
The image uses `host.docker.internal` as the `client_host` value which
|
||||
should allow Xdebug work for Docker for Mac/Windows.
|
||||
|
||||
On Linux, you need to create a `docker-compose.override.yml` file with the following
|
||||
contents:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
mediawiki:
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
```
|
||||
|
||||
With the latest version of Docker on Linux hosts, this _should_ work
|
||||
transparently as long as you're using the recommended
|
||||
`docker-compose.override.yml`. If it doesn't, first check `docker version` to
|
||||
make sure you're running Docker 20.10.2 or above, and `docker compose version`
|
||||
to make sure it's 1.27.4 or above.
|
||||
|
||||
If Xdebug still doesn't work, try specifying the hostname or IP address of your
|
||||
host. The IP address works more reliably. You can obtain it by running e.g.
|
||||
`ip -4 addr show docker0` and copying the IP address into the config in `.env`,
|
||||
like `XDEBUG_CONFIG=remote_host=172.17.0.1`
|
||||
|
||||
### Generating logs
|
||||
|
||||
Switching on the remote log for Xdebug comes at a performance cost so only
|
||||
use it while troubleshooting. You can enable it like so: `XDEBUG_CONFIG=remote_log=/tmp/xdebug.log`
|
||||
|
||||
### "(Permission Denied)" errors on running docker compose
|
||||
|
||||
See if you're able to run any docker commands to start with. Try running
|
||||
`docker container ls`, which should also throw a permission error. If not,
|
||||
go through the following steps to get access to the socket that the docker
|
||||
client uses to talk to the daemon.
|
||||
|
||||
`sudo usermod -aG docker $USER`
|
||||
|
||||
And then `relogin` (or `newgrp docker`) to re-login with the new group membership.
|
||||
|
||||
### "(Cannot access the database: Unknown error (localhost))"
|
||||
|
||||
The environment's working directory has recently changed to `/var/www/html/w`.
|
||||
Reconfigure this in your `LocalSettings.php` by ensuring that the following
|
||||
values are set correctly:
|
||||
|
||||
```php
|
||||
$wgScriptPath = '/w';
|
||||
$wgSQLiteDataDir = "/var/www/html/w/cache/sqlite";
|
||||
```
|
||||
|
||||
### Windows users, "(Cannot access the database: No database connection (unknown))"
|
||||
|
||||
The permissions with the `cache/sqlite` directory have to be set manually on Windows:
|
||||
|
||||
```sh
|
||||
docker compose exec mediawiki chmod -R o+rwx cache/sqlite
|
||||
```
|
||||
|
||||
### Linux users, "(Cannot access the database: No database connection (localhost))"
|
||||
|
||||
Make sure you have the `MW_DOCKER_UID` and `MW_DOCKER_GID` set in your `.env` file (instructions above).
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
The MediaWiki FAQ can be found at:
|
||||
https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
'use strict';
|
||||
module.exports = function ( grunt ) {
|
||||
grunt.loadNpmTasks( 'grunt-banana-checker' );
|
||||
grunt.loadNpmTasks( 'grunt-eslint' );
|
||||
grunt.loadNpmTasks( 'grunt-karma' );
|
||||
grunt.loadNpmTasks( 'grunt-stylelint' );
|
||||
|
||||
const fs = require( 'fs' );
|
||||
const wgServer = process.env.MW_SERVER;
|
||||
const wgScriptPath = process.env.MW_SCRIPT_PATH;
|
||||
const karmaProxy = {};
|
||||
|
||||
let qunitURL = wgServer + wgScriptPath + '/index.php?title=Special:JavaScriptTest/qunit/export';
|
||||
|
||||
// "MediaWiki" for core, or extension/skin name (e.g. "GrowthExperiments")
|
||||
const qunitComponent = grunt.option( 'qunit-component' );
|
||||
const qunitWatch = grunt.option( 'qunit-watch' ) || false;
|
||||
const qunitWatchFiles = [];
|
||||
if ( qunitComponent ) {
|
||||
qunitURL = qunitURL + '&component=' + qunitComponent;
|
||||
}
|
||||
if ( qunitWatch ) {
|
||||
if ( !qunitComponent || qunitComponent === 'MediaWiki' ) {
|
||||
// MediaWiki core
|
||||
qunitWatchFiles.push( 'tests/qunit/**' );
|
||||
qunitWatchFiles.push( 'resources/**' );
|
||||
} else {
|
||||
// one extension or skin
|
||||
const extPath = __dirname + '/extensions/' + qunitComponent + '/extension.json';
|
||||
const skinPath = __dirname + '/skins/' + qunitComponent + '/skin.json';
|
||||
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
||||
if ( fs.existsSync( extPath ) ) {
|
||||
qunitWatchFiles.push( 'extensions/' + qunitComponent + '/extension.json' );
|
||||
qunitWatchFiles.push( 'extensions/' + qunitComponent + '/{modules,resources,tests}/**' );
|
||||
}
|
||||
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
||||
if ( fs.existsSync( skinPath ) ) {
|
||||
qunitWatchFiles.push( 'skins/' + qunitComponent + '/skin.json' );
|
||||
qunitWatchFiles.push( 'skins/' + qunitComponent + '/{modules,resources,tests}/**' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
karmaProxy[ wgScriptPath ] = {
|
||||
target: wgServer + wgScriptPath,
|
||||
changeOrigin: true
|
||||
};
|
||||
|
||||
grunt.initConfig( {
|
||||
eslint: {
|
||||
options: {
|
||||
extensions: [ '.js', '.json', '.vue' ],
|
||||
cache: true,
|
||||
fix: grunt.option( 'fix' )
|
||||
},
|
||||
all: '.'
|
||||
},
|
||||
banana: {
|
||||
options: {
|
||||
requireLowerCase: false,
|
||||
disallowBlankTranslations: false
|
||||
},
|
||||
core: 'languages/i18n/',
|
||||
codex: 'languages/i18n/codex/',
|
||||
exif: 'languages/i18n/exif/',
|
||||
preferences: 'languages/i18n/preferences/',
|
||||
api: 'includes/api/i18n/',
|
||||
rest: 'includes/Rest/i18n/',
|
||||
installer: 'includes/installer/i18n/',
|
||||
paramvalidator: 'includes/libs/ParamValidator/i18n/'
|
||||
},
|
||||
stylelint: {
|
||||
options: {
|
||||
reportNeedlessDisables: true,
|
||||
cache: true
|
||||
},
|
||||
resources: 'resources/src/**/*.{css,less,vue}',
|
||||
config: 'mw-config/**/*.css'
|
||||
},
|
||||
watch: {
|
||||
files: [
|
||||
'.{stylelintrc,eslintrc}.json',
|
||||
'**/*',
|
||||
'!{extensions,node_modules,skins,vendor}/**'
|
||||
],
|
||||
tasks: 'test'
|
||||
},
|
||||
karma: {
|
||||
options: {
|
||||
plugins: [
|
||||
'@wikimedia/karma-firefox-launcher',
|
||||
'karma-*'
|
||||
],
|
||||
customLaunchers: {
|
||||
ChromeCustom: {
|
||||
base: 'ChromeHeadless',
|
||||
// Chrome requires --no-sandbox in Docker/CI.
|
||||
// WMF CI images expose CHROMIUM_FLAGS which sets that.
|
||||
flags: process.env.CHROMIUM_FLAGS ? ( process.env.CHROMIUM_FLAGS || '' ).split( ' ' ) : []
|
||||
}
|
||||
},
|
||||
proxies: karmaProxy,
|
||||
files: [ {
|
||||
pattern: qunitURL,
|
||||
type: 'js',
|
||||
watched: false,
|
||||
included: true,
|
||||
served: false
|
||||
}, ...qunitWatchFiles.map( ( file ) => ( {
|
||||
pattern: file,
|
||||
type: 'js',
|
||||
watched: true,
|
||||
included: false,
|
||||
served: false
|
||||
} ) ) ],
|
||||
logLevel: ( process.env.ZUUL_PROJECT ? 'DEBUG' : 'INFO' ),
|
||||
frameworks: [ 'qunit' ],
|
||||
// Disable autostart because we load modules asynchronously.
|
||||
client: {
|
||||
qunit: {
|
||||
autostart: false
|
||||
}
|
||||
},
|
||||
reporters: [ 'mocha' ],
|
||||
singleRun: !qunitWatch,
|
||||
autoWatch: qunitWatch,
|
||||
// Some tests in extensions don't yield for more than the default 10s (T89075)
|
||||
browserNoActivityTimeout: 60 * 1000,
|
||||
// Karma requires Same-Origin (or CORS) by default since v1.1.1
|
||||
// for better stacktraces. But we load the first request from wgServer
|
||||
crossOriginAttribute: false
|
||||
},
|
||||
main: {
|
||||
browsers: [ 'FirefoxHeadless' ]
|
||||
},
|
||||
firefox: {
|
||||
browsers: [ 'FirefoxHeadless' ]
|
||||
},
|
||||
chrome: {
|
||||
browsers: [ 'ChromeCustom' ]
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
grunt.registerTask( 'assert-mw-env', () => {
|
||||
let ok = true;
|
||||
if ( !process.env.MW_SERVER ) {
|
||||
grunt.log.error( 'Environment variable MW_SERVER must be set.\n' +
|
||||
'Set this like $wgServer, e.g. "http://localhost"'
|
||||
);
|
||||
ok = false;
|
||||
}
|
||||
// MW_SCRIPT_PATH= empty string is valid, e.g. for docroot installs
|
||||
// This includes "composer serve" (Quickstart)
|
||||
if ( process.env.MW_SCRIPT_PATH === undefined ) {
|
||||
grunt.log.error( 'Environment variable MW_SCRIPT_PATH must be set.\n' +
|
||||
'Set this like $wgScriptPath, e.g. "/w"' );
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
} );
|
||||
|
||||
grunt.registerTask( 'lint', [ 'eslint', 'banana', 'stylelint' ] );
|
||||
grunt.registerTask( 'qunit', [ 'assert-mw-env', 'karma:firefox' ] );
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,103 @@
|
|||
---
|
||||
Installing MediaWiki
|
||||
---
|
||||
|
||||
It is possible to install and configure the wiki "in-place", as long as you have
|
||||
the necessary prerequisites available.
|
||||
|
||||
Required software as of MediaWiki 1.43.0:
|
||||
|
||||
* Web server with PHP 8.1.0 or higher, plus the following extensions:
|
||||
** ctype
|
||||
** dom
|
||||
** fileinfo
|
||||
** iconv
|
||||
** intl
|
||||
** json
|
||||
** libxml
|
||||
** mbstring
|
||||
** openssl
|
||||
** xml
|
||||
** xmlreader
|
||||
* A SQL server, the following types are supported
|
||||
** MariaDB 10.3 or higher
|
||||
** MySQL 5.7.0 or higher
|
||||
** PostgreSQL 10 or higher
|
||||
** SQLite 3.8.0 or higher
|
||||
|
||||
In addition, either the bcmath or gmp PHP extension is required on 32-bit
|
||||
systems.
|
||||
|
||||
MediaWiki is developed and tested mainly on Unix/Linux platforms, but should
|
||||
work on Windows as well.
|
||||
|
||||
Support for specialised content requires installing the relevant extension. For
|
||||
formulæ, see https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:Math
|
||||
|
||||
Don't forget to check the RELEASE-NOTES file...
|
||||
|
||||
|
||||
Additional documentation is available online, which may include more detailed
|
||||
notes on particular operating systems and workarounds for difficult hosting
|
||||
environments:
|
||||
|
||||
https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Installing_MediaWiki
|
||||
|
||||
|
||||
******************* WARNING *******************
|
||||
|
||||
REMEMBER: ALWAYS BACK UP YOUR DATABASE BEFORE
|
||||
ATTEMPTING TO INSTALL OR UPGRADE!!!
|
||||
|
||||
******************* WARNING *******************
|
||||
|
||||
----
|
||||
In-place Web install
|
||||
----
|
||||
|
||||
Decompress the MediaWiki installation archive either on your server, or on your
|
||||
local machine and upload the directory tree. Rename it from "mediawiki-1.x.x" to
|
||||
something nice, like "wiki", since it will be appearing in your URL,
|
||||
ie. /wiki/index.php/Article.
|
||||
|
||||
+--------------------------------------------------------------------------+
|
||||
| Note: If you plan to use a fancy URL-rewriting scheme to prettify your |
|
||||
| URLs, such as http://www.example.com/wiki/Article, you should put the |
|
||||
| files in a *different* directory from the virtual path where page names |
|
||||
| will appear. It is common in this case to use w as the folder name and |
|
||||
| /wiki/ as the virtual article path where your articles pretend to be. |
|
||||
| |
|
||||
| See: https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Short_URL |
|
||||
+--------------------------------------------------------------------------+
|
||||
|
||||
Hop into your browser and surf into the wiki directory. It'll direct you into
|
||||
the config script. Fill out the form... remember you're probably not on an
|
||||
encrypted connection.
|
||||
Gaaah! :)
|
||||
|
||||
If all goes well, you should soon be told that it's set up your wiki database
|
||||
and generated a configuration file. There is now a copy of "LocalSettings.php"
|
||||
available to download from the installer. Download this now, there is not a
|
||||
way (yet) to get it after you exit the installer. Place it in the main wiki
|
||||
directory, and the wiki should now be working.
|
||||
|
||||
Once the wiki is set up, you should remove the mw-config directory (though it
|
||||
will refuse to config again if the wiki is set up).
|
||||
|
||||
----
|
||||
|
||||
Don't forget that this is free software under development! Chances are good
|
||||
there's a crucial step that hasn't made it into the documentation. You should
|
||||
probably sign up for the MediaWiki developers' mailing list; you can ask for
|
||||
help (please provide enough information to work with, and preferably be aware of
|
||||
what you're doing!) and keep track of major changes to the software, including
|
||||
performance improvements and security patches.
|
||||
|
||||
https://lists.wikimedia.org/postorius/lists/mediawiki-announce.lists.wikimedia.org/
|
||||
(low traffic)
|
||||
|
||||
https://lists.wikimedia.org/postorius/lists/mediawiki-l.lists.wikimedia.org/
|
||||
(site admin support)
|
||||
|
||||
https://lists.wikimedia.org/postorius/lists/wikitech-l.lists.wikimedia.org/
|
||||
(development)
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# MediaWiki
|
||||
|
||||
MediaWiki is a free and open-source wiki software package written in PHP. It
|
||||
serves as the platform for Wikipedia and the other Wikimedia projects, used
|
||||
by hundreds of millions of people each month. MediaWiki is localised in over
|
||||
350 languages and its reliability and robust feature set have earned it a large
|
||||
and vibrant community of third-party users and developers.
|
||||
|
||||
MediaWiki is:
|
||||
|
||||
* feature-rich and extensible, both on-wiki and with hundreds of extensions;
|
||||
* scalable and suitable for both small and large sites;
|
||||
* simple to install, working on most hardware/software combinations; and
|
||||
* available in your language.
|
||||
|
||||
For system requirements, installation, and upgrade details, see the files
|
||||
RELEASE-NOTES, INSTALL, and UPGRADE.
|
||||
|
||||
* Ready to get started?
|
||||
* https://www.mediawiki.org/wiki/Special:MyLanguage/Download
|
||||
* Setting up your local development environment?
|
||||
* https://www.mediawiki.org/wiki/Local_development_quickstart
|
||||
* Looking for the technical manual?
|
||||
* https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents
|
||||
* Seeking help from a person?
|
||||
* https://www.mediawiki.org/wiki/Special:MyLanguage/Communication
|
||||
* Looking to file a bug report or a feature request?
|
||||
* https://bugs.mediawiki.org/
|
||||
* Interested in helping out?
|
||||
* https://www.mediawiki.org/wiki/Special:MyLanguage/How_to_contribute
|
||||
|
||||
MediaWiki is the result of global collaboration and cooperation. The CREDITS
|
||||
file lists technical contributors to the project. The COPYING file explains
|
||||
MediaWiki's copyright and license (GNU General Public License, version 2 or
|
||||
later). Many thanks to the Wikimedia community for testing and suggestions.
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,3 @@
|
|||
MediaWiki takes security very seriously. If you believe you have found a
|
||||
security issue, see <https://www.mediawiki.org/wiki/Reporting_security_bugs>
|
||||
for information on how to responsibly report it.
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
This file provides an overview of the MediaWiki upgrade process. For help with
|
||||
specific problems, you should check:
|
||||
|
||||
* the docs at https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents ;
|
||||
* the mediawiki-l mailing list archive at
|
||||
https://lists.wikimedia.org/hyperkitty/list/mediawiki-l@lists.wikimedia.org/ ;
|
||||
and
|
||||
* the bug tracker at https://phabricator.wikimedia.org/
|
||||
|
||||
… for information and workarounds to common issues.
|
||||
|
||||
== Overview ==
|
||||
|
||||
We provide comprehensive documentation on upgrading to the latest version of the
|
||||
software at https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Upgrading.
|
||||
|
||||
Important: Upgrading from releases older than two LTS release is not supported anymore.
|
||||
If you want to upgrade from an old version, please upgrade to a more recent LTS version first,
|
||||
then to this version.
|
||||
|
||||
Currently any upgrade from any version older than 1.35 will fail.
|
||||
|
||||
=== Consult the release notes ===
|
||||
|
||||
Before doing anything, stop and consult the release notes supplied with the new
|
||||
version of the software. These detail bug fixes, new features and functionality,
|
||||
and any particular points that may need to be noted during the upgrade process.
|
||||
|
||||
=== Backup first ===
|
||||
|
||||
It is imperative that, prior to attempting an upgrade of the database schema,
|
||||
you take a complete backup of your wiki database and files and verify it. While
|
||||
the upgrade scripts are somewhat robust, there is no guarantee that things will
|
||||
not fail, leaving the database in an inconsistent state.
|
||||
|
||||
https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Backing_up_a_wiki is an
|
||||
overview of the backup process. You should also refer to the documentation for
|
||||
your database management system for information on backing up a database, and to
|
||||
your operating system documentation for information on making copies of files.
|
||||
|
||||
=== Perform the file upgrade ===
|
||||
|
||||
Download the files for the new version of the software. These are available as a
|
||||
compressed "tar" archive from the Wikimedia Download Service
|
||||
(https://releases.wikimedia.org/mediawiki/).
|
||||
|
||||
You can also obtain the new files directly from our Git source code repository.
|
||||
|
||||
Replace the existing MediaWiki files with the new. You should preserve the
|
||||
LocalSettings.php file and the "extensions" and "images" directories.
|
||||
|
||||
Depending upon your configuration, you may also need to preserve additional
|
||||
directories, including a custom upload directory ($wgUploadDirectory),
|
||||
deleted file archives, and any custom skins.
|
||||
|
||||
=== Perform the database upgrade ===
|
||||
|
||||
As of 1.21, it is possible to separate schema changes (i.e. adding, dropping, or
|
||||
changing tables, fields, or indices) from all other database changes (e.g.
|
||||
populating fields). If you need this capability, see "From the command line"
|
||||
below.
|
||||
|
||||
==== From the Web ====
|
||||
|
||||
If you browse to the Web-based installation script (usually at
|
||||
./mw-config/index.php) from your wiki installation you can follow the script and
|
||||
upgrade your database in place.
|
||||
|
||||
==== From the command line ====
|
||||
|
||||
From the command line, browse to the "maintenance" directory and use
|
||||
`run.php update` to check and update the schema. This will insert missing
|
||||
tables, update existing tables, and move data around as needed. In most cases,
|
||||
this is successful and nothing further needs to be done.
|
||||
|
||||
If you need to separate out the schema changes so they can be run by someone
|
||||
with more privileges, then you can use the --schema option to produce a text
|
||||
file with the necessary commands. You can use --schema, --noschema,
|
||||
$wgAllowSchemaUpdates as well as proper database permissions to enforce this
|
||||
separation.
|
||||
|
||||
=== Check configuration settings ===
|
||||
|
||||
The names of configuration variables, and their default values and purposes, can
|
||||
change between release branches, e.g. $wgDisableUploads in 1.4 is replaced with
|
||||
$wgEnableUploads in later versions. When upgrading, consult the release notes to
|
||||
check for configuration changes which would alter the expected behavior of
|
||||
MediaWiki.
|
||||
|
||||
=== Check installed extensions ===
|
||||
|
||||
Extensions usually need to be upgraded at the same time as the MediaWiki core.
|
||||
|
||||
=== Test ===
|
||||
|
||||
It makes sense to test your wiki immediately following any kind of maintenance
|
||||
procedure, and especially after upgrading; check that page views and edits work
|
||||
normally, that special pages continue to function, etc., and correct any errors
|
||||
and quirks which reveal themselves.
|
||||
|
||||
You should also test any extensions, and upgrade these if necessary.
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
/**
|
||||
* The web entry point for all %Action API queries, handled by ApiMain
|
||||
* and ApiBase subclasses.
|
||||
*
|
||||
* @see ApiEntryPoint The corresponding entry point class
|
||||
*
|
||||
* 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 entrypoint
|
||||
* @ingroup API
|
||||
*/
|
||||
|
||||
use MediaWiki\Api\ApiEntryPoint;
|
||||
use MediaWiki\Context\RequestContext;
|
||||
use MediaWiki\EntryPointEnvironment;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
// So extensions (and other code) can check whether they're running in API mode
|
||||
define( 'MW_API', true );
|
||||
define( 'MW_ENTRY_POINT', 'api' );
|
||||
|
||||
require __DIR__ . '/includes/WebStart.php';
|
||||
|
||||
// Construct entry point object and call doRun() to handle the request.
|
||||
( new ApiEntryPoint(
|
||||
RequestContext::getMain(),
|
||||
new EntryPointEnvironment(),
|
||||
MediaWikiServices::getInstance()
|
||||
) )->run();
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,227 @@
|
|||
{
|
||||
"name": "mediawiki/core",
|
||||
"description": "Free software wiki application developed by the Wikimedia Foundation and others",
|
||||
"type": "mediawiki-core",
|
||||
"keywords": [
|
||||
"mediawiki",
|
||||
"wiki"
|
||||
],
|
||||
"homepage": "https://www.mediawiki.org/",
|
||||
"authors": [
|
||||
{
|
||||
"name": "MediaWiki Community",
|
||||
"homepage": "https://www.mediawiki.org/wiki/Special:Version/Credits"
|
||||
}
|
||||
],
|
||||
"license": "GPL-2.0-or-later",
|
||||
"support": {
|
||||
"issues": "https://phabricator.wikimedia.org/",
|
||||
"irc": "irc://irc.libera.chat/mediawiki",
|
||||
"wiki": "https://www.mediawiki.org/"
|
||||
},
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"composer/semver": "3.4.3",
|
||||
"ext-calendar": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-fileinfo": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-intl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-xmlreader": "*",
|
||||
"guzzlehttp/guzzle": "7.10.0",
|
||||
"justinrainbow/json-schema": "5.3.1",
|
||||
"liuggio/statsd-php-client": "1.0.18",
|
||||
"mck89/peast": "1.17.4",
|
||||
"monolog/monolog": "2.9.3",
|
||||
"oojs/oojs-ui": "0.51.2",
|
||||
"pear/mail": "2.0.0",
|
||||
"pear/mail_mime": "1.10.12",
|
||||
"pear/net_smtp": "1.12.1",
|
||||
"php": ">=8.1.0",
|
||||
"psr/container": "1.1.2",
|
||||
"psr/http-message": "1.1",
|
||||
"psr/log": "1.1.4",
|
||||
"ralouphie/getallheaders": "3.0.3",
|
||||
"symfony/polyfill-php82": "1.37.0",
|
||||
"symfony/polyfill-php83": "1.37.0",
|
||||
"symfony/polyfill-php84": "1.37.0",
|
||||
"symfony/polyfill-php85": "1.37.0",
|
||||
"symfony/yaml": "5.4.52",
|
||||
"wikimedia/assert": "0.5.1",
|
||||
"wikimedia/at-ease": "3.0.0",
|
||||
"wikimedia/base-convert": "2.0.2",
|
||||
"wikimedia/bcp-47-code": "2.0.0",
|
||||
"wikimedia/cdb": "3.0.0",
|
||||
"wikimedia/cldr-plural-rule-parser": "3.0.0",
|
||||
"wikimedia/common-passwords": "0.5.0",
|
||||
"wikimedia/composer-merge-plugin": "2.1.0",
|
||||
"wikimedia/css-sanitizer": "6.2.1",
|
||||
"wikimedia/cssjanus": "2.3.0",
|
||||
"wikimedia/html-formatter": "4.1.0",
|
||||
"wikimedia/ip-utils": "5.0.0",
|
||||
"wikimedia/json-codec": "4.0.0",
|
||||
"wikimedia/less.php": "5.5.0",
|
||||
"wikimedia/minify": "2.9.0",
|
||||
"wikimedia/normalized-exception": "2.0.0",
|
||||
"wikimedia/object-factory": "5.0.1",
|
||||
"wikimedia/parsoid": "0.20.8",
|
||||
"wikimedia/php-session-serializer": "3.0.0",
|
||||
"wikimedia/purtle": "2.0.0",
|
||||
"wikimedia/relpath": "4.0.1",
|
||||
"wikimedia/remex-html": "4.1.2",
|
||||
"wikimedia/request-timeout": "2.0.0",
|
||||
"wikimedia/running-stat": "2.1.0",
|
||||
"wikimedia/scoped-callback": "5.0.0",
|
||||
"wikimedia/services": "4.0.0",
|
||||
"wikimedia/shellbox": "4.1.1",
|
||||
"wikimedia/utfnormal": "4.0.0",
|
||||
"wikimedia/timestamp": "4.1.1",
|
||||
"wikimedia/wait-condition-loop": "2.0.2",
|
||||
"wikimedia/wrappedstring": "4.0.1",
|
||||
"wikimedia/xmp-reader": "0.10.2",
|
||||
"zordius/lightncandy": "1.2.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"composer/spdx-licenses": "1.5.8",
|
||||
"doctrine/dbal": "3.8.4",
|
||||
"doctrine/sql-formatter": "1.1.3",
|
||||
"ext-simplexml": "*",
|
||||
"giorgiosironi/eris": "^0.14.0",
|
||||
"hamcrest/hamcrest-php": "^2.0",
|
||||
"johnkary/phpunit-speedtrap": "^4.0",
|
||||
"mediawiki/mediawiki-codesniffer": "45.0.0",
|
||||
"mediawiki/mediawiki-phan-config": "0.14.0",
|
||||
"mediawiki/minus-x": "1.1.3",
|
||||
"nikic/php-parser": "^5.5.0",
|
||||
"php-parallel-lint/php-console-highlighter": "1.0.0",
|
||||
"php-parallel-lint/php-parallel-lint": "1.4.0",
|
||||
"phpunit/phpunit": "9.6.34",
|
||||
"psy/psysh": "^0.12.19",
|
||||
"seld/jsonlint": "1.10.2",
|
||||
"wikimedia/alea": "1.0.0",
|
||||
"wikimedia/langconv": "^0.4.2",
|
||||
"wikimedia/testing-access-wrapper": "^3.0.0 || ^4.0.0",
|
||||
"wmde/hamcrest-html-matchers": "^1.0.0"
|
||||
},
|
||||
"replace": {
|
||||
"symfony/polyfill-ctype": "1.99",
|
||||
"symfony/polyfill-intl-grapheme": "1.17.1",
|
||||
"symfony/polyfill-intl-normalizer": "1.17.1",
|
||||
"symfony/polyfill-mbstring": "1.99",
|
||||
"symfony/polyfill-php80": "1.99",
|
||||
"symfony/polyfill-php81": "1.99"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-apcu": "Faster web responses overall.",
|
||||
"ext-bcmath": "Increased performance of some operations. Required especially on 32 bit machines. This or ext-gmp are needed for scrambling Temporary Accounts.",
|
||||
"ext-curl": "Faster HTTP services, e.g. when using InstantCommons, Swift, or Etcd.",
|
||||
"ext-exif": "Enable processing of EXIF information in file uploads.",
|
||||
"ext-gd": "Enable thumbnails for file uploads.",
|
||||
"ext-gmp": "Increased performance of some operations. Required especially on 32 bit machines. This or ext-bcmath are needed for scrambling Temporary Accounts.",
|
||||
"ext-igbinary": "Enables use of igbinary for serialisation.",
|
||||
"ext-imagick": "Enables use of imagemagick for image manipulation.",
|
||||
"ext-memcached": "Enables use of Memcached for caching purposes.",
|
||||
"ext-mysqli": "Enable the MySQL and MariaDB database type for MediaWiki.",
|
||||
"ext-pdo": "Enable the SQLite database type for MediaWiki.",
|
||||
"ext-pgsql": "Enable the PostgreSQL database type for MediaWiki.",
|
||||
"ext-posix": "Enable CLI concurrent processing, e.g. for runJobs.php.",
|
||||
"ext-pcntl": "Enable CLI concurrent processing, e.g. for runJobs.php and rebuildLocalisationCache.php.",
|
||||
"ext-readline": "Enable CLI history and autocomplete, e.g. for eval.php and other REPLs.",
|
||||
"ext-redis": "Enables use of Redis for caching purposes.",
|
||||
"ext-sockets": "Enable CLI concurrent processing, e.g. for rebuildLocalisationCache.php.",
|
||||
"ext-wikidiff2": "Faster text difference engine.",
|
||||
"ext-zlib": "Enable use of GZIP compression, e.g. for SqlBagOStuff (ParserCache), $wgCompressRevisions, or $wgUseFileCache."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MediaWiki\\Composer\\": "includes/composer"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"files": [
|
||||
"vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest.php",
|
||||
"vendor/wmde/hamcrest-html-matchers/src/functions.php"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"mw-install:sqlite": "@php maintenance/run.php install --server=http://localhost:4000 --dbtype sqlite --with-developmentsettings --dbpath cache/ --scriptpath= --pass adminpassword MediaWiki Admin",
|
||||
"serve": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"@putenv MW_LOG_DIR=logs",
|
||||
"@putenv MW_LOG_STDERR=1",
|
||||
"@putenv PHP_CLI_SERVER_WORKERS=8",
|
||||
"@php -S 127.0.0.1:4000"
|
||||
],
|
||||
"lint": "parallel-lint --exclude node_modules --exclude vendor",
|
||||
"phan": "phan -d . --long-progress-bar",
|
||||
"phpcs": "phpcs -p -s --cache",
|
||||
"fix": [
|
||||
"minus-x fix .",
|
||||
"phpcbf"
|
||||
],
|
||||
"pre-install-cmd": "MediaWiki\\Composer\\VersionChecker::onEvent",
|
||||
"pre-update-cmd": "MediaWiki\\Composer\\VersionChecker::onEvent",
|
||||
"post-install-cmd": "MediaWiki\\Composer\\ComposerVendorHtaccessCreator::onEvent",
|
||||
"post-update-cmd": "MediaWiki\\Composer\\ComposerVendorHtaccessCreator::onEvent",
|
||||
"releasenotes": "@phpunit --group ReleaseNotes",
|
||||
"test": [
|
||||
"@lint .",
|
||||
"@phpcs .",
|
||||
"minus-x check ."
|
||||
],
|
||||
"test-some": [
|
||||
"@lint",
|
||||
"@phpcs"
|
||||
],
|
||||
"phpunit": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"phpunit"
|
||||
],
|
||||
"phpunit:unit": "@phpunit --colors=always --testsuite=core:unit,extensions:unit,skins:unit",
|
||||
"phpunit:integration": "@phpunit --colors=always --testsuite=core:integration,extensions:integration,skins:integration",
|
||||
"phpunit:coverage": "@phpunit --testsuite=core:unit --exclude-group Dump,Broken",
|
||||
"phpunit:coverage-edit": "MediaWiki\\Composer\\ComposerPhpunitXmlCoverageEdit::onEvent",
|
||||
"phpunit:entrypoint": "@phpunit",
|
||||
"phpunit:prepare-parallel:extensions": [
|
||||
"MediaWiki\\Composer\\PhpUnitSplitter\\PhpUnitXmlManager::listTestsNotice",
|
||||
"@phpunit --list-tests-xml=tests-list-extensions.xml --testsuite=extensions",
|
||||
"MediaWiki\\Composer\\PhpUnitSplitter\\PhpUnitXmlManager::splitTestsListExtensions"
|
||||
],
|
||||
"phpunit:prepare-parallel:default": [
|
||||
"MediaWiki\\Composer\\PhpUnitSplitter\\PhpUnitXmlManager::listTestsNotice",
|
||||
"@phpunit --list-tests-xml=tests-list-default.xml",
|
||||
"MediaWiki\\Composer\\PhpUnitSplitter\\PhpUnitXmlManager::splitTestsListDefault"
|
||||
],
|
||||
"phpunit:prepare-parallel:split-file": "MediaWiki\\Composer\\PhpUnitSplitter\\PhpUnitXmlManager::splitTestsCustom",
|
||||
"phpunit:parallel:custom-groups": "MediaWiki\\Composer\\ComposerLaunchParallel::launchTestsCustomGroups",
|
||||
"phpunit:parallel:database": "MediaWiki\\Composer\\ComposerLaunchParallel::launchTestsDatabase",
|
||||
"phpunit:parallel:databaseless": "MediaWiki\\Composer\\ComposerLaunchParallel::launchTestsDatabaseless",
|
||||
"maintenance": "@php maintenance/run.php"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"prepend-autoloader": false,
|
||||
"allow-plugins": {
|
||||
"wikimedia/composer-merge-plugin": true,
|
||||
"composer/installers": true,
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
},
|
||||
"audit": {
|
||||
"block-insecure": false
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"merge-plugin": {
|
||||
"include": [
|
||||
"composer.local.json"
|
||||
],
|
||||
"merge-dev": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"extra": {
|
||||
"merge-plugin": {
|
||||
"include": [
|
||||
"extensions/*/composer.json",
|
||||
"skins/*/composer.json"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
# Please see DEVELOPERS.md for help
|
||||
#
|
||||
# Contributions to this file are welcome but please note that this file is
|
||||
# minimal by design, with the idea to make it easily extensible via
|
||||
# docker-compose.override.yml. For help with doing that, please see
|
||||
# DEVELOPERS.md
|
||||
services:
|
||||
mediawiki:
|
||||
image: docker-registry.wikimedia.org/dev/bookworm-php83-fpm:1.0.0-s1
|
||||
user: "${MW_DOCKER_UID}:${MW_DOCKER_GID}"
|
||||
volumes:
|
||||
- ./:/var/www/html/w:cached
|
||||
env_file:
|
||||
- '.env'
|
||||
environment:
|
||||
COMPOSER_CACHE_DIR: '/var/www/html/w/cache/composer'
|
||||
MW_SERVER: 'http://localhost:${MW_DOCKER_PORT:-8080}'
|
||||
MW_DOCKER_PORT: "${MW_DOCKER_PORT:-8080}"
|
||||
MW_SCRIPT_PATH: '/w'
|
||||
MW_DBPATH: '/var/www/html/w/cache/sqlite'
|
||||
MW_DBTYPE: 'sqlite'
|
||||
MW_LANG: 'en'
|
||||
MW_USER: '${MEDIAWIKI_USER:-Admin}'
|
||||
MW_PASS: '${MEDIAWIKI_PASSWORD:-dockerpass}'
|
||||
MW_SITENAME: 'MediaWiki'
|
||||
MW_LOG_DIR: /var/www/html/w/cache
|
||||
XDEBUG_CONFIG: '${XDEBUG_CONFIG}'
|
||||
XDEBUG_ENABLE: '${XDEBUG_ENABLE:-true}'
|
||||
XHPROF_ENABLE: '${XHPROF_ENABLE:-true}'
|
||||
|
||||
mediawiki-web:
|
||||
image: docker-registry.wikimedia.org/dev/bookworm-apache2:1.0.1
|
||||
user: "${MW_DOCKER_UID}:${MW_DOCKER_GID}"
|
||||
ports:
|
||||
- "${MW_DOCKER_PORT:-8080}:8080"
|
||||
volumes:
|
||||
- ./:/var/www/html/w:cached
|
||||
env_file:
|
||||
- '.env'
|
||||
environment:
|
||||
MW_LOG_DIR: /var/www/html/w/cache
|
||||
MW_DOCKER_PORT: "${MW_DOCKER_PORT:-8080}"
|
||||
|
||||
mediawiki-jobrunner:
|
||||
image: docker-registry.wikimedia.org/dev/bookworm-php83-jobrunner:1.0.0
|
||||
user: "${MW_DOCKER_UID}:${MW_DOCKER_GID}"
|
||||
volumes:
|
||||
- ./:/var/www/html/w:cached
|
||||
env_file:
|
||||
- '.env'
|
||||
environment:
|
||||
MW_LOG_DIR: /var/www/html/w/cache
|
||||
MW_INSTALL_PATH: /var/www/html/w
|
||||
|
|
@ -0,0 +1,274 @@
|
|||
Hooks {#hooks}
|
||||
=====
|
||||
|
||||
## Introduction
|
||||
|
||||
Hooks allow MediaWiki Core to call extensions or allow one extension to call
|
||||
another extension. For more information and a list of hooks, see
|
||||
https://www.mediawiki.org/wiki/Manual:Hooks
|
||||
|
||||
Starting in MediaWiki 1.35, each hook called by MediaWiki Core has an
|
||||
associated interface with a single method. To call the hook, obtain a "hook
|
||||
runner" object, which implements the relevant interface, and call the relevant
|
||||
method. To handle a hook event in an extension, create a handler object which
|
||||
implements the interface.
|
||||
|
||||
The name of the interface is the name of the hook with "Hook" added to the end.
|
||||
Interfaces are typically placed in the namespace of their primary caller.
|
||||
|
||||
The method name for the hook is the name of the hook, prefixed with "on".
|
||||
|
||||
Several hooks had colons in their name, which are invalid in an interface or
|
||||
method name. These hooks have interfaces and method names in which the colons
|
||||
are replaced with underscores.
|
||||
|
||||
For example, if the hook is called `Mash`, we might have the interface:
|
||||
|
||||
interface MashHook {
|
||||
public function onMash( $banana );
|
||||
}
|
||||
|
||||
Hooks can be defined and called by extensions. The extension should define a
|
||||
hook interface for each hook, as described above.
|
||||
|
||||
## HookContainer
|
||||
|
||||
HookContainer is a service which is responsible for maintaining a list of hook
|
||||
handlers and calling those handlers when requested. HookContainer is not aware
|
||||
of hook interfaces or parameter types.
|
||||
|
||||
HookContainer provides hook metadata. For example, `isRegistered()` tells us
|
||||
whether there are any handlers for a given hook event.
|
||||
|
||||
A HookContainer instance can be obtained from the global service locator with
|
||||
MediaWikiServices::getHookContainer(). When implementing a service that needs
|
||||
to call a hook, a HookContainer object should be passed to the constructor of
|
||||
the service.
|
||||
|
||||
## Hook runner classes
|
||||
|
||||
A hook runner is a class which implements hook interfaces, proxying the calls
|
||||
to `HookContainer::run()`.
|
||||
|
||||
MediaWiki has three hook runner classes: HookRunner, ApiHookRunner and
|
||||
ResourceLoader\HookRunner.
|
||||
ApiHookRunner has proxy methods for all hooks which are called by the Action
|
||||
API. HookRunner has proxy methods for all hooks which are called by other parts
|
||||
of Core. ResourceLoader\HookRunner contains hooks specific to ResourceLoader.
|
||||
Some hooks are implemented in two hook runner classes.
|
||||
|
||||
Extensions which call hooks should create their own hook runner class, by
|
||||
analogy with the ones in Core. Hook runner classes are effectively internal
|
||||
to the module which calls the relevant hooks. Reorganisation of the hook
|
||||
calling code may lead to methods being removed from hook runner classes. Thus,
|
||||
it is safer for extensions to define their own hook runner classes even if
|
||||
they are calling Core hooks.
|
||||
|
||||
New code should typically be written in a service which takes a HookContainer
|
||||
as a constructor parameter. In static functions it can fall back to the global
|
||||
HookContainer instance.
|
||||
For example, to call the hook `Mash`, as defined above, in static code:
|
||||
|
||||
$hookRunner = new HookRunner( MediaWikiServices::getInstance()->getHookContainer() )
|
||||
$hookRunner->onMash( $banana );
|
||||
|
||||
## How to handle a hook event in an extension
|
||||
|
||||
In extension.json, there is a new attribute called `HookHandlers`. This is
|
||||
an object mapping the handler name to an ObjectFactory specification describing
|
||||
how to create the handler object. The specification will typically have a
|
||||
`class` member with the name of the handler class. For example, in an extension
|
||||
called `FoodProcessor`, we may have:
|
||||
|
||||
"HookHandlers": {
|
||||
"main": {
|
||||
"class": "MediaWiki\\Extension\\FoodProcessor\\HookHandler"
|
||||
}
|
||||
}
|
||||
|
||||
Then in the Hooks attribute, instead of a function name, the value will be the
|
||||
handler name:
|
||||
|
||||
"Hooks": {
|
||||
"Mash": "main"
|
||||
}
|
||||
|
||||
Or more explicitly, by using an object instead of a string for the handler:
|
||||
|
||||
"Hooks": {
|
||||
"Mash": {
|
||||
"handler": "main"
|
||||
}
|
||||
}
|
||||
|
||||
Note that while your HookHandler class will implement an interface that ends
|
||||
with the word "Hook", in `extension.json` you should omit the word "Hook"
|
||||
from the key in the `Hooks` definition. For example, in the definitions above,
|
||||
the key must be "Mash", not "MashHook".
|
||||
|
||||
Then the extension will define a handler class:
|
||||
|
||||
namespace MediaWiki\Extension\FoodProcessor;
|
||||
|
||||
class HookHandler implements MashHook {
|
||||
public function onMash( $banana ) {
|
||||
// Implementation goes here
|
||||
}
|
||||
}
|
||||
|
||||
## Service dependencies
|
||||
|
||||
The ObjectFactory specification in HookHandlers can contain a list of services
|
||||
which should be instantiated and provided to the constructor or factory
|
||||
function for the handler. For example:
|
||||
|
||||
"HookHandlers": {
|
||||
"main": {
|
||||
"class": "MediaWiki\\Extension\\FoodProcessor\\HookHandler",
|
||||
"services": [ "ReadOnlyMode" ]
|
||||
}
|
||||
}
|
||||
|
||||
However, care should be taken with this feature. Some services have expensive
|
||||
constructors, so requesting them when handling commonly-called hooks may damage
|
||||
performance. Also, some services may not be safe to construct from within a hook
|
||||
call.
|
||||
|
||||
The safest pattern for service injection is to use a separate handler for each
|
||||
hook, and to inject only the services needed by that hook.
|
||||
|
||||
Calling a hook with the `noServices` option disables service injection. If a
|
||||
handler for such a hook specifies services, an exception will be thrown when
|
||||
the hook is called.
|
||||
|
||||
## Returning and aborting
|
||||
|
||||
If a hook handler returns false, HookContainer will stop iterating through the
|
||||
list of handlers and will immediately return false.
|
||||
|
||||
If a hook handler returns true, or if there is no return value (causing it to
|
||||
effectively return null), then HookContainer will continue to call any other
|
||||
remaining handlers. Eventually HookContainer::run() will return true.
|
||||
|
||||
If there were no registered handlers, HookContainer::run() will return true.
|
||||
|
||||
Some hooks are declared to be "not abortable". If a handler for a non-abortable
|
||||
hook returns false, an exception will be thrown. A hook is declared to be not
|
||||
abortable by passing `[ "abortable" => false ]` in the $options parameter to
|
||||
HookContainer::run().
|
||||
|
||||
Aborting is properly used to enforce a convention that only one extension
|
||||
may handle a given hook call.
|
||||
|
||||
Aborting is sometimes used as a generic return value, to indicate that the
|
||||
caller should stop performing some action.
|
||||
|
||||
Most hook callers do not check the return value from HookContainer::run() and
|
||||
there is no real concept of aborting. The only effect of returning `false` from
|
||||
a handler of these hooks is to break other extensions.
|
||||
|
||||
Theoretically, extensions which are registered first in LocalSettings.php will
|
||||
be called first, and thus will have the first opportunity to abort a hook call.
|
||||
This behaviour should not be relied upon. In the new hook system, handlers
|
||||
registered in the legacy way are called first, before handlers registered in
|
||||
the new way.
|
||||
|
||||
## Parameters passed by reference
|
||||
|
||||
The typical way for a handler to return data to the caller is by modifying a
|
||||
parameter which was passed by reference. This is sometimes called "replacement".
|
||||
|
||||
Reference parameters were somewhat overused in early versions of MediaWiki. You
|
||||
may find that some parameters passed by reference cannot reasonably be modified.
|
||||
Replacement either has no effect on the caller or would cause unexpected or
|
||||
inconsistent effects. Handlers should generally only replace a parameter when it
|
||||
is clear from the documentation that replacement is expected.
|
||||
|
||||
## How to define a new hook
|
||||
|
||||
* Create a hook interface, typically in a subnamespace called `Hook` relative
|
||||
to the caller namespace. For example, if the caller is in a namespace called
|
||||
`MediaWiki\Foo`, the hook interface might be placed in `MediaWiki\Foo\Hook`.
|
||||
* Add an implementation to the relevant HookRunner class.
|
||||
|
||||
## Hook deprecation
|
||||
|
||||
Core hooks are deprecated by adding them to an array in the DeprecatedHooks
|
||||
class. Hooks declared in extensions may be deprecated by listing them in the
|
||||
`DeprecatedHooks` attribute:
|
||||
|
||||
"DeprecatedHooks": {
|
||||
"Mash": {
|
||||
"deprecatedVersion": "2.0",
|
||||
"component": "FoodProcessor"
|
||||
}
|
||||
}
|
||||
|
||||
If the `component` is not specified, it defaults to the name of the extension.
|
||||
|
||||
The hook interface should be marked as deprecated by adding `@deprecated` to the
|
||||
interface doc comment. The interface doc comment is a better place for
|
||||
`@deprecated` than the method doc comment, because this causes the interface to
|
||||
be deprecated for implementation. Deprecating the method only causes calling
|
||||
to be deprecated, not handling.
|
||||
|
||||
Deprecating a hook in this way activates a migration system called
|
||||
**call filtering**. Extensions opt in to call filtering of deprecated hooks by
|
||||
**acknowledging** deprecation. An extension acknowledges deprecation with the
|
||||
`deprecated` parameter in the `Hooks` attribute:
|
||||
|
||||
"Hooks": {
|
||||
"Mash": {
|
||||
"handler": "main",
|
||||
"deprecated": true
|
||||
}
|
||||
}
|
||||
|
||||
If deprecation is acknowledged by the extension:
|
||||
|
||||
* If MediaWiki knows that the hook is deprecated, the handler will not be
|
||||
called. The call to the handler is filtered.
|
||||
* If MediaWiki does not have the hook in its list of deprecated hooks, the
|
||||
handler will be called anyway.
|
||||
|
||||
Deprecation acknowledgement is a way for the extension to say that it has made
|
||||
some other arrangement for implementing the relevant functionality and does
|
||||
not need the handler for the deprecated hook to be called.
|
||||
|
||||
### Call filtering example
|
||||
|
||||
Suppose the hook `Mash` is deprecated in MediaWiki 2.0, and is replaced by a
|
||||
new one called `Slice`. In our example extension FoodProcessor 1.0, the
|
||||
`Mash` hook is handled. In FoodProcessor 2.0, both `Mash` and `Slice` have
|
||||
handlers, but deprecation of `Mash` is acknowledged. Thus:
|
||||
|
||||
* With MediaWiki 2.0 and FoodProcessor 1.0, `onMash` is called but raises a
|
||||
deprecation warning.
|
||||
* With MediaWiki 2.0 and FoodProcessor 2.0, `onMash` is filtered, and `onSlice`
|
||||
is called.
|
||||
* With MediaWiki 1.0 and FoodProcessor 2.0, `onMash` is called, since it is not
|
||||
yet deprecated in Core. `onSlice` is not called since it does not yet exist
|
||||
in Core.
|
||||
|
||||
So the call filtering system provides both forwards and backwards compatibility.
|
||||
|
||||
### Silent deprecation
|
||||
|
||||
Developers sometimes use two stages of deprecation: "soft" deprecation in which
|
||||
the deprecated entity is merely discouraged in documentation, and "hard"
|
||||
deprecation in which a warning is raised. When you soft-deprecate a hook, it is
|
||||
important to register it as deprecated so that call filtering is activated.
|
||||
Activating call filtering simplifies the task of migrating extensions to the
|
||||
new hook.
|
||||
|
||||
To deprecate a hook without raising deprecation warnings, use the "silent" flag:
|
||||
|
||||
"DeprecatedHooks": {
|
||||
"Mash": {
|
||||
"deprecatedVersion": "2.0",
|
||||
"component": "FoodProcessor",
|
||||
"silent": true
|
||||
}
|
||||
}
|
||||
|
||||
As with hard deprecation, `@deprecated` should be added to the interface.
|
||||
|
|
@ -0,0 +1,372 @@
|
|||
Dependency Injection {#dependencyinjection}
|
||||
=======
|
||||
|
||||
This is an overview of how MediaWiki uses of dependency injection.
|
||||
The design originates from [RFC T384](https://phabricator.wikimedia.org/T384).
|
||||
|
||||
The term "dependency injection" (DI) refers to a pattern in object oriented
|
||||
programming. DI tries to improve modularity by reducing strong coupling
|
||||
between classes. In practical terms, this means that anything an object needs
|
||||
to operate should be injected from the outside. The object itself should only
|
||||
know narrow interfaces, no concrete implementation of the logic it relies on.
|
||||
|
||||
The requirement to inject everything typically results in an architecture based
|
||||
on two main kinds of objects: simple "value" objects with no business logic
|
||||
(and often immutable), and essentially stateless "service" objects that use
|
||||
other service objects to operate on value objects.
|
||||
|
||||
As of 2022 (MediaWiki 1.39), MediaWiki has adopted dependency injection in much
|
||||
of its code. However, some operations still require the use of singletons or
|
||||
otherwise involve global state.
|
||||
|
||||
## Overview
|
||||
|
||||
The heart of the DI in MediaWiki is the central service locator,
|
||||
MediaWikiServices, which acts as the top-level factory (or registry) for
|
||||
services. MediaWikiServices represents the tree (or network) of service objects
|
||||
that define MediaWiki's application logic. It acts as an entry point to all
|
||||
dependency injection for MediaWiki core.
|
||||
|
||||
When `MediaWikiServices::getInstance()` is first called, it will create an
|
||||
instance of MediaWikiServices and populate it with the services defined by
|
||||
MediaWiki core in `includes/ServiceWiring.php`, as well as any additional
|
||||
bootstrapping files specified in `$wgServiceWiringFiles`. The service
|
||||
wiring files define the (default) service implementations to use, and
|
||||
specifies how they depend on each other ("wiring").
|
||||
|
||||
Extensions can add their own wiring files to `$wgServiceWiringFiles`, in order
|
||||
to define their own service. Extensions may also use the `MediaWikiServices`
|
||||
hook to replace ("redefine") a core service, by calling methods on the
|
||||
MediaWikiServices instance.
|
||||
|
||||
It should be noted that the term "service locator" is often used to refer to a
|
||||
top-level factory that is accessed directly, throughout the code, to avoid
|
||||
explicit dependency injection. In contrast, the term "DI container" is often
|
||||
used to describe a top-level factory that is only accessed only inside service
|
||||
wiring code when instantiating service classes. We use the term "service locator"
|
||||
because it is more descriptive than "DI container", even though application
|
||||
logic is strongly discouraged from accessing MediaWikiServices directly.
|
||||
|
||||
`MediaWikiServices::getInstance()` should ideally be accessed only in "static
|
||||
entry points" such as hook handler functions. See "Migration" below.
|
||||
|
||||
## Principles {#di-principles}
|
||||
|
||||
Service classes generally only vary on site configuration and are
|
||||
deterministic and agnostic of global state. It is the responsibility of
|
||||
callers to a service object to obtain and derive information from a
|
||||
web request (such as title, user, language, WebRequest, RequestContext),
|
||||
and pass this to specific methods of a service class as-needed. See
|
||||
[T218555](https://phabricator.wikimedia.org/T218555) for related discussion.
|
||||
|
||||
Consider using the factory pattern if your service would otherwise be
|
||||
unergonomic or slow, e.g. due to passing many parameters and/or recomputing
|
||||
the same derived information. This keeps the global state out of the
|
||||
service class, by having the service be a factory from which the caller
|
||||
can obtain a (re-usable) object for its specific context.
|
||||
|
||||
This design ensures service classes are safe to use in both user-facing
|
||||
contexts on the web (e.g. index.php page views and special pages), as
|
||||
well as in an API, job, or maintenance script. It also ensures that
|
||||
within a web-facing context the same service can be safely used
|
||||
multiple times to perform different operations, without incorrectly
|
||||
implying certain commonalities between these calls. Lastly, this
|
||||
restriction allows services to be instantiated across wikis in the
|
||||
future.
|
||||
|
||||
If a feature is not ready to meet these requirements, keep it outside
|
||||
the service container. This avoids false confidence in the safety of an
|
||||
injected service, and its ripple effect on other services.
|
||||
|
||||
### Principle exemption
|
||||
|
||||
There is a limited exemption to the above principles for "inconsequential
|
||||
state". That is, global state may be used directly if and only if used
|
||||
for diagnostics or to optimise performance, so long as they do not
|
||||
change the observed functional outcome of a called method.
|
||||
|
||||
Examples of safe and inconsequential state:
|
||||
|
||||
|
||||
* Use `$_SERVER['REQUEST_TIME_FLOAT']` or `ConvertibleTimestamp::now`
|
||||
to help compute a time measure that is sent to a metric service.
|
||||
|
||||
* Use `wfHostname()`, `PHP_SAPI`, or `WikiMap::getCurrentWikiId()`
|
||||
to describe where, how, or for which wiki the overall process was
|
||||
created and send it as message context to a logging service.
|
||||
|
||||
* Use `WebRequest::getRequestId()` to automatically inject a
|
||||
header into HTTP requests to other services. These are for tracking
|
||||
purposes only.
|
||||
|
||||
* Use `function_exists('apcu_fetch')` to automatically enable use
|
||||
of caching.
|
||||
|
||||
Examples of unsafe state in a service class:
|
||||
|
||||
* Do not use `WikiMap::getCurrentWikiId()` as the default value
|
||||
to obtain a database connection.
|
||||
|
||||
* Do not use `$_SERVER['SERVER_NAME']` to inject a header into
|
||||
HTTP requests to other services to control which wiki to operate on.
|
||||
|
||||
## Create a new service
|
||||
|
||||
To create a new service in MediaWiki core, write a function that will return
|
||||
the appropriate class instantiation for that service in ServiceWiring.php. This
|
||||
makes the service available through the generic `getService()` method on the
|
||||
`MediaWikiServices` class. We then also add a wrapper method to
|
||||
MediaWikiServices.php with a discoverable method named and strictly typed
|
||||
return value to reduce mistakes and improve static analysis.
|
||||
|
||||
## Service Reset
|
||||
|
||||
Services get their configuration injected, and changes to global
|
||||
configuration variables will not have any effect on services that were already
|
||||
instantiated. This would typically be the case for low level services like
|
||||
the ConfigFactory or the ObjectCacheManager, which are used during extension
|
||||
registration. To address this issue, Setup.php resets the global service
|
||||
locator instance by calling `MediaWikiServices::resetGlobalInstance()` once
|
||||
configuration and extension registration is complete.
|
||||
|
||||
Note that "unmanaged" legacy services services that manage their own singleton
|
||||
must not keep references to services managed by MediaWikiServices, to allow a
|
||||
clean reset. After the global MediaWikiServices instance got reset, any such
|
||||
references would be stale, and using a stale service will result in an error.
|
||||
|
||||
Services should either have all dependencies injected and be themselves managed
|
||||
by MediaWikiServices, or they should use the Service Locator pattern, accessing
|
||||
service instances via the global MediaWikiServices instance state when needed.
|
||||
This ensures that no stale service references remain after a reset.
|
||||
|
||||
## Configuration
|
||||
|
||||
When the default MediaWikiServices instance is created, a Config object is
|
||||
provided to the constructor. This Config object represents the "bootstrap"
|
||||
configuration which will become available as the 'BootstrapConfig' service.
|
||||
As of MW 1.27, the bootstrap config is a GlobalVarConfig object providing
|
||||
access to the $wgXxx configuration variables.
|
||||
|
||||
The bootstrap config is then used to construct a 'ConfigFactory' service,
|
||||
which in turn is used to construct the 'MainConfig' service. Application
|
||||
logic should use the 'MainConfig' service (or a more specific configuration
|
||||
object). 'BootstrapConfig' should only be used for bootstrapping basic
|
||||
services that are needed to load the 'MainConfig'.
|
||||
|
||||
Note: Several well known services in MediaWiki core act as factories
|
||||
themselves, e.g. ApiModuleManager, ObjectCache, SpecialPageFactory, etc.
|
||||
The registries these factories are based on are currently managed as part of
|
||||
the configuration. This may however change in the future.
|
||||
|
||||
## Migration
|
||||
|
||||
This section provides some recipes for improving code modularity by reducing
|
||||
strong coupling. The dependency injection mechanism described above is an
|
||||
essential tool in this effort.
|
||||
|
||||
### Migrate access to global service instances and config variables
|
||||
Assume `Foo` is a class that uses the `$wgScriptPath` global and calls
|
||||
`wfGetDB()` to get a database connection, in non-static methods.
|
||||
* Add `$scriptPath` as a constructor parameter and use `$this->scriptPath`
|
||||
instead of `$wgScriptPath`.
|
||||
* Add IConnectionProvider `$dbProvider` as a constructor parameter. Use
|
||||
`$this->dbProvider->getReplicaDatabase()` instead of `wfGetDB( DB_REPLICA )`,
|
||||
`$this->dbProvider->->getPrimaryDatabase()` instead of `wfGetDB( DB_PRIMARY )`.
|
||||
* Any code that calls `Foo`'s constructor would now need to provide the
|
||||
`$scriptPath` and `$dbProvider`. To avoid this, avoid direct instantiation
|
||||
of services all together - see below.
|
||||
|
||||
### Migrate services with multiple configuration variables
|
||||
When a service needs multiple configuration globals injected, a ServiceOptions
|
||||
object is commonly used with the service class defining a public constant
|
||||
(usually `CONSTRUCTOR_OPTIONS`) with an array of settings that the class needs
|
||||
access to.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
class DemoService {
|
||||
|
||||
public const CONSTRUCTOR_OPTIONS = [
|
||||
'Foo',
|
||||
'Bar'
|
||||
];
|
||||
|
||||
private $options;
|
||||
|
||||
public function __construct( ServiceOptions $options ) {
|
||||
// ServiceOptions::assertRequiredOptions ensures that all of the
|
||||
// settings listed in CONSTRUCTOR_OPTIONS are available
|
||||
$options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
|
||||
$this->options = $options;
|
||||
// $wgFoo is now available with $this->options->get( 'Foo' )
|
||||
// $wgBar is now available with $this->options->get( 'Bar' )
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
ServiceOptions objects are constructed within ServiceWiring.php and can also
|
||||
be created in tests.
|
||||
```php
|
||||
'DemoService' => function ( MediaWikiServices $services ) : DemoService {
|
||||
return new DemoService(
|
||||
new ServiceOptions(
|
||||
DemoService::CONSTRUCTOR_OPTIONS,
|
||||
$services->getMainConfig()
|
||||
)
|
||||
);
|
||||
},
|
||||
```
|
||||
|
||||
### Migrate class-level singleton getters
|
||||
Assume class `Foo` has mostly non-static methods, and provides a static
|
||||
`getInstance()` method that returns a singleton (or default instance).
|
||||
* Add an instantiator function for `Foo` into ServiceWiring.php. The
|
||||
instantiator would do exactly what `Foo::getInstance()` did. However, it
|
||||
should replace any access to global state with calls to `$services->getXxx()`
|
||||
to get a service, or `$services->getMainConfig()->get()` to get a
|
||||
configuration setting.
|
||||
* Add a `getFoo()` method to MediaWikiServices. Don't forget to add the
|
||||
appropriate test cases in MediaWikiServicesTest.
|
||||
* Turn `Foo::getInstance()` into a deprecated alias for
|
||||
`MediaWikiServices::getInstance()->getFoo()`. Change all calls to
|
||||
`Foo::getInstance()` to use injection (see above).
|
||||
|
||||
### Migrate direct service instantiation
|
||||
Assume class `Bar` calls `new Foo()`.
|
||||
* Add an instantiator function for `Foo` into ServiceWiring.php and add a
|
||||
`getFoo()` method to MediaWikiServices. Don't forget to add the appropriate
|
||||
test cases in MediaWikiServicesTest.
|
||||
* In the instantiator, replace any access to global state with calls
|
||||
to `$services->getXxx()` to get a service, or
|
||||
`$services->getMainConfig()->get()` to get a configuration setting.
|
||||
* The code in `Bar` that calls `Foo`'s constructor should be changed to have a
|
||||
`Foo` instance injected; Eventually, the only code that instantiates `Foo` is
|
||||
the instantiator in ServiceWiring.php.
|
||||
* As an intermediate step, `Bar`'s constructor could initialize the `$foo`
|
||||
member variable by calling `MediaWikiServices::getInstance()->getFoo()`. This
|
||||
is acceptable as a stepping stone, but should be replaced by proper injection
|
||||
via a constructor argument. Do not however inject the MediaWikiServices
|
||||
object!
|
||||
|
||||
### Migrate parameterized helper instantiation
|
||||
Assume class `Bar` creates some helper object by calling `new Foo( $x )`,
|
||||
and `Foo` uses a global singleton of the `Xyzzy` service.
|
||||
* Define a `FooFactory` class (or a `FooFactory` interface along with a
|
||||
`MyFooFactory` implementation). `FooFactory` defines the method
|
||||
`newFoo( $x )` or `getFoo( $x )`, depending on the desired semantics (`newFoo`
|
||||
would guarantee a fresh instance). When Foo gets refactored to have `Xyzzy`
|
||||
injected, `FooFactory` will need a `Xyzzy` instance, so `newFoo()` can pass it
|
||||
to `new Foo()`.
|
||||
* Add an instantiator function for FooFactory into ServiceWiring.php and add a
|
||||
getFooFactory() method to MediaWikiServices. Don't forget to add the
|
||||
appropriate test cases in MediaWikiServicesTest.
|
||||
* The code in Bar that calls Foo's constructor should be changed to have a
|
||||
FooFactory instance injected; Eventually, the only code that instantiates
|
||||
Foo are implementations of FooFactory, and the only code that instantiates
|
||||
FooFactory is the instantiator in ServiceWiring.php.
|
||||
* As an intermediate step, Bar's constructor could initialize the $fooFactory
|
||||
member variable by calling `MediaWikiServices::getInstance()->getFooFactory()`.
|
||||
This is acceptable as a stepping stone, but should be replaced by proper
|
||||
injection via a constructor argument. Do not however inject the
|
||||
MediaWikiServices object!
|
||||
|
||||
### Migrate a handler registry
|
||||
Assume class `Bar` calls `FooRegistry::getFoo( $x )` to get a specialized `Foo`
|
||||
instance for handling `$x`.
|
||||
* Turn `getFoo` into a non-static method.
|
||||
* Add an instantiator function for `FooRegistry` into ServiceWiring.php and add
|
||||
a `getFooRegistry()` method to MediaWikiServices. Don't forget to add the
|
||||
appropriate test cases in MediaWikiServicesTest.
|
||||
* Change all code that calls `FooRegistry::getFoo()` statically to call this
|
||||
method on a `FooRegistry` instance. That is, `Bar` would have a `$fooRegistry`
|
||||
member, initialized from a constructor parameter.
|
||||
* As an intermediate step, Bar's constructor could initialize the `$fooRegistry`
|
||||
member variable by calling
|
||||
`MediaWikiServices::getInstance()->getFooRegistry()`. This is acceptable as a
|
||||
stepping stone, but should be replaced by proper injection via a constructor
|
||||
argument. Do not however inject the MediaWikiServices object!
|
||||
|
||||
### Migrate deferred service instantiation
|
||||
Assume class `Bar` calls `new Foo()`, but only when needed, to avoid the cost of
|
||||
instantiating Foo().
|
||||
* Define a `FooFactory` interface and a `MyFooFactory` implementation of that
|
||||
interface. `FooFactory` defines the method `getFoo()` with no parameters.
|
||||
* Precede as for the "parameterized helper instantiation" case described above.
|
||||
|
||||
### Migrate a class with only static methods
|
||||
Assume `Foo` is a class with only static methods, such as `frob()`, which
|
||||
interacts with global state or system resources.
|
||||
* Introduce a `FooService` interface and a `DefaultFoo` implementation of that
|
||||
interface. `FooService` contains the public methods defined by Foo.
|
||||
* Add an instantiator function for `FooService` into ServiceWiring.php and
|
||||
add a `getFooService()` method to MediaWikiServices. Don't forget to
|
||||
add the appropriate test cases in MediaWikiServicesTest.
|
||||
* Add a private static `getFooService()` method to `Foo`. That method just
|
||||
calls `MediaWikiServices::getInstance()->getFooService()`.
|
||||
* Make all methods in `Foo` delegate to the `FooService` returned by
|
||||
`getFooService()`. That is, `Foo::frob()` would do
|
||||
`self::getFooService()->frob()`.
|
||||
* Deprecate `Foo`. Inject a `FooService` into all code that calls methods
|
||||
on `Foo`, and change any calls to static methods in foo to the methods
|
||||
provided by the `FooService` interface.
|
||||
|
||||
### Migrate static hook handler functions (to allow unit testing)
|
||||
Assume `MyExtHooks::onFoo` is a static hook handler function that is called with
|
||||
the parameter `$x`; Further assume `MyExt::onFoo` needs service `Bar`, which is
|
||||
already known to MediaWikiServices (if not, see above).
|
||||
* Create a non-static `doFoo( $x )` method in `MyExtHooks` that has the same
|
||||
signature as `onFoo( $x )`. Move the code from `onFoo()` into `doFoo()`,
|
||||
replacing any access to global or static variables with access to instance
|
||||
member variables.
|
||||
* Add a constructor to `MyExtHooks` that takes a Bar service as a parameter.
|
||||
* Add a static method called `newFromGlobalState()` with no parameters. It
|
||||
should just return
|
||||
`new MyExtHooks( MediaWikiServices::getInstance()->getBar() )`.
|
||||
* The original static handler method `onFoo( $x )` is then implemented as
|
||||
`self::newFromGlobalState()->doFoo( $x )`.
|
||||
|
||||
### Migrate a "smart record"
|
||||
Assume `Thingy` is a "smart record" that "knows" how to load and store itself.
|
||||
For this purpose, `Thingy` uses wfGetDB().
|
||||
* Create a "dumb" value class `ThingyRecord` that contains all the information
|
||||
that `Thingy` represents (e.g. the information from a database row). The value
|
||||
object should not know about any service.
|
||||
* Create a DAO-style service for loading and storing `ThingyRecord`s, called
|
||||
`ThingyStore`. It may be useful to split the interfaces for reading and
|
||||
writing, with a single class implementing both interfaces, so we in the
|
||||
end have the `ThingyLookup` and `ThingyStore` interfaces, and a SqlThingyStore
|
||||
implementation.
|
||||
* Add instantiator functions for `ThingyLookup` and `ThingyStore` in
|
||||
ServiceWiring.php. Since we want to use the same instance for both service
|
||||
interfaces, the instantiator for `ThingyLookup` would return
|
||||
`$services->getThingyStore()`.
|
||||
* Add `getThingyLookup()` and `getThingyStore()` methods to MediaWikiServices.
|
||||
Don't forget to add the appropriate test cases in MediaWikiServicesTest.
|
||||
* In the old `Thingy` class, replace all member variables that represent the
|
||||
record's data with a single `ThingyRecord` object.
|
||||
* In the old Thingy class, replace all calls to static methods or functions,
|
||||
such as wfGetDB(), with calls to the appropriate services, such as
|
||||
`IConnectionProvider::getReplicaDatabase()`.
|
||||
* In Thingy's constructor, pull in any services needed, such as the
|
||||
IConnectionProvider, by using `MediaWikiServices::getInstance()`. These services
|
||||
cannot be injected without changing the constructor signature, which
|
||||
is often impractical for "smart records" that get instantiated directly
|
||||
in many places in the code base.
|
||||
* Deprecate the old `Thingy` class. Replace all usages of it with one of the
|
||||
three new classes: loading needs a `ThingyLookup`, storing needs a
|
||||
`ThingyStore`, and reading data needs a `ThingyRecord`.
|
||||
|
||||
### Migrate lazy loading
|
||||
Assume `Thingy` is a "smart record" as described above, but requires lazy
|
||||
loading of some or all the data it represents.
|
||||
* Instead of a plain object, define `ThingyRecord` to be an interface. Provide a
|
||||
"simple" and "lazy" implementations, called `SimpleThingyRecord` and
|
||||
`LazyThingyRecord`. `LazyThingyRecord` knows about some lower level storage
|
||||
interface, like a LoadBalancer, and uses it to load information on demand.
|
||||
* Any direct instantiation of a `ThingyRecord` would use the
|
||||
`SimpleThingyRecord` implementation.
|
||||
* `SqlThingyStore` however creates instances of `LazyThingyRecord`, and injects
|
||||
whatever storage layer service `LazyThingyRecord` needs to perform lazy
|
||||
loading.
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
Introduction {#mainpage}
|
||||
===============================
|
||||
|
||||
Welcome to the MediaWiki autogenerated documentation system.
|
||||
If you are looking to use, install or configure your wiki, see the main site: <https://www.mediawiki.org/>.
|
||||
|
||||
Helpful resources
|
||||
-------------------------------
|
||||
- [General information](https://www.mediawiki.org/)
|
||||
- [Installation guide](https://www.mediawiki.org/wiki/Manual:Installation_guide)
|
||||
- [Configuration](https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:System_administration)
|
||||
- [New Developers](https://www.mediawiki.org/wiki/New_Developers)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
Language {#language}
|
||||
=======
|
||||
|
||||
The Language object handles all readable text produced by the software.
|
||||
|
||||
See [MediaWiki.org](https://www.mediawiki.org/wiki/Localisation#General_use_.28for_developers.29)
|
||||
for documentation relating to using localized messages.
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
LinkCache {#linkcache}
|
||||
========
|
||||
|
||||
The LinkCache class maintains a list of article titles and the information about
|
||||
whether or not the article exists in the database. This is used to mark up links
|
||||
when displaying a page. If the same link appears more than once on any page,
|
||||
then it only has to be looked up once. In most cases, link lookups are done in
|
||||
batches with the LinkBatch class, or the equivalent in Parser::replaceLinkHolders(),
|
||||
so the link cache is mostly useful for short snippets of parsed text (such as
|
||||
the site notice), and for links in the navigation areas of the skin.
|
||||
|
||||
The link cache was formerly used to track links used in a document for the
|
||||
purposes of updating the link tables. This application is now deprecated.
|
||||
|
||||
To create a batch, you can use the following code:
|
||||
|
||||
```php
|
||||
$pages = [ 'Main Page', 'Project:Help', /* ... */ ];
|
||||
$titles = [];
|
||||
|
||||
foreach( $pages as $page ){
|
||||
$titles[] = Title::newFromText( $page );
|
||||
}
|
||||
|
||||
$linkBatchFactory = MediaWikiServices::getInstance()->getLinkBatchFactory();
|
||||
$batch = $linkBatchFactory->newLinkBatch( $titles );
|
||||
$batch->execute();
|
||||
```
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
Logger {#debuglogger}
|
||||
=======
|
||||
|
||||
MediaWiki.Logger.LoggerFactory implements a [PSR-3] compatible message logging
|
||||
system.
|
||||
|
||||
Named Psr.Log.LoggerInterface instances can be obtained from the
|
||||
MediaWiki.Logger.LoggerFactory::getInstance() static method.
|
||||
MediaWiki.Logger.LoggerFactory expects a class implementing the
|
||||
MediaWiki.Logger.Spi interface to act as a factory for new
|
||||
Psr.Log.LoggerInterface instances.
|
||||
|
||||
The "Spi" in MediaWiki.Logger.Spi stands for "service provider interface". An
|
||||
SPI is an API intended to be implemented or extended by a third party. This
|
||||
software design pattern is intended to enable framework extension and
|
||||
replaceable components. It is specifically used in the
|
||||
MediaWiki.Logger.LoggerFactory service to allow alternate PSR-3 logging
|
||||
implementations to be easily integrated with MediaWiki.
|
||||
|
||||
The service provider interface allows the backend logging library to be
|
||||
implemented in multiple ways. The $wgMWLoggerDefaultSpi global provides the
|
||||
classname of the default MediaWiki.Logger.Spi implementation to be loaded at
|
||||
runtime. This can either be the name of a class implementing the
|
||||
MediaWiki.Logger.Spi with a zero argument constructor or a callable that will
|
||||
return an MediaWiki.Logger.Spi instance. Alternately the
|
||||
MediaWiki.Logger.LoggerFactory::registerProvider() static method can be called
|
||||
to inject an MediaWiki.Logger.Spi instance into the LoggerFactory and bypass the
|
||||
use of the default configuration variable.
|
||||
|
||||
The MediaWiki.Logger.LegacySpi class implements a service provider to generate
|
||||
MediaWiki.Logger.LegacyLogger instances. The MediaWiki.Logger.LegacyLogger class
|
||||
implements the PSR-3 logger interface and provides output and configuration
|
||||
equivalent to the historic logging output of wfDebug, wfDebugLog, wfLogDBError
|
||||
and wfErrorLog. The MediaWiki.Logger.LegacySpi class is the default service
|
||||
provider defined in MainConfigSchema.php. It's usage should be transparent for
|
||||
users who are not ready or do not wish to switch to a alternate logging
|
||||
platform.
|
||||
|
||||
The MediaWiki.Logger.MonologSpi class implements a service provider to generate
|
||||
Psr.Log.LoggerInterface instances that use the [Monolog] logging library. See
|
||||
the PHP docs (or source) for MediaWiki.Logger.MonologSpi for details on the
|
||||
configuration of this provider. The default configuration installs a null
|
||||
handler that will silently discard all logging events. The documentation
|
||||
provided by the class describes a more feature rich logging configuration.
|
||||
|
||||
## Classes
|
||||
|
||||
* MediaWiki.Logger.LoggerFactory: Factory for Psr.Log.LoggerInterface loggers
|
||||
* MediaWiki.Logger.Spi: Service provider interface for
|
||||
MediaWiki.Logger.LoggerFactory
|
||||
* MediaWiki.Logger.NullSpi: MediaWiki.Logger.Spi for creating instances that
|
||||
discard all log events
|
||||
* MediaWiki.Logger.LegacySpi: Service provider for creating
|
||||
MediaWiki.Logger.LegacyLogger instances
|
||||
* MediaWiki.Logger.LegacyLogger: PSR-3 logger that mimics the historical output
|
||||
and configuration of wfDebug, wfErrorLog and other global logging functions.
|
||||
* MediaWiki.Logger.MonologSpi: MediaWiki.Logger.Spi for creating instances
|
||||
backed by the monolog logging library
|
||||
* MediaWiki.Logger.Monolog.LegacyHandler: Monolog handler that replicates the
|
||||
udp2log and file logging functionality of wfErrorLog()
|
||||
* MediaWiki.Logger.Monolog.WikiProcessor: Monolog log processor that adds host:
|
||||
wfHostname() and wiki: WikiMap::getCurrentWikiId() to all records
|
||||
|
||||
## Globals
|
||||
|
||||
* $wgMWLoggerDefaultSpi: Configure which service provider LoggerFactory will
|
||||
use for creating logger objects.
|
||||
|
||||
[PSR-3]: https://www.php-fig.org/psr/psr-3/
|
||||
[Monolog]: https://github.com/Seldaek/monolog
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/docs Directory README
|
||||
======================
|
||||
|
||||
The 'docs' directory contain various text files that should help you understand
|
||||
the most important parts of the code of MediaWiki. More in-depth documentation
|
||||
can be found at:
|
||||
https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Code
|
||||
https://www.mediawiki.org/wiki/Special:MyLanguage/Developer_hub
|
||||
API documentation is automatically generated and updated daily at:
|
||||
https://doc.wikimedia.org/mediawiki-core/master/php/
|
||||
|
||||
You can get a fresh version using 'make doc' or mwdocgen.php in the
|
||||
../maintenance/ directory.
|
||||
|
||||
|
||||
For end users, most of the documentation is located online at:
|
||||
https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents
|
||||
Documentation for MediaWiki site administrators is at:
|
||||
https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
Skins {#skin}
|
||||
=======
|
||||
|
||||
## Core Skins
|
||||
|
||||
MediaWiki includes four core skins:
|
||||
|
||||
* Vector: The default skin. Introduced in the 1.16 release (2010), it has been
|
||||
set as the default in MediaWiki since the 1.17 release (2011), replacing
|
||||
Monobook.
|
||||
* Monobook: Named after the black-and-white photo of a book in the page
|
||||
background. Introduced in the 2004 release of 1.3, it had been the
|
||||
default skin since then, before being replaced by Vector.
|
||||
* Modern: An attractive blue/grey theme with sidebar and top bar. Derived from
|
||||
Monobook.
|
||||
* Cologne Blue: A lightweight skin with minimal formatting. The oldest of the
|
||||
currently bundled skins, largely rewritten in 2012 while keeping its
|
||||
appearance.
|
||||
|
||||
### Legacy core skins
|
||||
|
||||
Several legacy skins were removed in the 1.22 release, as the burden of
|
||||
supporting them became too heavy to bear. Those were:
|
||||
|
||||
* Standard (a.k.a. Classic): The old default skin written by Lee Crocker during
|
||||
the phase 3 rewrite, in 2002.
|
||||
* Nostalgia: A skin which looks like Wikipedia did in its first year (2001).
|
||||
This skin is now used for the old Wikipedia snapshot at
|
||||
https://nostalgia.wikipedia.org/
|
||||
* Chick: A lightweight Monobook skin with no sidebar. The sidebar links were
|
||||
given at the bottom of the page instead.
|
||||
* Simple: A lightweight skin with a simple white-background sidebar and no top
|
||||
bar.
|
||||
* MySkin: Essentially Monobook without the CSS. The idea was that it could be
|
||||
customised using user-specific or site-wide CSS (see below).
|
||||
|
||||
|
||||
## Custom CSS/JS
|
||||
|
||||
It is possible to customise the site CSS and JavaScript without editing any
|
||||
server-side source files. This is done by editing some pages on the wiki:
|
||||
|
||||
* `MediaWiki:Common.css` for skin-independent CSS
|
||||
* `MediaWiki:Common.js` for skin-independent JavaScript
|
||||
* `MediaWiki:Vector.css`, `MediaWiki:Monobook.css`, etc. for skin-dependent CSS
|
||||
* `MediaWiki:Vector.js`, `MediaWiki:Monobook.js`, etc. for skin-dependent
|
||||
JavaScript
|
||||
|
||||
These can also be customised on a per-user basis, by editing
|
||||
`User:<name>/vector.css`, `User:<name>/vector.js`, etc.
|
||||
|
||||
|
||||
## Custom skins
|
||||
|
||||
Several custom skins are available as of 2019. List of all skins is available at
|
||||
[MediaWiki.org](https://www.mediawiki.org/wiki/Special:MyLanguage/Category:All_skins).
|
||||
|
||||
Installing a skin requires adding its files in a subdirectory under `skins/` and
|
||||
adding an appropriate `wfLoadSkin` line to `LocalSettings.php`, similarly to
|
||||
how extensions are installed.
|
||||
|
||||
You can then make that skin the default by adding:
|
||||
|
||||
```php
|
||||
$wgDefaultSkin = '<name>';
|
||||
```
|
||||
|
||||
|
||||
Or disable it entirely by removing the `wfLoadSkin` line. (User settings will
|
||||
not be lost if it's reenabled later.)
|
||||
|
||||
See https://www.mediawiki.org/wiki/Manual:Skinning for more information on
|
||||
writing new skins.
|
||||
|
||||
### Legacy custom skins
|
||||
|
||||
Until MediaWiki 1.25 it used to be possible to just put a `<name>.php` file in
|
||||
MediaWiki's `skins/` directory, which would be loaded and expected to contain
|
||||
the `Skin<name>` class. This way has always been discouraged because of its
|
||||
limitations (inability to add localisation messages, ResourceLoader modules,
|
||||
etc.) and awkwardness in managing such skins. For information on migrating skins
|
||||
using this old method, see
|
||||
https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery.
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
Title {#title}
|
||||
========
|
||||
|
||||
The MediaWiki software's "Title" class represents article titles, which are used
|
||||
for many purposes: as the human-readable text title of the article, in the URL
|
||||
used to access the article, the wikitext link to the article, the key into the
|
||||
article database, and so on. The class in instantiated from one of these forms
|
||||
and can be queried for the others, and for other attributes of the title. This
|
||||
is intended to be an immutable "value" class, so there are no mutator functions.
|
||||
|
||||
To get a new instance, call Title::newFromText(). Once instantiated, the
|
||||
non-static accessor methods can be used, such as getText(), getDBkey(),
|
||||
getNamespace(), etc. Note that Title::newFromText() may return false if the text
|
||||
is illegal according to the rules below.
|
||||
|
||||
The prefix rules: a title consists of an optional interwiki prefix (such as "m:"
|
||||
for meta or "de:" for German), followed by an optional namespace, followed by
|
||||
the remainder of the title. Both interwiki prefixes and namespace prefixes have
|
||||
the same rules: they contain only letters, digits, space, and underscore, must
|
||||
start with a letter, are case insensitive, and spaces and underscores are
|
||||
interchangeable. Prefixes end with a ":". A prefix is only recognized if it is
|
||||
one of those specifically allowed by the software. For example, "de:name" is a
|
||||
link to the article "name" in the German Wikipedia, because "de" is recognized
|
||||
as one of the allowable interwikis. The title "talk:name" is a link to the
|
||||
article "name" in the "talk" namespace of the current wiki, because "talk" is a
|
||||
recognized namespace. Both may be present, and if so, the interwiki must
|
||||
come first, for example, "m:talk:name". If a title begins with a colon as its
|
||||
first character, no prefixes are scanned for, and the colon is just removed.
|
||||
Note that because of these rules, it is possible to have articles with colons in
|
||||
their names. "E. Coli 0157:H7" is a valid title, as is "2001: A Space Odyssey",
|
||||
because "E. Coli 0157" and "2001" are not valid interwikis or namespaces.
|
||||
|
||||
It is not possible to have an article whose bare name includes a namespace or
|
||||
interwiki prefix.
|
||||
|
||||
An initial colon in a title listed in wiki text may however suppress special
|
||||
handling for interlanguage links, image links, and category links. It is also
|
||||
used to indicate the main namespace in template inclusions.
|
||||
|
||||
Once prefixes have been stripped, the rest of the title processed this way:
|
||||
|
||||
* Spaces and underscores are treated as equivalent and each is converted to the
|
||||
other in the appropriate context (underscore in URL and database keys, spaces
|
||||
in plain text).
|
||||
* Multiple consecutive spaces are converted to a single space.
|
||||
* Leading or trailing space is removed.
|
||||
* If $wgCapitalLinks is enabled (the default), the first letter is capitalised,
|
||||
using the capitalisation function of the content language object.
|
||||
* The unicode characters LRM (U+200E) and RLM (U+200F) are silently stripped.
|
||||
* Invalid UTF-8 sequences or instances of the replacement character (U+FFFD) are
|
||||
considered illegal.
|
||||
* A percent sign followed by two hexadecimal characters is illegal
|
||||
* Anything that looks like an XML/HTML character reference is illegal
|
||||
* Any character not matched by the $wgLegalTitleChars regex is illegal
|
||||
* Zero-length titles (after whitespace stripping) are illegal
|
||||
|
||||
All titles except special pages must be less than 255 bytes when encoded with
|
||||
UTF-8, because that is the size of the database field. Special page titles may
|
||||
be up to 512 bytes.
|
||||
|
||||
Note that Unicode Normal Form C (NFC) is enforced by MediaWiki's user interface
|
||||
input functions, and so titles will typically be in this form.
|
||||
|
||||
getArticleID() needs some explanation: for "internal" articles, it should return
|
||||
the "page_id" field if the article exists, else it returns 0. For all external
|
||||
articles it returns 0. All of the IDs for all instances of Title created during
|
||||
a request are cached, so they can be looked up quickly while rendering wiki text
|
||||
with lots of internal links. See LinkCache.md.
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/schema#",
|
||||
"description": "MediaWiki abstract database schema schema",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"comment": {
|
||||
"type": "string",
|
||||
"description": "Comment describing the schema change"
|
||||
},
|
||||
"before": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"description": "Emtpy object signifying table creation",
|
||||
"maxProperties": 0
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "Schema before the change",
|
||||
"$ref": "abstract-schema-table.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
"after": {
|
||||
"type": "object",
|
||||
"description": "Schema after the change",
|
||||
"$ref": "abstract-schema-table.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/schema#",
|
||||
"description": "Abstract description of a mediawiki database table",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the table"
|
||||
},
|
||||
"comment": {
|
||||
"type": "string",
|
||||
"description": "Comment describing the table"
|
||||
},
|
||||
"columns": {
|
||||
"type": "array",
|
||||
"additionalItems": false,
|
||||
"description": "Columns",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the column"
|
||||
},
|
||||
"comment": {
|
||||
"type": "string",
|
||||
"description": "Comment describing the column"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Data type of the column",
|
||||
"enum": [
|
||||
"bigint",
|
||||
"binary",
|
||||
"blob",
|
||||
"boolean",
|
||||
"datetimetz",
|
||||
"decimal",
|
||||
"float",
|
||||
"integer",
|
||||
"mwenum",
|
||||
"mwtimestamp",
|
||||
"mwtinyint",
|
||||
"smallint",
|
||||
"string",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"description": "Additional options",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"autoincrement": {
|
||||
"type": "boolean",
|
||||
"description": "Indicates if the field should use an autoincremented value if no value was provided",
|
||||
"default": false
|
||||
},
|
||||
"default": {
|
||||
"type": [
|
||||
"number",
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "The default value of the column if no value was specified",
|
||||
"default": null
|
||||
},
|
||||
"fixed": {
|
||||
"type": "boolean",
|
||||
"description": "Indicates if the column should have a fixed length",
|
||||
"default": false
|
||||
},
|
||||
"length": {
|
||||
"type": "number",
|
||||
"description": "Length of the field.",
|
||||
"default": null,
|
||||
"minimum": 0
|
||||
},
|
||||
"notnull": {
|
||||
"type": "boolean",
|
||||
"description": "Indicates whether the column is nullable or not",
|
||||
"default": true
|
||||
},
|
||||
"unsigned": {
|
||||
"type": "boolean",
|
||||
"description": "If the column should be an unsigned integer",
|
||||
"default": false
|
||||
},
|
||||
"scale": {
|
||||
"type": "number",
|
||||
"description": "Exact number of decimal digits to be stored in a decimal type column",
|
||||
"default": 0
|
||||
},
|
||||
"precision": {
|
||||
"type": "number",
|
||||
"description": "Precision of a decimal type column that determines the overall maximum number of digits to be stored (including scale)",
|
||||
"default": 10
|
||||
},
|
||||
"PlatformOptions": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CustomSchemaOptions": {
|
||||
"type": "object",
|
||||
"description": "Custom schema options",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"allowInfinite": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"doublePrecision": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enum_values": {
|
||||
"type": "array",
|
||||
"description": "Values to use with type 'mwenum'",
|
||||
"additionalItems": false,
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"uniqueItems": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"type",
|
||||
"options"
|
||||
]
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"type": "array",
|
||||
"additionalItems": false,
|
||||
"description": "Indexes",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Index name"
|
||||
},
|
||||
"comment": {
|
||||
"type": "string",
|
||||
"description": "Comment describing the index"
|
||||
},
|
||||
"columns": {
|
||||
"type": "array",
|
||||
"additionalItems": false,
|
||||
"description": "Columns used by the index",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"unique": {
|
||||
"type": "boolean",
|
||||
"description": "If the index is unique",
|
||||
"default": false
|
||||
},
|
||||
"flags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"fulltext",
|
||||
"spatial"
|
||||
]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"lengths": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": [
|
||||
"number",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"minItems": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"columns",
|
||||
"unique"
|
||||
]
|
||||
}
|
||||
},
|
||||
"pk": {
|
||||
"type": "array",
|
||||
"additionalItems": false,
|
||||
"description": "Array of column names used in the primary key",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"table_options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"columns",
|
||||
"indexes"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/schema#",
|
||||
"description": "MediaWiki abstract database schema schema",
|
||||
"type": "array",
|
||||
"additionalItems": false,
|
||||
"items": {
|
||||
"$ref": "abstract-schema-table.json"
|
||||
},
|
||||
"minItems": 1
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,118 @@
|
|||
ContentHandler {#contenthandler}
|
||||
=====
|
||||
|
||||
The *ContentHandler* facility adds support for arbitrary content types on wiki pages, instead of relying on wikitext for everything. It was introduced in MediaWiki 1.21.
|
||||
|
||||
Each kind of content ("content model") supported by MediaWiki is identified by unique name. The content model determines how a page's content is rendered, compared, stored, edited, and so on.
|
||||
|
||||
Built-in content types are:
|
||||
|
||||
* wikitext - wikitext, as usual
|
||||
* javascript - user provided javascript code
|
||||
* json - simple implementation for use by extensions, etc.
|
||||
* css - user provided css code
|
||||
* text - plain text
|
||||
|
||||
In PHP, use the corresponding `CONTENT_MODEL_XXX` constant.
|
||||
|
||||
A page's content model is available using the `Title::getContentModel()` method. A page's default model is determined by `ContentHandler::getDefaultModelFor($title)` as follows:
|
||||
|
||||
* The global setting `$wgNamespaceContentModels` specifies a content model for the given namespace.
|
||||
* The hook `ContentHandlerDefaultModelFor` may be used to override the page's default model.
|
||||
* Pages in `NS_MEDIAWIKI` and `NS_USER` default to the CSS or JavaScript model if they end in .css or .js, respectively. Pages in `NS_MEDIAWIKI` default to the wikitext model otherwise.
|
||||
* Otherwise, the wikitext model is used.
|
||||
|
||||
Note that there is no guarantee that revisions of a page will all have the same content model. To find the content model of the slot of a revision, use `SlotRecord::getModel()` -
|
||||
the content model of the main slot can for now be assumed to be the content model for the overall revision.
|
||||
|
||||
## Architecture
|
||||
|
||||
Two class hierarchies are used to provide the functionality associated with the different content models:
|
||||
|
||||
* Content interface (and `AbstractContent` base class) define functionality that acts on the concrete content of a page, and
|
||||
* `ContentHandler` base class provides functionality specific to a content model, but not acting on concrete content.
|
||||
|
||||
The most important function of ContentHandler is to act as a factory for the appropriate implementation of Content. These `Content` objects are to be used by MediaWiki everywhere, instead of passing page content around as text. All manipulation and analysis of page content must be done via the appropriate methods of the Content object.
|
||||
|
||||
For each content model, a subclass of ContentHandler has to be registered with `$wgContentHandlers`. The ContentHandler object for a given content model can be obtained using `ContentHandler::getForModelID( $id )`. Also `Title` and `WikiPage` now have `getContentHandler()` methods for convenience.
|
||||
|
||||
`ContentHandler` objects are singletons that provide functionality specific to the content type, but not directly acting on the content of some page. `ContentHandler::makeEmptyContent()` and `ContentHandler::unserializeContent()` can be used to create a Content object of the appropriate type. However, it is recommended to instead use `WikiPage::getContent()` resp. `RevisionRecord::getContent()` to get a page's content as a Content object. These two methods should be the ONLY way in which page content is accessed.
|
||||
For `WikiPage::getContent()` the content of the main slot is returned, other slots can be retrieved by using `RevisionRecord::getContent()` and specifying the slot.
|
||||
|
||||
Another important function of ContentHandler objects is to define custom action handlers for a content model, see `ContentHandler::getActionOverrides()`. This is similar to what `WikiPage::getActionOverrides()` was already doing.
|
||||
|
||||
## Serialization
|
||||
|
||||
With the ContentHandler facility, page content no longer has to be text based. Objects implementing the Content interface are used to represent and handle the content internally. For storage and data exchange, each content model supports at least one serialization format via `ContentHandler::serializeContent( $content )`. The list of supported formats for a given content model can be accessed using `ContentHandler::getSupportedFormats()`.
|
||||
|
||||
Content serialization formats are identified using MIME type like strings. The following formats are built in:
|
||||
|
||||
* text/x-wiki - wikitext
|
||||
* text/javascript - for js pages
|
||||
* text/css - for css pages
|
||||
* text/plain - for future use, e.g. with plain text messages.
|
||||
* text/html - for future use, e.g. with plain html messages.
|
||||
* application/vnd.php.serialized - for future use with the api and for extensions
|
||||
* application/json - for future use with the api, and for use by extensions
|
||||
* application/xml - for future use with the api, and for use by extensions
|
||||
|
||||
In PHP, use the corresponding `CONTENT_FORMAT_XXX` constant.
|
||||
|
||||
Note that when using the API to access page content, especially `action=edit`, `action=parse` and `action=query&prop=revisions`, the model and format of the content should always be handled explicitly. Without that information, interpretation of the provided content is not reliable. The same applies to XML dumps generated via `maintenance/dumpBackup.php` or `Special:Export`.
|
||||
|
||||
Also note that the API will provide encapsulated, serialized content - so if the API was called with `format=json`, and contentformat is also json (or rather, application/json), the page content is represented as a string containing an escaped json structure. Extensions that use JSON to serialize some types of page content may provide specialized API modules that allow access to that content in a more natural form.
|
||||
|
||||
## Compatibility
|
||||
|
||||
The ContentHandler facility is introduced in a way that should allow all existing code to keep functioning at least for pages that contain wikitext or other text based content. However, a number of functions and hooks have been deprecated in favor of new versions that are aware of the page's content model, and will now generate warnings when used.
|
||||
|
||||
Most importantly, the following functions have been deprecated:
|
||||
|
||||
* `Revision::getText()` was deprecated in favor of `Revision::getContent()` (though the Revision class was later fully removed as part of the migration to Multi-Content Revisions (MCR), see [documentation of mediawiki.org][mediawiki.org/wiki/Multi-Content_Revisions].
|
||||
* `WikiPage::getText()` is deprecated in favor of `WikiPage::getContent()`
|
||||
|
||||
Also, the old `Article::getContent()` (which returns text) is superceded by `Article::getContentObject()`. However, both methods should be avoided since they do not provide clean access to the page's actual content. For instance, they may return a system message for non-existing pages. Use `WikiPage::getContent()` instead.
|
||||
|
||||
Code that relies on a textual representation of the page content should eventually be rewritten. However, `ContentHandler::getContentText()` provides a stop-gap that can be used to get text for a page. It will return the text for text based content, and null for any other content.
|
||||
|
||||
For rendering page content, `Content::getParserOutput()` should be used instead of accessing the parser directly. `WikiPage::makeParserOptions()` can be used to construct appropriate options.
|
||||
|
||||
Besides some functions, some hooks have also been replaced by new versions (see hooks.txt for details). These hooks will now trigger a warning when used:
|
||||
|
||||
* `ArticleAfterFetchContent` was replaced by `ArticleAfterFetchContentObject`, later replaced by `ArticleRevisionViewCustom`
|
||||
* `ArticleInsertComplete` was replaced by `PageContentInsertComplete`, later replaced by `PageSaveComplete`
|
||||
* `ArticleSave` was replaced by `PageContentSave`
|
||||
* `ArticleSaveComplete` was replaced by `PageContentSaveComplete`, later replaced by `PageSaveComplete`
|
||||
* `ArticleViewCustom` was replaced by `ArticleContentViewCustom`, which was later removed entirely
|
||||
* `EditFilterMerged` was replaced by `EditFilterMergedContent`
|
||||
* `EditPageGetDiffText` was replaced by `EditPageGetDiffContent`
|
||||
* `EditPageGetPreviewText` was replaced by `EditPageGetPreviewContent`
|
||||
* `ShowRawCssJs` was deprecated in favor of custom rendering implemented in the respective ContentHandler object.
|
||||
|
||||
## Database Storage
|
||||
|
||||
Page content is stored in the database using the same mechanism as before. Non-text content is serialized first.
|
||||
|
||||
Each revision's content model and serialization format is stored in the revision table (resp. in the archive table, if the revision was deleted). The page's (current) content model (that is, the content model of the latest revision) is also stored in the page table.
|
||||
|
||||
Note however that the content model and format is only stored if it differs from the page's default, as determined by `ContentHandler::getDefaultModelFor( $title )`. The default values are represented as `NULL` in the database, to preserve space.
|
||||
|
||||
## Globals
|
||||
|
||||
There are some new globals that can be used to control the behavior of the ContentHandler facility:
|
||||
|
||||
* `$wgContentHandlers` associates content model IDs with the names of the appropriate ContentHandler subclasses or callbacks that create an instance of the appropriate ContentHandler subclass.
|
||||
|
||||
* `$wgNamespaceContentModels` maps namespace IDs to a content model that should be the default for that namespace.
|
||||
|
||||
## Caveats
|
||||
|
||||
There are some changes in behavior that might be surprising to users:
|
||||
|
||||
* Javascript and CSS pages are no longer parsed as wikitext (though pre-save transform is still applied). Most importantly, this means that links, including categorization links, contained in the code will not work.
|
||||
|
||||
* `action=edit` will fail for pages with non-text content, unless the respective ContentHandler implementation has provided a specialized handler for the edit action. This is true for the API as well.
|
||||
|
||||
* `action=raw` will fail for all non-text content. This seems better than serving content in other formats to an unsuspecting recipient. This will also cause client-side diffs to fail.
|
||||
|
||||
* File pages provide their own action overrides that do not combine gracefully with any custom handlers defined by a ContentHandler. If for example a File page used a content model with a custom revert action, this would be overridden by WikiFilePage's handler for the revert action.
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
Database Access {#database}
|
||||
=====
|
||||
|
||||
*Some information about database access in MediaWiki. By Tim Starling, January 2006.*
|
||||
|
||||
## Database Layout
|
||||
|
||||
For information about the MediaWiki database layout, such as a description of the tables and their contents, please see:
|
||||
|
||||
* [The manual](https://www.mediawiki.org/wiki/Manual:Database_layout)
|
||||
* [Abstract schema of MediaWiki core](https://gerrit.wikimedia.org/g/mediawiki/core/+/refs/heads/master/maintenance/tables.json)
|
||||
* [MySQL schema (automatically generated)](https://gerrit.wikimedia.org/g/mediawiki/core/+/refs/heads/master/maintenance/tables-generated.sql)
|
||||
|
||||
|
||||
## API
|
||||
|
||||
To make a read query, something like this usually suffices:
|
||||
|
||||
```php
|
||||
use MediaWiki\MediaWikiServices;
|
||||
$dbProvider = MediaWikiServices::getInstance()->getConnectionProvider();
|
||||
...
|
||||
$dbr = $dbProvider->getReplicaDatabase();
|
||||
$res = $dbr->newSelectQueryBuilder()
|
||||
->select( /* ... see docs... */ )
|
||||
// ...see docs for other methods...
|
||||
->fetchResultSet();
|
||||
|
||||
foreach( $res as $row ) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
For a write query, use something like:
|
||||
```php
|
||||
$dbw = $dbProvider->getPrimaryDatabase();
|
||||
$dbw->newInsertQueryBuilder()
|
||||
->insertInto( /* ...see docs... */ )
|
||||
// ...see docs for other methods...
|
||||
->execute();
|
||||
```
|
||||
We use the convention `$dbr` for read and `$dbw` for write to help you keep track of whether the database object is a replica (read-only) or a primary (read/write). If you write to a replica, the world will explode. Or to be precise, a subsequent write query which succeeded on the primary may fail when propagated to the replica due to a unique key collision. Replication will then stop and it may take hours to repair the database and get it back online. Setting `read_only` in `my.cnf` on the replica will avoid this scenario, but given the dire consequences, we prefer to have as many checks as possible.
|
||||
|
||||
We provide a `query()` function for raw SQL, but the query builders like `SelectQueryBuilder` and `InsertQueryBuilder` are usually more convenient. They take care of things like table prefixes and escaping for you. If you really need to make your own SQL, please read the documentation for `tableName()` and `addQuotes()`. You will need both of them.
|
||||
|
||||
|
||||
## Basic query optimisation
|
||||
|
||||
MediaWiki developers who need to write DB queries should have some understanding of databases and the performance issues associated with them. Patches containing unacceptably slow features will not be accepted. Unindexed queries are generally not welcome in MediaWiki, except in special pages derived from `QueryPage`. It's a common pitfall for new developers to submit code containing SQL queries which examine huge numbers of rows. Remember that `COUNT(*)` is **O(N)**, counting rows in a table is like counting beans in a bucket.
|
||||
|
||||
## Replication
|
||||
|
||||
The largest installation of MediaWiki, Wikimedia, uses a large set of replica MySQL servers replicating writes made to a primary MySQL server. It is important to understand the issues associated with this setup if you want to write code destined for Wikipedia.
|
||||
|
||||
It's often the case that the best algorithm to use for a given task depends on whether or not replication is in use. Due to our unabashed Wikipedia-centrism, we often just use the replication-friendly version, but if you like, you can use `LoadBalancer::getServerCount() > 1` to check to see if replication is in use.
|
||||
|
||||
## Lag
|
||||
|
||||
Lag primarily occurs when large write queries are sent to the primary. Writes are executed in parallel on the primary, but they are executed serially when replicated to the replicas. The primary database may not write its query to the binlog for replication, until after the transaction is committed. The replicas poll this binlog, and apply the query locally as soon as it appears there. They can respond to reads while they are applying the replicated writes, but will not read anything more from the binlog and thus will perform no more writes. This means that if the write query runs for a long time, the replicas will lag behind the primary for as long as it takes for the write query to complete.
|
||||
|
||||
Lag can be exacerbated by high read load. MediaWiki's LoadBalancer will avoid sending reads to a replica lagged by more than a few seconds.
|
||||
|
||||
MediaWiki does its best for multiple queries during a given web request to represent a single consistent snapshot of the database at a given point in time. In addition to this, MediaWiki tries to ensure that a user sees the wiki change in chronological order, such as subsequent web requests see the same or newer data. In particular, it tries to ensure that the user's own actions are immediately reflected in subsequent requests. This is done by saving the primary's binlog position after a database write, and during subsequent connections to a replica it will wait as-needed to catch up to that position before sending any read queries.
|
||||
|
||||
If the wait for chronology protection times out, or more generally if a queried replica is lagged by more than 6 seconds (`LoadBalancer::MAX_LAG_DEFAULT`, configurable via `max lag` in `$wgLBFactoryConf`), the MediaWiki request is considered to be in "lagged replica mode" (`ILBFactory::laggedReplicaUsed`). In this mode, MediaWiki automatically shortens the expiry of object caching (via WANObjectCache) and HTTP/CDN caching to ensure that any stale data will soon converge.
|
||||
|
||||
## Lag avoidance
|
||||
|
||||
To avoid excessive lag, queries which write large numbers of rows should be split up, generally to write one row at a time. Multi-row `INSERT ... SELECT` queries are the worst offenders should be avoided altogether. Instead do the select first and then the insert.
|
||||
|
||||
## Working with lag
|
||||
|
||||
Despite our best efforts, it's not practical to guarantee a low-lag environment. Lag will usually be less than one second, but may occasionally be up to 30 seconds. For scalability, it's very important to keep load on the primary low, so simply sending all your queries to the primary is not the answer. So when you have a genuine need for up-to-date data, the following approach is advised:
|
||||
|
||||
1) Do a quick query to the primary for a sequence number or timestamp
|
||||
2) Run the full query on the replica and check if it matches the data you got
|
||||
from the primary
|
||||
3) If it doesn't, run the full query on the primary
|
||||
|
||||
To avoid swamping the primary every time the replicas lag, use of this approach should be kept to a minimum. In most cases you should just read from the replica and let the user deal with the delay.
|
||||
|
||||
## Lock contention
|
||||
|
||||
Due to the high write rate on Wikipedia (and some other wikis), MediaWiki developers need to be very careful to structure their writes to avoid long-lasting locks. By default, MediaWiki opens a transaction at the first query, and commits it before the output is sent. Locks will be held from the time when the query is done until the commit. So you can reduce lock time by doing as much processing as possible before you do your write queries.
|
||||
|
||||
Often this approach is not good enough, and it becomes necessary to enclose small groups of queries in their own transaction. Use the following syntax:
|
||||
|
||||
```php
|
||||
$dbw = $dbProvider->getPrimaryDatabase();
|
||||
$dbw->begin( __METHOD__ );
|
||||
/* Do queries */
|
||||
$dbw->commit( __METHOD__ );
|
||||
```
|
||||
|
||||
Use of locking reads (e.g. the `FOR UPDATE` clause) is not advised. They are poorly implemented in InnoDB and will cause regular deadlock errors. It's also surprisingly easy to cripple the wiki with lock contention.
|
||||
|
||||
Instead of locking reads, combine your existence checks into your write queries, by using an appropriate condition in the `WHERE` clause of an `UPDATE`, or by using unique indexes in combination with `INSERT IGNORE`. Then use the affected row count to see if the query succeeded.
|
||||
|
||||
## Query groups
|
||||
|
||||
MediaWiki supports database query groups, a way to indicate a preferred group of database hosts to use for a given query. Query groups are only supported for connections to child (non-primary) databases, making them only viable for read operations. It should be noted that using query groups does not _guarantee_ a given group of hosts will be used, but rather that the query prefers such group. Making use of query groups can be beneficial in many cases.
|
||||
|
||||
One benefit is a reduction of cache misses. Directing reads for a category of queries (e.g. all logging queries) to a given host can result in more deterministic and faster performing queries.
|
||||
|
||||
Another benefit is that it allows high-traffic wikis to configure some of their database hosts to handle some types of queries more optimally than others. For example, optimizing with different table indices for faster performance.
|
||||
|
||||
Query groups are especially beneficial for queries expected to have a long execution time. Such queries can exhaust a database of its resources (e.g. cache space and I/O time), so targeting a specific group of hosts prevents more urgent queries from suffering a performance decrease.
|
||||
|
||||
Additionally, expensive queries can delay database maintenance operations which may increase latency for other queries.
|
||||
For example, while a database read is executing, if other queries have performed updates to any tables those tables must retain all stale versions of its rows until the read is complete. Now, other potentially unrelated queries must now spend additional time scanning over obsolete rows that are waiting to be purged. Directing these long running queries to dedicated hosts helps prevent other queries in suffering a performance hit.
|
||||
|
||||
MediaWiki currently supports the following query groups:
|
||||
|
||||
* `api`: For queries specific to api.php requests. This is set via ApiBase::getDB(). Note that most queries from api.php are performed via re-used service classes that are not specific to api.php, and thus don't use this query group.
|
||||
|
||||
* `dump`: For dump-related CLI maintenance scripts (also known as "export" or "snapshot"). These scripts set the query group at the process level, and thus affect all queries, including fast/general ones.
|
||||
|
||||
* `vslow`: For queries that are expected to have a long execution time (e.g. more than one second when run against the largest wiki). These tend to be unoptimized queries that are unable to use an index, and thus get slower the more rows a table contains instead of staying relatively constant. These should be limited to jobs and maintenance scripts, or guarded by `$wgMiserMode`.
|
||||
|
||||
The below is how you specify a query group when obtaining a connection:
|
||||
|
||||
```php
|
||||
$dbProvider = MediaWikiServices::getInstance()->getConnectionProvider();
|
||||
$dbProvider->getReplicaDatabase( false, 'vslow' );
|
||||
```
|
||||
|
||||
## Supported DBMSs
|
||||
|
||||
MediaWiki is written primarily for use with MySQL. Queries are optimized for it and its schema is considered the canonical version. However, MediaWiki does support the following other DBMSs to varying degrees:
|
||||
|
||||
* PostgreSQL
|
||||
* SQLite
|
||||
|
||||
More information can be found about each of these databases (known issues, level of support, extra configuration) in the `databases` subdirectory in this folder.
|
||||
|
||||
## Use of `GROUP BY`
|
||||
|
||||
MySQL supports `GROUP BY` without checking anything in the `SELECT` clause. Other DBMSs (especially Postgres) are stricter and require that all the non-aggregate items in the `SELECT` clause appear in the `GROUP BY`. For this reason, it is highly discouraged to use `SELECT *` with `GROUP BY` queries.
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
This document describes the state of Postgres support in MediaWiki.
|
||||
|
||||
== Overview ==
|
||||
|
||||
Support for PostgreSQL has been available since version 1.7
|
||||
of MediaWiki, and is fairly well maintained. The main code
|
||||
is very well integrated, while extensions are very hit and miss.
|
||||
Still, it is probably the most supported database after MySQL.
|
||||
Much of the work in making MediaWiki database-agnostic came
|
||||
about through the work of creating Postgres support.
|
||||
|
||||
== Required versions ==
|
||||
|
||||
The current minimum version of PostgreSQL for MediaWiki is 10.
|
||||
|
||||
== Database schema ==
|
||||
|
||||
PostgreSQL schema is automatically generated from the abstract schema.
|
||||
You can see the generated schema in maintenance/postgres/tables-generated.sql
|
||||
|
||||
For more information on abstract schema see:
|
||||
https://www.mediawiki.org/wiki/Manual:Schema_changes
|
||||
|
||||
== MySQL differences ==
|
||||
|
||||
The major differences between MySQL and Postgres are represented as
|
||||
methods in the Database class. For example, implicitGroupby() is
|
||||
true for MySQL and false for Postgres. This means that in those
|
||||
places where the code does not add all the non-aggregate items
|
||||
from the SELECT clause to the GROUP BY, we can add them in, but in
|
||||
a conditional manner with the above method, as simply adding them
|
||||
all in to the main query may cause performance problems with
|
||||
MySQL.
|
||||
|
||||
== Getting help ==
|
||||
|
||||
In addition to the normal venues (MediaWiki mailing lists
|
||||
and IRC channels), the #postgresql channel on irc.libera.chat
|
||||
is a friendly and expert resource if you should encounter a
|
||||
problem with your Postgres-enabled MediaWiki.
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
SQLite schema is automatically generated from the abstract schema.
|
||||
You can see the generated schema in maintenance/sqlite/tables-generated.sql
|
||||
|
||||
For more information on abstract schema see:
|
||||
https://www.mediawiki.org/wiki/Manual:Schema_changes
|
||||
|
||||
SQLite in MediaWiki also accepts MySQL and there are a set of compatibility
|
||||
regexes to convert MySQL syntax to SQLite syntax:
|
||||
|
||||
* BINARY() and VARBINARY() fields are converted to BLOB
|
||||
* the UNSIGNED modifier is removed
|
||||
* "INT" fields are converted to "INTEGER"
|
||||
* ENUM is converted to BLOB
|
||||
* the BINARY collation modifier is removed
|
||||
* AUTO_INCREMENT is converted to AUTOINCREMENT
|
||||
* Any table options are removed
|
||||
* Truncated indexes are upgraded to full-width indexes
|
||||
* FULLTEXT indexes are converted to ordinary indexes
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
deferred.txt
|
||||
|
||||
A few of the database updates required by various functions here can be
|
||||
deferred until after the result page is displayed to the user. For example,
|
||||
updating the view counts, updating the linked-to tables after a save, etc. PHP
|
||||
does not yet have any way to tell the server to actually return and disconnect
|
||||
while still running these updates (as a Java servlet could), but it might have
|
||||
such a feature in the future.
|
||||
|
||||
We handle these by creating a deferred-update object and putting those objects
|
||||
on a global list, then executing the whole list after the page is displayed. We
|
||||
don't do anything smart like collating updates to the same table or such
|
||||
because the list is almost always going to have just one item on it, if that,
|
||||
so it's not worth the trouble.
|
||||
|
||||
Since 1.6 there is a 'job queue' in the jobs table, which is used to update
|
||||
link tables of transcluding pages after edits; this may be extended in the
|
||||
future to more general background tasks.
|
||||
|
||||
Job queue items are fetched out of the queue and run either at a random rate
|
||||
during regular page views (by default) or by a batch process which can be run
|
||||
via maintenance/runJobs.php.
|
||||
|
||||
Currently there are a few different types of jobs:
|
||||
|
||||
refreshLinks
|
||||
Used to refresh the database tables that store the links between pages.
|
||||
When a page is changed, all pages using that page are also cleared by
|
||||
inserting a new job for all those pages. Each job refreshes only one page.
|
||||
|
||||
htmlCacheUpdate
|
||||
Clear caches when a template is changed to ensure that changes can be seen.
|
||||
Each job clears $wgUpdateRowsPerJob pages (300 by default).
|
||||
|
||||
enotifNotify
|
||||
Used to send mail using the job queue.
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
This document is intended to provide useful advice for parties seeking to
|
||||
redistribute MediaWiki to end users. It's targeted particularly at maintainers
|
||||
for Linux distributions, since it's been observed that distribution packages of
|
||||
MediaWiki often break. We've consistently had to recommend that users seeking
|
||||
support use official tarballs instead of their distribution's packages, and
|
||||
this often solves whatever problem the user is having. It would be nice if
|
||||
this could change.
|
||||
|
||||
== Background: why web applications are different ==
|
||||
|
||||
MediaWiki is intended to be usable on any web host that provides support for
|
||||
PHP and a database. Many users of low-end shared hosting have very limited
|
||||
access to their machine: often only FTP access to some subdirectory of the web
|
||||
root. Support for these users entails several restrictions, such as:
|
||||
|
||||
1) We cannot require installation of any files outside the web root. Few of
|
||||
our users have access to directories like /usr or /etc.
|
||||
2) We cannot require the ability to run any utility on the command line.
|
||||
Many shared hosts have exec() and similar PHP functions disabled.
|
||||
3) We cannot assume that the software has write access anywhere useful. The
|
||||
user account that MediaWiki (including its installer) runs under is often
|
||||
different from the account the user used to upload the files, and we might be
|
||||
restricted by PHP settings such as safe mode or open_basedir.
|
||||
4) We cannot assume that the software even has read access anywhere useful.
|
||||
Many shared hosts run all users' web applications under the same user, so
|
||||
they can't rely on Unix permissions, and must forbid reads to even standard
|
||||
directories like /tmp lest users read each others' files.
|
||||
5) We cannot assume that the user has the ability to install or run any
|
||||
programs not written as web-accessible PHP scripts.
|
||||
|
||||
Since anything that works on cheap shared hosting will work if you have shell
|
||||
or root access too, MediaWiki's design is based around catering to the lowest
|
||||
common denominator. Although we support higher-end setups as well (like
|
||||
Wikipedia!), the way many things work by default is tailored toward shared
|
||||
hosting. These defaults are unconventional from the point of view of normal
|
||||
(non-web) applications -- they might conflict with distributors' policies, and
|
||||
they certainly aren't ideal for someone who's installing MediaWiki as root.
|
||||
|
||||
== Directory structure ==
|
||||
|
||||
Because of constraint (1) above, MediaWiki does not conform to normal
|
||||
Unix filesystem layout. Hopefully we'll offer direct support for standard
|
||||
layouts in the future, but for now *any change to the location of files is
|
||||
unsupported*. Moving things and leaving symlinks will *probably* not break
|
||||
anything, but it is *strongly* advised not to try any more intrusive changes to
|
||||
get MediaWiki to conform more closely to your filesystem hierarchy. Any such
|
||||
attempt will almost certainly result in unnecessary bugs.
|
||||
|
||||
The standard recommended location to install MediaWiki, relative to the web
|
||||
root, is /w (so, e.g., /var/www/w). Rewrite rules can then be used to enable
|
||||
"pretty URLs" like /wiki/Article instead of /w/index.php?title=Article. (This
|
||||
is the convention Wikipedia uses.) In theory, it should be possible to enable
|
||||
the appropriate rewrite rules by default, if you can reconfigure the web
|
||||
server, but you'd need to alter LocalSettings.php too. See
|
||||
<https://www.mediawiki.org/wiki/Manual:Short_URL> for details on short URLs.
|
||||
|
||||
If you really must mess around with the directory structure, note that the
|
||||
following files *must* all be web-accessible for MediaWiki to function
|
||||
correctly:
|
||||
|
||||
* api.php, img_auth.php, index.php, load.php, opensearch_desc.php, thumb.php.
|
||||
These are the entry points for normal usage. This list may be
|
||||
incomplete and is subject to change.
|
||||
* mw-config/index.php: Used for web-based installation (sets up the database,
|
||||
prompts for the name of the wiki, etc.).
|
||||
* images/: Used for uploaded files. This could be somewhere else if
|
||||
$wgUploadDirectory and $wgUploadPath are changed appropriately.
|
||||
* skins/*/: Subdirectories of skins/ contain CSS and JavaScript files that
|
||||
must be accessible to web browsers. The PHP files and Skin.sample in skins/
|
||||
don't need to be accessible. This could be somewhere else if
|
||||
$wgStyleDirectory and $wgStylePath are changed appropriately.
|
||||
* extensions/: Many extensions include CSS and JavaScript files in their
|
||||
extensions directory, and will break if they aren't web-accessible. Some
|
||||
extensions might theoretically provide additional entry points as well, at
|
||||
least in principle.
|
||||
|
||||
But all files should keep their position relative to the web-visible
|
||||
installation directory no matter what. If you must move includes/ somewhere in
|
||||
/usr/share, provide a symlink from /var/www/w. If you don't, you *will* break
|
||||
something. You have been warned.
|
||||
|
||||
== Configuration ==
|
||||
|
||||
MediaWiki is configured using LocalSettings.php. This is a PHP file that's
|
||||
generated when the user visits mw-config/index.php to install the software, and
|
||||
which the user can edit by hand thereafter. It's just a plain old PHP file,
|
||||
and can contain any PHP statements. It usually sets global variables that are
|
||||
used for configuration, and includes files used by any extensions.
|
||||
|
||||
Distributors can easily change the default settings by creating
|
||||
includes/PlatformSettings.php with overrides/additions to the default settings.
|
||||
The installer will automatically include the platform defaults when generating
|
||||
the user's LocalSettings.php file.
|
||||
|
||||
Furthermore, distributors can change the installer behavior, by placing their
|
||||
overrides into mw-config/overrides directory. Doing that is highly preferred
|
||||
to modifying MediaWiki code directly. See mw-config/overrides/README for more
|
||||
details and examples.
|
||||
|
||||
There's a new maintenance/install.php script which could be used for performing
|
||||
an install through the command line.
|
||||
|
||||
Some configuration options that distributors might be in a position to set
|
||||
intelligently:
|
||||
|
||||
* $wgEmergencyContact: An e-mail address that can be used to contact the wiki
|
||||
administrator. By default, "wikiadmin@ServerName".
|
||||
* $wgPasswordSender: The e-mail address to use when sending password e-mails.
|
||||
By default, "MediaWiki Mail <apache@ServerName>".
|
||||
(with ServerName guessed from the http request)
|
||||
* $wgSMTP: Can be configured to use SMTP for mail sending instead of PHP
|
||||
mail().
|
||||
|
||||
== Updates ==
|
||||
|
||||
The correct way for updating a wiki is to update the files and then run from
|
||||
command line the maintenance/update.php script (with appropriate parameters if
|
||||
files were moved). It will perform all the needed steps to update the database
|
||||
schema and contents to the version from whatever old one it has.
|
||||
Any package manager which replaces the files but doesn't update the db is leaving
|
||||
an inconsistent wiki that may produce blank pages (php errors) when new features
|
||||
using the changed schema would be used.
|
||||
|
||||
Since MediaWiki 1.17 it is possible to upgrade using the web installer by providing
|
||||
an arbitrary secret value stored as $wgUpgradeKey in LocalSettings (older versions
|
||||
needed to rename LocalSettings.php in order to upgrade using the installer).
|
||||
|
||||
== Documentation ==
|
||||
|
||||
MediaWiki's official documentation is split between two places: the source
|
||||
code, and <https://www.mediawiki.org/>. The source code documentation is written
|
||||
exclusively by developers, and so is likely to be reliable (at worst,
|
||||
outdated). However, it can be pretty sparse. mediawiki.org documentation is
|
||||
often much more thorough, but it's maintained by a wiki that's open to
|
||||
anonymous edits, so its quality is sometimes sketchy -- don't assume that
|
||||
anything there is officially endorsed!
|
||||
|
||||
== Upstream ==
|
||||
|
||||
MediaWiki is a project hosted and led by the Wikimedia Foundation, the
|
||||
not-for-profit charity that operates Wikipedia. Wikimedia employs the lead
|
||||
developer and several other paid developers, but commit access is given out
|
||||
liberally and there are multiple very active volunteer developers as well. A
|
||||
list of developers can be found at <https://www.mediawiki.org/wiki/Developers>.
|
||||
|
||||
MediaWiki's bug tracker is at <https://phabricator.wikimedia.org>. However, you
|
||||
might find that the best place to post if you want to get developers' attention
|
||||
is the wikitech-l mailing list
|
||||
<https://lists.wikimedia.org/postorius/lists/wikitech-l.lists.wikimedia.org/>.
|
||||
Posts to wikitech-l will inevitably be read by multiple experienced MediaWiki
|
||||
developers. There's also an active IRC chat at <irc://irc.libera.chat/mediawiki>,
|
||||
where there are usually several developers at reasonably busy times of day.
|
||||
|
||||
Our Git repositories are hosted at <https://gerrit.wikimedia.org>, see
|
||||
<https://www.mediawiki.org/wiki/Gerrit> for more information. Patches should
|
||||
be submitted there. If you know which developers are best suited to review your
|
||||
patch, add them to it, otherwise ask on IRC to get better review time.
|
||||
|
||||
All redistributors of MediaWiki should be subscribed to mediawiki-announce
|
||||
<https://lists.wikimedia.org/postorius/lists/mediawiki-announce.lists.wikimedia.org/>.
|
||||
It's extremely low-traffic, with an average of less than one post per month.
|
||||
All new releases are announced here, including critical security updates.
|
||||
|
||||
== Useful software to install ==
|
||||
|
||||
There are several other pieces of software that MediaWiki can make good use of.
|
||||
Distributors might choose to install these automatically with MediaWiki and
|
||||
perhaps configure it to use them (see Configuration section of this document):
|
||||
|
||||
* APC (Alternative PHP Cache) or similar: Will greatly speed up the
|
||||
execution of MediaWiki, and all other PHP applications, at some cost in
|
||||
memory usage. Will be used automatically for the most part.
|
||||
* clamav: Can be used for virus scanning of uploaded files. Enable with
|
||||
"$wgAntivirus = 'clamav';".
|
||||
* DjVuLibre: Allows processing of DjVu files. To enable this, set
|
||||
"$wgDjvuDump = 'djvudump'; $wgDjvuRenderer = 'ddjvu'; $wgDjvuTxt = 'djvutxt';".
|
||||
* ImageMagick: For resizing images. "$wgUseImageMagick = true;" will enable
|
||||
it. PHP's GD can also be used, but ImageMagick is preferable.
|
||||
* HTTP cache such as Varnish or Squid: can provide a drastic speedup and a
|
||||
major cut in resource consumption, but enabling it may interfere with other
|
||||
applications. It might be suitable for a separate package. For setup details, see:
|
||||
- <https://www.mediawiki.org/wiki/Manual:Varnish_caching>
|
||||
- <https://www.mediawiki.org/wiki/Manual:Squid_caching>
|
||||
* rsvg or other SVG rasterizer: ImageMagick can be used for SVG support, but
|
||||
is not ideal. Wikipedia (as of the time of this writing) uses rsvg. To
|
||||
enable, set "$wgSVGConverter = 'rsvg';" (or other as appropriate).
|
||||
|
||||
MediaWiki uses some standard GNU utilities as well, such as diff and diff3. If
|
||||
these are present in /usr/bin or some other reasonable location, they will be
|
||||
configured automatically on install.
|
||||
|
||||
MediaWiki also has a "job queue" that handles background processing. Because
|
||||
shared hosts often don't provide access to cron, the job queue is run on every
|
||||
page view by default. This means the background tasks aren't really done in
|
||||
the background. Busy wikis can set $wgJobRunRate to 0 and run
|
||||
maintenance/runJobs.php periodically out of cron. Distributors probably
|
||||
shouldn't set this up as a default, however, since the extra cron job is
|
||||
unnecessary overhead for a little-used wiki.
|
||||
|
||||
== Web server configuration ==
|
||||
|
||||
MediaWiki includes several .htaccess files to restrict access to some
|
||||
directories. If the web server is not configured to support these files, and
|
||||
the relevant directories haven't been moved someplace inaccessible anyway (e.g.
|
||||
symlinked in /usr/share with the web server configured to not follow symlinks),
|
||||
then it might be useful to deny web access to those directories in the web
|
||||
server's configuration.
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
output by MediaWiki's Special:Export system.
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
http://www.mediawiki.org/xml/export-0.1.xsd
|
||||
|
||||
Use the namespace:
|
||||
http://www.mediawiki.org/xml/export-0.1/
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mw="http://www.mediawiki.org/xml/export-0.1/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/export-0.1/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's page export format
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Need this to reference xml:lang -->
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="mediawiki" type="mw:MediaWikiType"/>
|
||||
|
||||
<complexType name="MediaWikiType">
|
||||
<sequence>
|
||||
<element name="page" type="mw:PageType"
|
||||
minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="required"/>
|
||||
<attribute ref="xml:lang" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="PageType">
|
||||
<sequence>
|
||||
<!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
|
||||
<element name="title" type="string"/>
|
||||
|
||||
<!-- optional page ID number -->
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
|
||||
<!-- comma-separated list of string tokens, if present -->
|
||||
<element name="restrictions" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- Zero or more sets of revision data -->
|
||||
<element name="revision" type="mw:RevisionType"
|
||||
minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RevisionType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="minor" minOccurs="0" />
|
||||
<element name="comment" type="string" minOccurs="0"/>
|
||||
<element name="text" type="string"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0"/>
|
||||
<element name="id" type="positiveInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
output by MediaWiki's Special:Export system.
|
||||
|
||||
Version 0.2 adds optional basic file upload info support,
|
||||
which is used by our OAI export/import submodule.
|
||||
|
||||
Version 0.3 adds some site configuration information such
|
||||
as a list of defined namespaces.
|
||||
|
||||
Version 0.4 adds per-revision delete flags, log exports,
|
||||
discussion threading data, a per-page redirect flag, and
|
||||
per-namespace capitalization.
|
||||
|
||||
Version 0.5 adds byte count per revision.
|
||||
|
||||
Version 0.6 adds a separate namespace tag, and resolves the
|
||||
redirect target and adds a separate sha1 tag for each revision.
|
||||
|
||||
Version 0.7 adds a unique identity constraint for both page and
|
||||
revision identifiers. See also bug 4220.
|
||||
Fix type for <ns> from "positiveInteger" to "nonNegativeInteger" to allow 0
|
||||
Moves <logitem> to its right location.
|
||||
Add parentid to revision.
|
||||
Fix type for <id> within <contributor> to "nonNegativeInteger"
|
||||
|
||||
Version 0.8 adds support for a <model> and a <format> tag for
|
||||
each revision. See contenthandler.md.
|
||||
|
||||
Version 0.9 adds the database name to the site information.
|
||||
|
||||
Version 0.10 moved the <model> and <format> tags before the <text> tag.
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
http://www.mediawiki.org/xml/export-0.10.xsd
|
||||
|
||||
Use the namespace:
|
||||
http://www.mediawiki.org/xml/export-0.10/
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mw="http://www.mediawiki.org/xml/export-0.10/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/export-0.10/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's page export format
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Need this to reference xml:lang -->
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd" />
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="mediawiki" type="mw:MediaWikiType">
|
||||
<!-- Page ID contraint, see bug 4220 -->
|
||||
<unique name="PageIDConstraint">
|
||||
<selector xpath="mw:page" />
|
||||
<field xpath="mw:id" />
|
||||
</unique>
|
||||
<!-- Revision ID contraint, see bug 4220 -->
|
||||
<unique name="RevIDConstraint">
|
||||
<selector xpath="mw:page/mw:revision" />
|
||||
<field xpath="mw:id" />
|
||||
</unique>
|
||||
</element>
|
||||
|
||||
<complexType name="MediaWikiType">
|
||||
<sequence>
|
||||
<element name="siteinfo" type="mw:SiteInfoType"
|
||||
minOccurs="0" maxOccurs="1" />
|
||||
<element name="page" type="mw:PageType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
<element name="logitem" type="mw:LogItemType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="required" />
|
||||
<attribute ref="xml:lang" use="required" />
|
||||
</complexType>
|
||||
|
||||
<complexType name="SiteInfoType">
|
||||
<sequence>
|
||||
<element name="sitename" type="string" minOccurs="0" />
|
||||
<element name="dbname" type="string" minOccurs="0" />
|
||||
<element name="base" type="anyURI" minOccurs="0" />
|
||||
<element name="generator" type="string" minOccurs="0" />
|
||||
<element name="case" type="mw:CaseType" minOccurs="0" />
|
||||
<element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="CaseType">
|
||||
<restriction base="NMTOKEN">
|
||||
<!-- Cannot have two titles differing only by case of first letter. -->
|
||||
<!-- Default behavior through 1.5, $wgCapitalLinks = true -->
|
||||
<enumeration value="first-letter" />
|
||||
|
||||
<!-- Complete title is case-sensitive -->
|
||||
<!-- Behavior when $wgCapitalLinks = false -->
|
||||
<enumeration value="case-sensitive" />
|
||||
|
||||
<!-- Cannot have non-case senstitive titles eg [[FOO]] == [[Foo]] -->
|
||||
<!-- Not yet implemented as of MediaWiki 1.18 -->
|
||||
<enumeration value="case-insensitive" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="DeletedFlagType">
|
||||
<restriction base="NMTOKEN">
|
||||
<enumeration value="deleted" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="NamespacesType">
|
||||
<sequence>
|
||||
<element name="namespace" type="mw:NamespaceType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="NamespaceType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="key" type="integer" />
|
||||
<attribute name="case" type="mw:CaseType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RedirectType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="title" type="string" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="ContentModelType">
|
||||
<restriction base="string">
|
||||
<pattern value="[a-zA-Z][-+./a-zA-Z0-9]*" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="ContentFormatType">
|
||||
<restriction base="string">
|
||||
<pattern value="[a-zA-Z][-+.a-zA-Z0-9]*/[a-zA-Z][-+.a-zA-Z0-9]*" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="PageType">
|
||||
<sequence>
|
||||
<!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
|
||||
<element name="title" type="string" />
|
||||
|
||||
<!-- Namespace in canonical form -->
|
||||
<element name="ns" type="nonNegativeInteger" />
|
||||
|
||||
<!-- optional page ID number -->
|
||||
<element name="id" type="positiveInteger" />
|
||||
|
||||
<!-- flag if the current revision is a redirect -->
|
||||
<element name="redirect" type="mw:RedirectType" minOccurs="0" maxOccurs="1" />
|
||||
|
||||
<!-- comma-separated list of string tokens, if present -->
|
||||
<element name="restrictions" type="string" minOccurs="0" />
|
||||
|
||||
<!-- Zero or more sets of revision or upload data -->
|
||||
<choice minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="revision" type="mw:RevisionType" />
|
||||
<element name="upload" type="mw:UploadType" />
|
||||
</choice>
|
||||
|
||||
<!-- Zero or One sets of discussion threading data -->
|
||||
<element name="discussionthreadinginfo" minOccurs="0" maxOccurs="1" type="mw:DiscussionThreadingInfo" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RevisionType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" />
|
||||
<element name="parentid" type="positiveInteger" minOccurs="0" />
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="minor" minOccurs="0" maxOccurs="1" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0" maxOccurs="1" />
|
||||
<element name="model" type="mw:ContentModelType" />
|
||||
<element name="format" type="mw:ContentFormatType" />
|
||||
<element name="text" type="mw:TextType" />
|
||||
<element name="sha1" type="string" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogItemType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" />
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0" />
|
||||
<element name="type" type="string" />
|
||||
<element name="action" type="string" />
|
||||
<element name="text" type="mw:LogTextType" minOccurs="0" maxOccurs="1" />
|
||||
<element name="logtitle" type="string" minOccurs="0" maxOccurs="1" />
|
||||
<element name="params" type="mw:LogParamsType" minOccurs="0" maxOccurs="1" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="CommentType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="TextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
<!-- This isn't a good idea; we should be using "ID" instead of "NMTOKEN" -->
|
||||
<!-- However, "NMTOKEN" is strictest definition that is both compatible with existing -->
|
||||
<!-- usage ([0-9]+) and with the "ID" type. -->
|
||||
<attribute name="id" use="optional" type="NMTOKEN" />
|
||||
<attribute name="bytes" use="optional" type="nonNegativeInteger" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogTextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogParamsType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0" />
|
||||
<element name="id" type="nonNegativeInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0" />
|
||||
</sequence>
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</complexType>
|
||||
|
||||
<complexType name="UploadType">
|
||||
<sequence>
|
||||
<!-- Revision-style data... -->
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="comment" type="string" minOccurs="0" />
|
||||
|
||||
<!-- Filename. (Using underscores, not spaces. No 'File:' namespace marker.) -->
|
||||
<element name="filename" type="string" />
|
||||
|
||||
<!-- URI at which this resource can be obtained -->
|
||||
<element name="src" type="anyURI" />
|
||||
|
||||
<element name="size" type="positiveInteger" />
|
||||
|
||||
<!-- TODO: add other metadata fields -->
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<!-- Discussion threading data for LiquidThreads -->
|
||||
<complexType name="DiscussionThreadingInfo">
|
||||
<sequence>
|
||||
<element name="ThreadSubject" type="string" />
|
||||
<element name="ThreadParent" type="positiveInteger" />
|
||||
<element name="ThreadAncestor" type="positiveInteger" />
|
||||
<element name="ThreadPage" type="string" />
|
||||
<element name="ThreadID" type="positiveInteger" />
|
||||
<element name="ThreadAuthor" type="string" />
|
||||
<element name="ThreadEditStatus" type="string" />
|
||||
<element name="ThreadType" type="string" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,336 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
output by MediaWiki's Special:Export system.
|
||||
|
||||
Version 0.2 adds optional basic file upload info support,
|
||||
which is used by our OAI export/import submodule.
|
||||
|
||||
Version 0.3 adds some site configuration information such
|
||||
as a list of defined namespaces.
|
||||
|
||||
Version 0.4 adds per-revision delete flags, log exports,
|
||||
discussion threading data, a per-page redirect flag, and
|
||||
per-namespace capitalization.
|
||||
|
||||
Version 0.5 adds byte count per revision.
|
||||
|
||||
Version 0.6 adds a separate namespace tag, and resolves the
|
||||
redirect target and adds a separate sha1 tag for each revision.
|
||||
|
||||
Version 0.7 adds a unique identity constraint for both page and
|
||||
revision identifiers. See also bug 4220.
|
||||
Fix type for <ns> from "positiveInteger" to "nonNegativeInteger" to allow 0
|
||||
Moves <logitem> to its right location.
|
||||
Add parentid to revision.
|
||||
Fix type for <id> within <contributor> to "nonNegativeInteger"
|
||||
|
||||
Version 0.8 adds support for a <model> and a <format> tag for
|
||||
each revision. See contenthandler.md.
|
||||
|
||||
Version 0.9 adds the database name to the site information.
|
||||
|
||||
Version 0.10 moved the <model> and <format> tags before the <text> tag.
|
||||
|
||||
Version 0.11 introduced <content> tag.
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
https://www.mediawiki.org/xml/export-0.11.xsd
|
||||
|
||||
Use the namespace:
|
||||
https://www.mediawiki.org/xml/export-0.11/
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mw="http://www.mediawiki.org/xml/export-0.11/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/export-0.11/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's page export format
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Need this to reference xml:lang -->
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd" />
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="mediawiki" type="mw:MediaWikiType">
|
||||
<!-- Page ID contraint, see bug 4220 -->
|
||||
<unique name="PageIDConstraint">
|
||||
<selector xpath="mw:page" />
|
||||
<field xpath="mw:id" />
|
||||
</unique>
|
||||
<!-- Revision ID contraint, see bug 4220 -->
|
||||
<unique name="RevIDConstraint">
|
||||
<selector xpath="mw:page/mw:revision" />
|
||||
<field xpath="mw:id" />
|
||||
</unique>
|
||||
</element>
|
||||
|
||||
<complexType name="MediaWikiType">
|
||||
<sequence>
|
||||
<element name="siteinfo" type="mw:SiteInfoType"
|
||||
minOccurs="0" maxOccurs="1" />
|
||||
<element name="page" type="mw:PageType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
<element name="logitem" type="mw:LogItemType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="required" />
|
||||
<attribute ref="xml:lang" use="required" />
|
||||
</complexType>
|
||||
|
||||
<complexType name="SiteInfoType">
|
||||
<sequence>
|
||||
<element name="sitename" type="string" minOccurs="0" />
|
||||
<element name="dbname" type="string" minOccurs="0" />
|
||||
<element name="base" type="anyURI" minOccurs="0" />
|
||||
<element name="generator" type="string" minOccurs="0" />
|
||||
<element name="case" type="mw:CaseType" minOccurs="0" />
|
||||
<element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="CaseType">
|
||||
<restriction base="NMTOKEN">
|
||||
<!-- Cannot have two titles differing only by case of first letter. -->
|
||||
<!-- Default behavior through 1.5, $wgCapitalLinks = true -->
|
||||
<enumeration value="first-letter" />
|
||||
|
||||
<!-- Complete title is case-sensitive -->
|
||||
<!-- Behavior when $wgCapitalLinks = false -->
|
||||
<enumeration value="case-sensitive" />
|
||||
|
||||
<!-- Cannot have non-case senstitive titles eg [[FOO]] == [[Foo]] -->
|
||||
<!-- Not yet implemented as of MediaWiki 1.18 -->
|
||||
<enumeration value="case-insensitive" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="DeletedFlagType">
|
||||
<restriction base="NMTOKEN">
|
||||
<enumeration value="deleted" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="NamespacesType">
|
||||
<sequence>
|
||||
<element name="namespace" type="mw:NamespaceType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="NamespaceType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="key" type="integer" />
|
||||
<attribute name="case" type="mw:CaseType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RedirectType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="title" type="string" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="ContentModelType">
|
||||
<restriction base="string">
|
||||
<pattern value="[a-zA-Z][-+./a-zA-Z0-9]*" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="ContentFormatType">
|
||||
<restriction base="string">
|
||||
<pattern value="[a-zA-Z][-+.a-zA-Z0-9]*/[a-zA-Z][-+.a-zA-Z0-9]*" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="PageType">
|
||||
<sequence>
|
||||
<!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
|
||||
<element name="title" type="string" />
|
||||
|
||||
<!-- Namespace in canonical form -->
|
||||
<element name="ns" type="nonNegativeInteger" />
|
||||
|
||||
<!-- optional page ID number -->
|
||||
<element name="id" type="positiveInteger" />
|
||||
|
||||
<!-- flag if the current revision is a redirect -->
|
||||
<element name="redirect" type="mw:RedirectType" minOccurs="0" maxOccurs="1" />
|
||||
|
||||
<!-- comma-separated list of string tokens, if present -->
|
||||
<element name="restrictions" type="string" minOccurs="0" />
|
||||
|
||||
<!-- Zero or more sets of revision or upload data -->
|
||||
<choice minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="revision" type="mw:RevisionType" />
|
||||
<element name="upload" type="mw:UploadType" />
|
||||
</choice>
|
||||
|
||||
<!-- Zero or One sets of discussion threading data -->
|
||||
<element name="discussionthreadinginfo" minOccurs="0" maxOccurs="1" type="mw:DiscussionThreadingInfo" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RevisionType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" />
|
||||
<element name="parentid" type="positiveInteger" minOccurs="0" maxOccurs="1" />
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="minor" minOccurs="0" maxOccurs="1" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0" maxOccurs="1" />
|
||||
<!-- corresponds to slot origin for the main slot -->
|
||||
<element name="origin" type="positiveInteger" />
|
||||
<!-- the main slot's content model -->
|
||||
<element name="model" type="mw:ContentModelType" />
|
||||
<!-- the main slot's serialization format -->
|
||||
<element name="format" type="mw:ContentFormatType" />
|
||||
<!-- the main slot's serialized content -->
|
||||
<element name="text" type="mw:TextType"/>
|
||||
<element name="content" type="mw:ContentType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<!-- sha1 of the revision, a combined sha1 of content in all slots -->
|
||||
<element name="sha1" type="string" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContentType">
|
||||
<sequence>
|
||||
<!-- corresponds to slot role_name -->
|
||||
<element name="role" type="mw:SlotRoleType" />
|
||||
<!-- corresponds to slot origin -->
|
||||
<element name="origin" type="positiveInteger" />
|
||||
<element name="model" type="mw:ContentModelType" />
|
||||
<element name="format" type="mw:ContentFormatType" />
|
||||
<element name="text" type="mw:ContentTextType" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="SlotRoleType">
|
||||
<restriction base="string">
|
||||
<pattern value="[a-zA-Z][-+./a-zA-Z0-9]*" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="ContentTextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" default="preserve" />
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" type="mw:DeletedFlagType" />
|
||||
<attribute name="location" type="anyURI" />
|
||||
<attribute name="sha1" type="string" />
|
||||
<attribute name="bytes" type="nonNegativeInteger" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogItemType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" />
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0" />
|
||||
<element name="type" type="string" />
|
||||
<element name="action" type="string" />
|
||||
<element name="text" type="mw:LogTextType" minOccurs="0" maxOccurs="1" />
|
||||
<element name="logtitle" type="string" minOccurs="0" maxOccurs="1" />
|
||||
<element name="params" type="mw:LogParamsType" minOccurs="0" maxOccurs="1" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="CommentType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" type="mw:DeletedFlagType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="TextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" default="preserve" />
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" type="mw:DeletedFlagType" />
|
||||
<!-- This isn't a good idea; we should be using "ID" instead of "NMTOKEN" -->
|
||||
<!-- However, "NMTOKEN" is strictest definition that is both compatible with existing -->
|
||||
<!-- usage ([0-9]+) and with the "ID" type. -->
|
||||
<attribute name="id" type="NMTOKEN" />
|
||||
<attribute name="location" type="anyURI" />
|
||||
<attribute name="sha1" type="string"/>
|
||||
<attribute name="bytes" type="nonNegativeInteger" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogTextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" type="mw:DeletedFlagType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogParamsType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" default="preserve" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0" />
|
||||
<element name="id" type="nonNegativeInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0" />
|
||||
</sequence>
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" type="mw:DeletedFlagType" />
|
||||
</complexType>
|
||||
|
||||
<complexType name="UploadType">
|
||||
<sequence>
|
||||
<!-- Revision-style data... -->
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="comment" type="string" minOccurs="0" />
|
||||
|
||||
<!-- Filename. (Using underscores, not spaces. No 'File:' namespace marker.) -->
|
||||
<element name="filename" type="string" />
|
||||
|
||||
<!-- URI at which this resource can be obtained -->
|
||||
<element name="src" type="anyURI" />
|
||||
|
||||
<element name="size" type="positiveInteger" />
|
||||
|
||||
<!-- TODO: add other metadata fields -->
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<!-- Discussion threading data for LiquidThreads -->
|
||||
<complexType name="DiscussionThreadingInfo">
|
||||
<sequence>
|
||||
<element name="ThreadSubject" type="string" />
|
||||
<element name="ThreadParent" type="positiveInteger" />
|
||||
<element name="ThreadAncestor" type="positiveInteger" />
|
||||
<element name="ThreadPage" type="string" />
|
||||
<element name="ThreadID" type="positiveInteger" />
|
||||
<element name="ThreadAuthor" type="string" />
|
||||
<element name="ThreadEditStatus" type="string" />
|
||||
<element name="ThreadType" type="string" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
output by MediaWiki's Special:Export system.
|
||||
|
||||
Version 0.2 adds optional basic file upload info support,
|
||||
which is used by our OAI export/import submodule.
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
http://www.mediawiki.org/xml/export-0.2.xsd
|
||||
|
||||
Use the namespace:
|
||||
http://www.mediawiki.org/xml/export-0.2/
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mw="http://www.mediawiki.org/xml/export-0.2/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/export-0.2/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's page export format
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Need this to reference xml:lang -->
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="mediawiki" type="mw:MediaWikiType"/>
|
||||
|
||||
<complexType name="MediaWikiType">
|
||||
<sequence>
|
||||
<element name="page" type="mw:PageType"
|
||||
minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="required"/>
|
||||
<attribute ref="xml:lang" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="PageType">
|
||||
<sequence>
|
||||
<!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
|
||||
<element name="title" type="string"/>
|
||||
|
||||
<!-- optional page ID number -->
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
|
||||
<!-- comma-separated list of string tokens, if present -->
|
||||
<element name="restrictions" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- Zero or more sets of revision or upload data -->
|
||||
<choice minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="revision" type="mw:RevisionType" />
|
||||
<element name="upload" type="mw:UploadType" />
|
||||
</choice>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RevisionType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="minor" minOccurs="0" />
|
||||
<element name="comment" type="string" minOccurs="0"/>
|
||||
<element name="text" type="string"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0"/>
|
||||
<element name="id" type="positiveInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="UploadType">
|
||||
<sequence>
|
||||
<!-- Revision-style data... -->
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="comment" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- Filename. (Using underscores, not spaces. No 'Image:' namespace marker.) -->
|
||||
<element name="filename" type="string"/>
|
||||
|
||||
<!-- URI at which this resource can be obtained -->
|
||||
<element name="src" type="anyURI"/>
|
||||
|
||||
<element name="size" type="positiveInteger" />
|
||||
|
||||
<!-- TODO: add other metadata fields -->
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
output by MediaWiki's Special:Export system.
|
||||
|
||||
Version 0.2 adds optional basic file upload info support,
|
||||
which is used by our OAI export/import submodule.
|
||||
|
||||
Version 0.3 adds some site configuration information such
|
||||
as a list of defined namespaces.
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
http://www.mediawiki.org/xml/export-0.3.xsd
|
||||
|
||||
Use the namespace:
|
||||
http://www.mediawiki.org/xml/export-0.3/
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mw="http://www.mediawiki.org/xml/export-0.3/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/export-0.3/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's page export format
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Need this to reference xml:lang -->
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="mediawiki" type="mw:MediaWikiType"/>
|
||||
|
||||
<complexType name="MediaWikiType">
|
||||
<sequence>
|
||||
<element name="siteinfo" type="mw:SiteInfoType"
|
||||
minOccurs="0" maxOccurs="1"/>
|
||||
<element name="page" type="mw:PageType"
|
||||
minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="required"/>
|
||||
<attribute ref="xml:lang" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="SiteInfoType">
|
||||
<sequence>
|
||||
<element name="sitename" type="string" minOccurs="0" />
|
||||
<element name="base" type="anyURI" minOccurs="0" />
|
||||
<element name="generator" type="string" minOccurs="0" />
|
||||
<element name="case" type="mw:CaseType" minOccurs="0" />
|
||||
<element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="CaseType">
|
||||
<restriction base="NMTOKEN">
|
||||
<!-- Cannot have two titles differing only by case of first letter. -->
|
||||
<!-- Default behavior through 1.5, $wgCapitalLinks = true -->
|
||||
<enumeration value="first-letter" />
|
||||
|
||||
<!-- Complete title is case-sensitive -->
|
||||
<!-- Behavior when $wgCapitalLinks = false -->
|
||||
<enumeration value="case-sensitive" />
|
||||
|
||||
<!-- Cannot have two titles differing only by case. -->
|
||||
<!-- Not yet implemented as of MediaWiki 1.5 -->
|
||||
<enumeration value="case-insensitive" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="NamespacesType">
|
||||
<sequence>
|
||||
<element name="namespace" type="mw:NamespaceType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="NamespaceType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="key" type="integer" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="PageType">
|
||||
<sequence>
|
||||
<!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
|
||||
<element name="title" type="string"/>
|
||||
|
||||
<!-- optional page ID number -->
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
|
||||
<!-- comma-separated list of string tokens, if present -->
|
||||
<element name="restrictions" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- Zero or more sets of revision or upload data -->
|
||||
<choice minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="revision" type="mw:RevisionType" />
|
||||
<element name="upload" type="mw:UploadType" />
|
||||
</choice>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RevisionType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="minor" minOccurs="0" />
|
||||
<element name="comment" type="string" minOccurs="0"/>
|
||||
<element name="text" type="mw:TextType" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="TextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0"/>
|
||||
<element name="id" type="positiveInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="UploadType">
|
||||
<sequence>
|
||||
<!-- Revision-style data... -->
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="comment" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- Filename. (Using underscores, not spaces. No 'Image:' namespace marker.) -->
|
||||
<element name="filename" type="string"/>
|
||||
|
||||
<!-- URI at which this resource can be obtained -->
|
||||
<element name="src" type="anyURI"/>
|
||||
|
||||
<element name="size" type="positiveInteger" />
|
||||
|
||||
<!-- TODO: add other metadata fields -->
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
output by MediaWiki's Special:Export system.
|
||||
|
||||
Version 0.2 adds optional basic file upload info support,
|
||||
which is used by our OAI export/import submodule.
|
||||
|
||||
Version 0.3 adds some site configuration information such
|
||||
as a list of defined namespaces.
|
||||
|
||||
Version 0.4 adds per-revision delete flags, log exports,
|
||||
discussion threading data, a per-page redirect flag, and
|
||||
per-namespace capitalization.
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
http://www.mediawiki.org/xml/export-0.4.xsd
|
||||
|
||||
Use the namespace:
|
||||
http://www.mediawiki.org/xml/export-0.4/
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mw="http://www.mediawiki.org/xml/export-0.4/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/export-0.4/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's page export format
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Need this to reference xml:lang -->
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="mediawiki" type="mw:MediaWikiType"/>
|
||||
|
||||
<complexType name="MediaWikiType">
|
||||
<sequence>
|
||||
<element name="siteinfo" type="mw:SiteInfoType"
|
||||
minOccurs="0" maxOccurs="1"/>
|
||||
<element name="page" type="mw:PageType"
|
||||
minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="required"/>
|
||||
<attribute ref="xml:lang" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="SiteInfoType">
|
||||
<sequence>
|
||||
<element name="sitename" type="string" minOccurs="0" />
|
||||
<element name="base" type="anyURI" minOccurs="0" />
|
||||
<element name="generator" type="string" minOccurs="0" />
|
||||
<element name="case" type="mw:CaseType" minOccurs="0" />
|
||||
<element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="CaseType">
|
||||
<restriction base="NMTOKEN">
|
||||
<!-- Cannot have two titles differing only by case of first letter. -->
|
||||
<!-- Default behavior through 1.5, $wgCapitalLinks = true -->
|
||||
<enumeration value="first-letter" />
|
||||
|
||||
<!-- Complete title is case-sensitive -->
|
||||
<!-- Behavior when $wgCapitalLinks = false -->
|
||||
<enumeration value="case-sensitive" />
|
||||
|
||||
<!-- Cannot have non-case senstitive titles eg [[FOO]] == [[Foo]] -->
|
||||
<!-- Not yet implemented as of MediaWiki 1.18 -->
|
||||
<enumeration value="case-insensitive" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="DeletedFlagType">
|
||||
<restriction base="NMTOKEN">
|
||||
<enumeration value="deleted"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="NamespacesType">
|
||||
<sequence>
|
||||
<element name="namespace" type="mw:NamespaceType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="NamespaceType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="key" type="integer" />
|
||||
<attribute name="case" type="mw:CaseType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="PageType">
|
||||
<sequence>
|
||||
<!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
|
||||
<element name="title" type="string"/>
|
||||
|
||||
<!-- optional page ID number -->
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
|
||||
<!-- flag if the current revision is a redirect -->
|
||||
<element name="redirect" minOccurs="0"/>
|
||||
|
||||
<!-- comma-separated list of string tokens, if present -->
|
||||
<element name="restrictions" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- Zero or more sets of revision or upload data -->
|
||||
<choice minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="revision" type="mw:RevisionType" />
|
||||
<element name="upload" type="mw:UploadType" />
|
||||
<element name="logitem" type="mw:LogItemType" />
|
||||
</choice>
|
||||
|
||||
<!-- Zero or One sets of discussion threading data -->
|
||||
<element name="discussionthreadinginfo" minOccurs="0" maxOccurs="1" type="mw:DiscussionThreadingInfo" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RevisionType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="minor" minOccurs="0" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0"/>
|
||||
<element name="text" type="mw:TextType" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogItemType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0"/>
|
||||
<element name="type" type="string" />
|
||||
<element name="action" type="string" />
|
||||
<element name="text" type="mw:TextType" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="CommentType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType"/>
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
|
||||
<complexType name="TextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType"/>
|
||||
<!-- This isn't a good idea; we should be using "ID" instead of "NMTOKEN" -->
|
||||
<!-- However, "NMTOKEN" is strictest definition that is both compatible with existing -->
|
||||
<!-- usage ([0-9]+) and with the "ID" type. -->
|
||||
<attribute name="id" type="NMTOKEN"/>
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0"/>
|
||||
<element name="id" type="positiveInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0"/>
|
||||
</sequence>
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="UploadType">
|
||||
<sequence>
|
||||
<!-- Revision-style data... -->
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="comment" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- Filename. (Using underscores, not spaces. No 'Image:' namespace marker.) -->
|
||||
<element name="filename" type="string"/>
|
||||
|
||||
<!-- URI at which this resource can be obtained -->
|
||||
<element name="src" type="anyURI"/>
|
||||
|
||||
<element name="size" type="positiveInteger" />
|
||||
|
||||
<!-- TODO: add other metadata fields -->
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<!-- Discussion threading data for LiquidThreads -->
|
||||
<complexType name="DiscussionThreadingInfo">
|
||||
<sequence>
|
||||
<element name="ThreadSubject" type="string" />
|
||||
<element name="ThreadParent" type="positiveInteger" />
|
||||
<element name="ThreadAncestor" type="positiveInteger" />
|
||||
<element name="ThreadPage" type="string" />
|
||||
<element name="ThreadID" type="positiveInteger" />
|
||||
<element name="ThreadAuthor" type="string" />
|
||||
<element name="ThreadEditStatus" type="string" />
|
||||
<element name="ThreadType" type="string" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
output by MediaWiki's Special:Export system.
|
||||
|
||||
Version 0.2 adds optional basic file upload info support,
|
||||
which is used by our OAI export/import submodule.
|
||||
|
||||
Version 0.3 adds some site configuration information such
|
||||
as a list of defined namespaces.
|
||||
|
||||
Version 0.4 adds per-revision delete flags, log exports,
|
||||
discussion threading data, a per-page redirect flag, and
|
||||
per-namespace capitalization.
|
||||
|
||||
Version 0.5 adds byte count per revision.
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
http://www.mediawiki.org/xml/export-0.5.xsd
|
||||
|
||||
Use the namespace:
|
||||
http://www.mediawiki.org/xml/export-0.5/
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mw="http://www.mediawiki.org/xml/export-0.5/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/export-0.5/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's page export format
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Need this to reference xml:lang -->
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="mediawiki" type="mw:MediaWikiType"/>
|
||||
|
||||
<complexType name="MediaWikiType">
|
||||
<sequence>
|
||||
<element name="siteinfo" type="mw:SiteInfoType"
|
||||
minOccurs="0" maxOccurs="1"/>
|
||||
<element name="page" type="mw:PageType"
|
||||
minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="required"/>
|
||||
<attribute ref="xml:lang" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="SiteInfoType">
|
||||
<sequence>
|
||||
<element name="sitename" type="string" minOccurs="0" />
|
||||
<element name="base" type="anyURI" minOccurs="0" />
|
||||
<element name="generator" type="string" minOccurs="0" />
|
||||
<element name="case" type="mw:CaseType" minOccurs="0" />
|
||||
<element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="CaseType">
|
||||
<restriction base="NMTOKEN">
|
||||
<!-- Cannot have two titles differing only by case of first letter. -->
|
||||
<!-- Default behavior through 1.5, $wgCapitalLinks = true -->
|
||||
<enumeration value="first-letter" />
|
||||
|
||||
<!-- Complete title is case-sensitive -->
|
||||
<!-- Behavior when $wgCapitalLinks = false -->
|
||||
<enumeration value="case-sensitive" />
|
||||
|
||||
<!-- Cannot have non-case senstitive titles eg [[FOO]] == [[Foo]] -->
|
||||
<!-- Not yet implemented as of MediaWiki 1.18 -->
|
||||
<enumeration value="case-insensitive" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="DeletedFlagType">
|
||||
<restriction base="NMTOKEN">
|
||||
<enumeration value="deleted"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="NamespacesType">
|
||||
<sequence>
|
||||
<element name="namespace" type="mw:NamespaceType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="NamespaceType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="key" type="integer" />
|
||||
<attribute name="case" type="mw:CaseType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="PageType">
|
||||
<sequence>
|
||||
<!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
|
||||
<element name="title" type="string"/>
|
||||
|
||||
<!-- optional page ID number -->
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
|
||||
<!-- flag if the current revision is a redirect -->
|
||||
<element name="redirect" minOccurs="0"/>
|
||||
|
||||
<!-- comma-separated list of string tokens, if present -->
|
||||
<element name="restrictions" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- Zero or more sets of revision or upload data -->
|
||||
<choice minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="revision" type="mw:RevisionType" />
|
||||
<element name="upload" type="mw:UploadType" />
|
||||
<element name="logitem" type="mw:LogItemType" />
|
||||
</choice>
|
||||
|
||||
<!-- Zero or One sets of discussion threading data -->
|
||||
<element name="discussionthreadinginfo" minOccurs="0" maxOccurs="1" type="mw:DiscussionThreadingInfo" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RevisionType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="minor" minOccurs="0" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0"/>
|
||||
<element name="text" type="mw:TextType" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogItemType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0"/>
|
||||
<element name="type" type="string" />
|
||||
<element name="action" type="string" />
|
||||
<element name="text" type="mw:TextType" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="CommentType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType"/>
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
|
||||
<complexType name="TextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType"/>
|
||||
<!-- This isn't a good idea; we should be using "ID" instead of "NMTOKEN" -->
|
||||
<!-- However, "NMTOKEN" is strictest definition that is both compatible with existing -->
|
||||
<!-- usage ([0-9]+) and with the "ID" type. -->
|
||||
<attribute name="id" type="NMTOKEN"/>
|
||||
<attribute name="bytes" use="optional" type="nonNegativeInteger"/>
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0"/>
|
||||
<element name="id" type="positiveInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0"/>
|
||||
</sequence>
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="UploadType">
|
||||
<sequence>
|
||||
<!-- Revision-style data... -->
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="comment" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- Filename. (Using underscores, not spaces. No 'Image:' namespace marker.) -->
|
||||
<element name="filename" type="string"/>
|
||||
|
||||
<!-- URI at which this resource can be obtained -->
|
||||
<element name="src" type="anyURI"/>
|
||||
|
||||
<element name="size" type="positiveInteger" />
|
||||
|
||||
<!-- TODO: add other metadata fields -->
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<!-- Discussion threading data for LiquidThreads -->
|
||||
<complexType name="DiscussionThreadingInfo">
|
||||
<sequence>
|
||||
<element name="ThreadSubject" type="string" />
|
||||
<element name="ThreadParent" type="positiveInteger" />
|
||||
<element name="ThreadAncestor" type="positiveInteger" />
|
||||
<element name="ThreadPage" type="string" />
|
||||
<element name="ThreadID" type="positiveInteger" />
|
||||
<element name="ThreadAuthor" type="string" />
|
||||
<element name="ThreadEditStatus" type="string" />
|
||||
<element name="ThreadType" type="string" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
output by MediaWiki's Special:Export system.
|
||||
|
||||
Version 0.2 adds optional basic file upload info support,
|
||||
which is used by our OAI export/import submodule.
|
||||
|
||||
Version 0.3 adds some site configuration information such
|
||||
as a list of defined namespaces.
|
||||
|
||||
Version 0.4 adds per-revision delete flags, log exports,
|
||||
discussion threading data, a per-page redirect flag, and
|
||||
per-namespace capitalization.
|
||||
|
||||
Version 0.5 adds byte count per revision.
|
||||
|
||||
Version 0.6 adds a separate namespace tag, and resolves the
|
||||
redirect target and adds a separate sha1 tag for each revision.
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
http://www.mediawiki.org/xml/export-0.6.xsd
|
||||
|
||||
Use the namespace:
|
||||
http://www.mediawiki.org/xml/export-0.6/
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mw="http://www.mediawiki.org/xml/export-0.6/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/export-0.6/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's page export format
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Need this to reference xml:lang -->
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="mediawiki" type="mw:MediaWikiType"/>
|
||||
|
||||
<complexType name="MediaWikiType">
|
||||
<sequence>
|
||||
<element name="siteinfo" type="mw:SiteInfoType"
|
||||
minOccurs="0" maxOccurs="1"/>
|
||||
<element name="page" type="mw:PageType"
|
||||
minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="required"/>
|
||||
<attribute ref="xml:lang" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="SiteInfoType">
|
||||
<sequence>
|
||||
<element name="sitename" type="string" minOccurs="0" />
|
||||
<element name="base" type="anyURI" minOccurs="0" />
|
||||
<element name="generator" type="string" minOccurs="0" />
|
||||
<element name="case" type="mw:CaseType" minOccurs="0" />
|
||||
<element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="CaseType">
|
||||
<restriction base="NMTOKEN">
|
||||
<!-- Cannot have two titles differing only by case of first letter. -->
|
||||
<!-- Default behavior through 1.5, $wgCapitalLinks = true -->
|
||||
<enumeration value="first-letter" />
|
||||
|
||||
<!-- Complete title is case-sensitive -->
|
||||
<!-- Behavior when $wgCapitalLinks = false -->
|
||||
<enumeration value="case-sensitive" />
|
||||
|
||||
<!-- Cannot have non-case senstitive titles eg [[FOO]] == [[Foo]] -->
|
||||
<!-- Not yet implemented as of MediaWiki 1.18 -->
|
||||
<enumeration value="case-insensitive" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="DeletedFlagType">
|
||||
<restriction base="NMTOKEN">
|
||||
<enumeration value="deleted"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="NamespacesType">
|
||||
<sequence>
|
||||
<element name="namespace" type="mw:NamespaceType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="NamespaceType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="key" type="integer" />
|
||||
<attribute name="case" type="mw:CaseType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="PageType">
|
||||
<sequence>
|
||||
<!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
|
||||
<element name="title" type="string"/>
|
||||
|
||||
<!-- Namespace in canonical form -->
|
||||
<element name="ns" type="positiveInteger"/>
|
||||
|
||||
<!-- optional page ID number -->
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
|
||||
<!-- flag if the current revision is a redirect -->
|
||||
<element name="redirect" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- comma-separated list of string tokens, if present -->
|
||||
<element name="restrictions" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- Zero or more sets of revision or upload data -->
|
||||
<choice minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="revision" type="mw:RevisionType" />
|
||||
<element name="upload" type="mw:UploadType" />
|
||||
<element name="logitem" type="mw:LogItemType" />
|
||||
</choice>
|
||||
|
||||
<!-- Zero or One sets of discussion threading data -->
|
||||
<element name="discussionthreadinginfo" minOccurs="0" maxOccurs="1" type="mw:DiscussionThreadingInfo" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RevisionType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="minor" minOccurs="0" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0"/>
|
||||
<element name="sha1" type="string" />
|
||||
<element name="text" type="mw:TextType" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogItemType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" minOccurs="0"/>
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0"/>
|
||||
<element name="type" type="string" />
|
||||
<element name="action" type="string" />
|
||||
<element name="text" type="mw:TextType" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="CommentType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType"/>
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
|
||||
<complexType name="TextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType"/>
|
||||
<!-- This isn't a good idea; we should be using "ID" instead of "NMTOKEN" -->
|
||||
<!-- However, "NMTOKEN" is strictest definition that is both compatible with existing -->
|
||||
<!-- usage ([0-9]+) and with the "ID" type. -->
|
||||
<attribute name="id" type="NMTOKEN"/>
|
||||
<attribute name="bytes" use="optional" type="nonNegativeInteger"/>
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0"/>
|
||||
<element name="id" type="positiveInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0"/>
|
||||
</sequence>
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="UploadType">
|
||||
<sequence>
|
||||
<!-- Revision-style data... -->
|
||||
<element name="timestamp" type="dateTime"/>
|
||||
<element name="contributor" type="mw:ContributorType"/>
|
||||
<element name="comment" type="string" minOccurs="0"/>
|
||||
|
||||
<!-- Filename. (Using underscores, not spaces. No 'Image:' namespace marker.) -->
|
||||
<element name="filename" type="string"/>
|
||||
|
||||
<!-- URI at which this resource can be obtained -->
|
||||
<element name="src" type="anyURI"/>
|
||||
|
||||
<element name="size" type="positiveInteger" />
|
||||
|
||||
<!-- TODO: add other metadata fields -->
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<!-- Discussion threading data for LiquidThreads -->
|
||||
<complexType name="DiscussionThreadingInfo">
|
||||
<sequence>
|
||||
<element name="ThreadSubject" type="string" />
|
||||
<element name="ThreadParent" type="positiveInteger" />
|
||||
<element name="ThreadAncestor" type="positiveInteger" />
|
||||
<element name="ThreadPage" type="string" />
|
||||
<element name="ThreadID" type="positiveInteger" />
|
||||
<element name="ThreadAuthor" type="string" />
|
||||
<element name="ThreadEditStatus" type="string" />
|
||||
<element name="ThreadType" type="string" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
output by MediaWiki's Special:Export system.
|
||||
|
||||
Version 0.2 adds optional basic file upload info support,
|
||||
which is used by our OAI export/import submodule.
|
||||
|
||||
Version 0.3 adds some site configuration information such
|
||||
as a list of defined namespaces.
|
||||
|
||||
Version 0.4 adds per-revision delete flags, log exports,
|
||||
discussion threading data, a per-page redirect flag, and
|
||||
per-namespace capitalization.
|
||||
|
||||
Version 0.5 adds byte count per revision.
|
||||
|
||||
Version 0.6 adds a separate namespace tag, and resolves the
|
||||
redirect target and adds a separate sha1 tag for each revision.
|
||||
|
||||
Version 0.7 adds a unique identity constraint for both page and
|
||||
revision identifiers. See also bug 4220.
|
||||
Fix type for <ns> from "positiveInteger" to "nonNegativeInteger" to allow 0
|
||||
Moves <logitem> to its right location.
|
||||
Add parentid to revision.
|
||||
Fix type for <id> within <contributor> to "nonNegativeInteger"
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
http://www.mediawiki.org/xml/export-0.7.xsd
|
||||
|
||||
Use the namespace:
|
||||
http://www.mediawiki.org/xml/export-0.7/
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mw="http://www.mediawiki.org/xml/export-0.7/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/export-0.7/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's page export format
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Need this to reference xml:lang -->
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd" />
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="mediawiki" type="mw:MediaWikiType">
|
||||
<!-- Page ID contraint, see bug 4220 -->
|
||||
<unique name="PageIDConstraint">
|
||||
<selector xpath="mw:page" />
|
||||
<field xpath="mw:id" />
|
||||
</unique>
|
||||
<!-- Revision ID contraint, see bug 4220 -->
|
||||
<unique name="RevIDConstraint">
|
||||
<selector xpath="mw:page/mw:revision" />
|
||||
<field xpath="mw:id" />
|
||||
</unique>
|
||||
</element>
|
||||
|
||||
<complexType name="MediaWikiType">
|
||||
<sequence>
|
||||
<element name="siteinfo" type="mw:SiteInfoType"
|
||||
minOccurs="0" maxOccurs="1" />
|
||||
<element name="page" type="mw:PageType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
<element name="logitem" type="mw:LogItemType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="required" />
|
||||
<attribute ref="xml:lang" use="required" />
|
||||
</complexType>
|
||||
|
||||
<complexType name="SiteInfoType">
|
||||
<sequence>
|
||||
<element name="sitename" type="string" minOccurs="0" />
|
||||
<element name="base" type="anyURI" minOccurs="0" />
|
||||
<element name="generator" type="string" minOccurs="0" />
|
||||
<element name="case" type="mw:CaseType" minOccurs="0" />
|
||||
<element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="CaseType">
|
||||
<restriction base="NMTOKEN">
|
||||
<!-- Cannot have two titles differing only by case of first letter. -->
|
||||
<!-- Default behavior through 1.5, $wgCapitalLinks = true -->
|
||||
<enumeration value="first-letter" />
|
||||
|
||||
<!-- Complete title is case-sensitive -->
|
||||
<!-- Behavior when $wgCapitalLinks = false -->
|
||||
<enumeration value="case-sensitive" />
|
||||
|
||||
<!-- Cannot have non-case senstitive titles eg [[FOO]] == [[Foo]] -->
|
||||
<!-- Not yet implemented as of MediaWiki 1.18 -->
|
||||
<enumeration value="case-insensitive" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="DeletedFlagType">
|
||||
<restriction base="NMTOKEN">
|
||||
<enumeration value="deleted" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="NamespacesType">
|
||||
<sequence>
|
||||
<element name="namespace" type="mw:NamespaceType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="NamespaceType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="key" type="integer" />
|
||||
<attribute name="case" type="mw:CaseType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RedirectType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="title" type="string" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="PageType">
|
||||
<sequence>
|
||||
<!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
|
||||
<element name="title" type="string" />
|
||||
|
||||
<!-- Namespace in canonical form -->
|
||||
<element name="ns" type="nonNegativeInteger" />
|
||||
|
||||
<!-- optional page ID number -->
|
||||
<element name="id" type="positiveInteger" />
|
||||
|
||||
<!-- flag if the current revision is a redirect -->
|
||||
<element name="redirect" type="mw:RedirectType" minOccurs="0" maxOccurs="1" />
|
||||
|
||||
<!-- comma-separated list of string tokens, if present -->
|
||||
<element name="restrictions" type="string" minOccurs="0" />
|
||||
|
||||
<!-- Zero or more sets of revision or upload data -->
|
||||
<choice minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="revision" type="mw:RevisionType" />
|
||||
<element name="upload" type="mw:UploadType" />
|
||||
</choice>
|
||||
|
||||
<!-- Zero or One sets of discussion threading data -->
|
||||
<element name="discussionthreadinginfo" minOccurs="0" maxOccurs="1" type="mw:DiscussionThreadingInfo" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RevisionType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" />
|
||||
<element name="parentid" type="positiveInteger" minOccurs="0" />
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="minor" minOccurs="0" maxOccurs="1" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0" maxOccurs="1" />
|
||||
<element name="sha1" type="string" />
|
||||
<element name="text" type="mw:TextType" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogItemType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" />
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0" />
|
||||
<element name="type" type="string" />
|
||||
<element name="action" type="string" />
|
||||
<element name="text" type="mw:LogTextType" minOccurs="0" maxOccurs="1" />
|
||||
<element name="logtitle" type="string" minOccurs="0" maxOccurs="1" />
|
||||
<element name="params" type="mw:LogParamsType" minOccurs="0" maxOccurs="1" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="CommentType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="TextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
<!-- This isn't a good idea; we should be using "ID" instead of "NMTOKEN" -->
|
||||
<!-- However, "NMTOKEN" is strictest definition that is both compatible with existing -->
|
||||
<!-- usage ([0-9]+) and with the "ID" type. -->
|
||||
<attribute name="id" type="NMTOKEN" />
|
||||
<attribute name="bytes" use="optional" type="nonNegativeInteger" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogTextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogParamsType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0" />
|
||||
<element name="id" type="nonNegativeInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0" />
|
||||
</sequence>
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</complexType>
|
||||
|
||||
<complexType name="UploadType">
|
||||
<sequence>
|
||||
<!-- Revision-style data... -->
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="comment" type="string" minOccurs="0" />
|
||||
|
||||
<!-- Filename. (Using underscores, not spaces. No 'File:' namespace marker.) -->
|
||||
<element name="filename" type="string" />
|
||||
|
||||
<!-- URI at which this resource can be obtained -->
|
||||
<element name="src" type="anyURI" />
|
||||
|
||||
<element name="size" type="positiveInteger" />
|
||||
|
||||
<!-- TODO: add other metadata fields -->
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<!-- Discussion threading data for LiquidThreads -->
|
||||
<complexType name="DiscussionThreadingInfo">
|
||||
<sequence>
|
||||
<element name="ThreadSubject" type="string" />
|
||||
<element name="ThreadParent" type="positiveInteger" />
|
||||
<element name="ThreadAncestor" type="positiveInteger" />
|
||||
<element name="ThreadPage" type="string" />
|
||||
<element name="ThreadID" type="positiveInteger" />
|
||||
<element name="ThreadAuthor" type="string" />
|
||||
<element name="ThreadEditStatus" type="string" />
|
||||
<element name="ThreadType" type="string" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
output by MediaWiki's Special:Export system.
|
||||
|
||||
Version 0.2 adds optional basic file upload info support,
|
||||
which is used by our OAI export/import submodule.
|
||||
|
||||
Version 0.3 adds some site configuration information such
|
||||
as a list of defined namespaces.
|
||||
|
||||
Version 0.4 adds per-revision delete flags, log exports,
|
||||
discussion threading data, a per-page redirect flag, and
|
||||
per-namespace capitalization.
|
||||
|
||||
Version 0.5 adds byte count per revision.
|
||||
|
||||
Version 0.6 adds a separate namespace tag, and resolves the
|
||||
redirect target and adds a separate sha1 tag for each revision.
|
||||
|
||||
Version 0.7 adds a unique identity constraint for both page and
|
||||
revision identifiers. See also bug 4220.
|
||||
Fix type for <ns> from "positiveInteger" to "nonNegativeInteger" to allow 0
|
||||
Moves <logitem> to its right location.
|
||||
Add parentid to revision.
|
||||
Fix type for <id> within <contributor> to "nonNegativeInteger"
|
||||
|
||||
Version 0.8 adds support for a <model> and a <format> tag for
|
||||
each revision. See contenthandler.md.
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
http://www.mediawiki.org/xml/export-0.8.xsd
|
||||
|
||||
Use the namespace:
|
||||
http://www.mediawiki.org/xml/export-0.8/
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mw="http://www.mediawiki.org/xml/export-0.8/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/export-0.8/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's page export format
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Need this to reference xml:lang -->
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd" />
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="mediawiki" type="mw:MediaWikiType">
|
||||
<!-- Page ID contraint, see bug 4220 -->
|
||||
<unique name="PageIDConstraint">
|
||||
<selector xpath="mw:page" />
|
||||
<field xpath="mw:id" />
|
||||
</unique>
|
||||
<!-- Revision ID contraint, see bug 4220 -->
|
||||
<unique name="RevIDConstraint">
|
||||
<selector xpath="mw:page/mw:revision" />
|
||||
<field xpath="mw:id" />
|
||||
</unique>
|
||||
</element>
|
||||
|
||||
<complexType name="MediaWikiType">
|
||||
<sequence>
|
||||
<element name="siteinfo" type="mw:SiteInfoType"
|
||||
minOccurs="0" maxOccurs="1" />
|
||||
<element name="page" type="mw:PageType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
<element name="logitem" type="mw:LogItemType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="required" />
|
||||
<attribute ref="xml:lang" use="required" />
|
||||
</complexType>
|
||||
|
||||
<complexType name="SiteInfoType">
|
||||
<sequence>
|
||||
<element name="sitename" type="string" minOccurs="0" />
|
||||
<element name="base" type="anyURI" minOccurs="0" />
|
||||
<element name="generator" type="string" minOccurs="0" />
|
||||
<element name="case" type="mw:CaseType" minOccurs="0" />
|
||||
<element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="CaseType">
|
||||
<restriction base="NMTOKEN">
|
||||
<!-- Cannot have two titles differing only by case of first letter. -->
|
||||
<!-- Default behavior through 1.5, $wgCapitalLinks = true -->
|
||||
<enumeration value="first-letter" />
|
||||
|
||||
<!-- Complete title is case-sensitive -->
|
||||
<!-- Behavior when $wgCapitalLinks = false -->
|
||||
<enumeration value="case-sensitive" />
|
||||
|
||||
<!-- Cannot have non-case senstitive titles eg [[FOO]] == [[Foo]] -->
|
||||
<!-- Not yet implemented as of MediaWiki 1.18 -->
|
||||
<enumeration value="case-insensitive" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="DeletedFlagType">
|
||||
<restriction base="NMTOKEN">
|
||||
<enumeration value="deleted" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="NamespacesType">
|
||||
<sequence>
|
||||
<element name="namespace" type="mw:NamespaceType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="NamespaceType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="key" type="integer" />
|
||||
<attribute name="case" type="mw:CaseType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RedirectType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="title" type="string" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="ContentModelType">
|
||||
<restriction base="string">
|
||||
<pattern value="[a-zA-Z][-+./a-zA-Z0-9]*" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="ContentFormatType">
|
||||
<restriction base="string">
|
||||
<pattern value="[a-zA-Z][-+.a-zA-Z0-9]*/[a-zA-Z][-+.a-zA-Z0-9]*" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="PageType">
|
||||
<sequence>
|
||||
<!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
|
||||
<element name="title" type="string" />
|
||||
|
||||
<!-- Namespace in canonical form -->
|
||||
<element name="ns" type="nonNegativeInteger" />
|
||||
|
||||
<!-- optional page ID number -->
|
||||
<element name="id" type="positiveInteger" />
|
||||
|
||||
<!-- flag if the current revision is a redirect -->
|
||||
<element name="redirect" type="mw:RedirectType" minOccurs="0" maxOccurs="1" />
|
||||
|
||||
<!-- comma-separated list of string tokens, if present -->
|
||||
<element name="restrictions" type="string" minOccurs="0" />
|
||||
|
||||
<!-- Zero or more sets of revision or upload data -->
|
||||
<choice minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="revision" type="mw:RevisionType" />
|
||||
<element name="upload" type="mw:UploadType" />
|
||||
</choice>
|
||||
|
||||
<!-- Zero or One sets of discussion threading data -->
|
||||
<element name="discussionthreadinginfo" minOccurs="0" maxOccurs="1" type="mw:DiscussionThreadingInfo" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RevisionType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" />
|
||||
<element name="parentid" type="positiveInteger" minOccurs="0" />
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="minor" minOccurs="0" maxOccurs="1" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0" maxOccurs="1" />
|
||||
<element name="text" type="mw:TextType" />
|
||||
<element name="sha1" type="string" />
|
||||
<element name="model" type="mw:ContentModelType" />
|
||||
<element name="format" type="mw:ContentFormatType" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogItemType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" />
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0" />
|
||||
<element name="type" type="string" />
|
||||
<element name="action" type="string" />
|
||||
<element name="text" type="mw:LogTextType" minOccurs="0" maxOccurs="1" />
|
||||
<element name="logtitle" type="string" minOccurs="0" maxOccurs="1" />
|
||||
<element name="params" type="mw:LogParamsType" minOccurs="0" maxOccurs="1" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="CommentType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="TextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
<!-- This isn't a good idea; we should be using "ID" instead of "NMTOKEN" -->
|
||||
<!-- However, "NMTOKEN" is strictest definition that is both compatible with existing -->
|
||||
<!-- usage ([0-9]+) and with the "ID" type. -->
|
||||
<attribute name="id" type="NMTOKEN" />
|
||||
<attribute name="bytes" use="optional" type="nonNegativeInteger" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogTextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogParamsType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0" />
|
||||
<element name="id" type="nonNegativeInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0" />
|
||||
</sequence>
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</complexType>
|
||||
|
||||
<complexType name="UploadType">
|
||||
<sequence>
|
||||
<!-- Revision-style data... -->
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="comment" type="string" minOccurs="0" />
|
||||
|
||||
<!-- Filename. (Using underscores, not spaces. No 'File:' namespace marker.) -->
|
||||
<element name="filename" type="string" />
|
||||
|
||||
<!-- URI at which this resource can be obtained -->
|
||||
<element name="src" type="anyURI" />
|
||||
|
||||
<element name="size" type="positiveInteger" />
|
||||
|
||||
<!-- TODO: add other metadata fields -->
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<!-- Discussion threading data for LiquidThreads -->
|
||||
<complexType name="DiscussionThreadingInfo">
|
||||
<sequence>
|
||||
<element name="ThreadSubject" type="string" />
|
||||
<element name="ThreadParent" type="positiveInteger" />
|
||||
<element name="ThreadAncestor" type="positiveInteger" />
|
||||
<element name="ThreadPage" type="string" />
|
||||
<element name="ThreadID" type="positiveInteger" />
|
||||
<element name="ThreadAuthor" type="string" />
|
||||
<element name="ThreadEditStatus" type="string" />
|
||||
<element name="ThreadType" type="string" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
output by MediaWiki's Special:Export system.
|
||||
|
||||
Version 0.2 adds optional basic file upload info support,
|
||||
which is used by our OAI export/import submodule.
|
||||
|
||||
Version 0.3 adds some site configuration information such
|
||||
as a list of defined namespaces.
|
||||
|
||||
Version 0.4 adds per-revision delete flags, log exports,
|
||||
discussion threading data, a per-page redirect flag, and
|
||||
per-namespace capitalization.
|
||||
|
||||
Version 0.5 adds byte count per revision.
|
||||
|
||||
Version 0.6 adds a separate namespace tag, and resolves the
|
||||
redirect target and adds a separate sha1 tag for each revision.
|
||||
|
||||
Version 0.7 adds a unique identity constraint for both page and
|
||||
revision identifiers. See also bug 4220.
|
||||
Fix type for <ns> from "positiveInteger" to "nonNegativeInteger" to allow 0
|
||||
Moves <logitem> to its right location.
|
||||
Add parentid to revision.
|
||||
Fix type for <id> within <contributor> to "nonNegativeInteger"
|
||||
|
||||
Version 0.8 adds support for a <model> and a <format> tag for
|
||||
each revision. See contenthandler.md.
|
||||
|
||||
Version 0.9 adds the database name to the site information.
|
||||
|
||||
The canonical URL to the schema document is:
|
||||
http://www.mediawiki.org/xml/export-0.9.xsd
|
||||
|
||||
Use the namespace:
|
||||
http://www.mediawiki.org/xml/export-0.9/
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mw="http://www.mediawiki.org/xml/export-0.9/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/export-0.9/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's page export format
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Need this to reference xml:lang -->
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd" />
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="mediawiki" type="mw:MediaWikiType">
|
||||
<!-- Page ID contraint, see bug 4220 -->
|
||||
<unique name="PageIDConstraint">
|
||||
<selector xpath="mw:page" />
|
||||
<field xpath="mw:id" />
|
||||
</unique>
|
||||
<!-- Revision ID contraint, see bug 4220 -->
|
||||
<unique name="RevIDConstraint">
|
||||
<selector xpath="mw:page/mw:revision" />
|
||||
<field xpath="mw:id" />
|
||||
</unique>
|
||||
</element>
|
||||
|
||||
<complexType name="MediaWikiType">
|
||||
<sequence>
|
||||
<element name="siteinfo" type="mw:SiteInfoType"
|
||||
minOccurs="0" maxOccurs="1" />
|
||||
<element name="page" type="mw:PageType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
<element name="logitem" type="mw:LogItemType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="required" />
|
||||
<attribute ref="xml:lang" use="required" />
|
||||
</complexType>
|
||||
|
||||
<complexType name="SiteInfoType">
|
||||
<sequence>
|
||||
<element name="sitename" type="string" minOccurs="0" />
|
||||
<element name="dbname" type="string" minOccurs="0" />
|
||||
<element name="base" type="anyURI" minOccurs="0" />
|
||||
<element name="generator" type="string" minOccurs="0" />
|
||||
<element name="case" type="mw:CaseType" minOccurs="0" />
|
||||
<element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="CaseType">
|
||||
<restriction base="NMTOKEN">
|
||||
<!-- Cannot have two titles differing only by case of first letter. -->
|
||||
<!-- Default behavior through 1.5, $wgCapitalLinks = true -->
|
||||
<enumeration value="first-letter" />
|
||||
|
||||
<!-- Complete title is case-sensitive -->
|
||||
<!-- Behavior when $wgCapitalLinks = false -->
|
||||
<enumeration value="case-sensitive" />
|
||||
|
||||
<!-- Cannot have non-case senstitive titles eg [[FOO]] == [[Foo]] -->
|
||||
<!-- Not yet implemented as of MediaWiki 1.18 -->
|
||||
<enumeration value="case-insensitive" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="DeletedFlagType">
|
||||
<restriction base="NMTOKEN">
|
||||
<enumeration value="deleted" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="NamespacesType">
|
||||
<sequence>
|
||||
<element name="namespace" type="mw:NamespaceType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="NamespaceType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="key" type="integer" />
|
||||
<attribute name="case" type="mw:CaseType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RedirectType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="title" type="string" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="ContentModelType">
|
||||
<restriction base="string">
|
||||
<pattern value="[a-zA-Z][-+./a-zA-Z0-9]*" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="ContentFormatType">
|
||||
<restriction base="string">
|
||||
<pattern value="[a-zA-Z][-+.a-zA-Z0-9]*/[a-zA-Z][-+.a-zA-Z0-9]*" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="PageType">
|
||||
<sequence>
|
||||
<!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
|
||||
<element name="title" type="string" />
|
||||
|
||||
<!-- Namespace in canonical form -->
|
||||
<element name="ns" type="nonNegativeInteger" />
|
||||
|
||||
<!-- optional page ID number -->
|
||||
<element name="id" type="positiveInteger" />
|
||||
|
||||
<!-- flag if the current revision is a redirect -->
|
||||
<element name="redirect" type="mw:RedirectType" minOccurs="0" maxOccurs="1" />
|
||||
|
||||
<!-- comma-separated list of string tokens, if present -->
|
||||
<element name="restrictions" type="string" minOccurs="0" />
|
||||
|
||||
<!-- Zero or more sets of revision or upload data -->
|
||||
<choice minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="revision" type="mw:RevisionType" />
|
||||
<element name="upload" type="mw:UploadType" />
|
||||
</choice>
|
||||
|
||||
<!-- Zero or One sets of discussion threading data -->
|
||||
<element name="discussionthreadinginfo" minOccurs="0" maxOccurs="1" type="mw:DiscussionThreadingInfo" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RevisionType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" />
|
||||
<element name="parentid" type="positiveInteger" minOccurs="0" />
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="minor" minOccurs="0" maxOccurs="1" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0" maxOccurs="1" />
|
||||
<element name="text" type="mw:TextType" />
|
||||
<element name="sha1" type="string" />
|
||||
<element name="model" type="mw:ContentModelType" />
|
||||
<element name="format" type="mw:ContentFormatType" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogItemType">
|
||||
<sequence>
|
||||
<element name="id" type="positiveInteger" />
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="comment" type="mw:CommentType" minOccurs="0" />
|
||||
<element name="type" type="string" />
|
||||
<element name="action" type="string" />
|
||||
<element name="text" type="mw:LogTextType" minOccurs="0" maxOccurs="1" />
|
||||
<element name="logtitle" type="string" minOccurs="0" maxOccurs="1" />
|
||||
<element name="params" type="mw:LogParamsType" minOccurs="0" maxOccurs="1" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="CommentType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="TextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
<!-- This isn't a good idea; we should be using "ID" instead of "NMTOKEN" -->
|
||||
<!-- However, "NMTOKEN" is strictest definition that is both compatible with existing -->
|
||||
<!-- usage ([0-9]+) and with the "ID" type. -->
|
||||
<attribute name="id" type="NMTOKEN" />
|
||||
<attribute name="bytes" use="optional" type="nonNegativeInteger" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogTextType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="LogParamsType">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute ref="xml:space" use="optional" default="preserve" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="ContributorType">
|
||||
<sequence>
|
||||
<element name="username" type="string" minOccurs="0" />
|
||||
<element name="id" type="nonNegativeInteger" minOccurs="0" />
|
||||
|
||||
<element name="ip" type="string" minOccurs="0" />
|
||||
</sequence>
|
||||
<!-- This allows deleted=deleted on non-empty elements, but XSD is not omnipotent -->
|
||||
<attribute name="deleted" use="optional" type="mw:DeletedFlagType" />
|
||||
</complexType>
|
||||
|
||||
<complexType name="UploadType">
|
||||
<sequence>
|
||||
<!-- Revision-style data... -->
|
||||
<element name="timestamp" type="dateTime" />
|
||||
<element name="contributor" type="mw:ContributorType" />
|
||||
<element name="comment" type="string" minOccurs="0" />
|
||||
|
||||
<!-- Filename. (Using underscores, not spaces. No 'File:' namespace marker.) -->
|
||||
<element name="filename" type="string" />
|
||||
|
||||
<!-- URI at which this resource can be obtained -->
|
||||
<element name="src" type="anyURI" />
|
||||
|
||||
<element name="size" type="positiveInteger" />
|
||||
|
||||
<!-- TODO: add other metadata fields -->
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<!-- Discussion threading data for LiquidThreads -->
|
||||
<complexType name="DiscussionThreadingInfo">
|
||||
<sequence>
|
||||
<element name="ThreadSubject" type="string" />
|
||||
<element name="ThreadParent" type="positiveInteger" />
|
||||
<element name="ThreadAncestor" type="positiveInteger" />
|
||||
<element name="ThreadPage" type="string" />
|
||||
<element name="ThreadID" type="positiveInteger" />
|
||||
<element name="ThreadAuthor" type="string" />
|
||||
<element name="ThreadEditStatus" type="string" />
|
||||
<element name="ThreadType" type="string" />
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.11/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.11/ http://www.mediawiki.org/xml/export-0.11.xsd" version="0.11" xml:lang="en">
|
||||
|
||||
<!-- Optional global configuration info -->
|
||||
<siteinfo>
|
||||
<!-- Site name, as set in $wgSitename -->
|
||||
<sitename>DemoWiki</sitename>
|
||||
|
||||
<!-- Database name, as set in $wgDBname -->
|
||||
<dbname>demowiki</dbname>
|
||||
|
||||
<!-- Forgot where you got this set? -->
|
||||
<base>http://example.com/wiki/Main_Page</base>
|
||||
|
||||
<!-- Source software version -->
|
||||
<generator>MediaWiki 1.24</generator>
|
||||
|
||||
<!-- Title case sensitivity options of the wiki this data came from -->
|
||||
<!-- May be 'first-letter', 'case-sensitive', or 'case-insensitive' -->
|
||||
<case>first-letter</case>
|
||||
|
||||
<!-- Defined namespace keys on the source wiki. -->
|
||||
<namespaces>
|
||||
<namespace key="-2" case="first-letter">Media</namespace>
|
||||
<namespace key="-1" case="first-letter">Special</namespace>
|
||||
<namespace key="0" case="first-letter" />
|
||||
<namespace key="1" case="first-letter">Talk</namespace>
|
||||
<namespace key="2" case="first-letter">User</namespace>
|
||||
<namespace key="3" case="first-letter">User talk</namespace>
|
||||
<namespace key="4" case="first-letter">DemoWiki</namespace>
|
||||
<namespace key="5" case="first-letter">DemoWiki talk</namespace>
|
||||
<namespace key="6" case="first-letter">File</namespace>
|
||||
<namespace key="7" case="first-letter">File talk</namespace>
|
||||
<namespace key="8" case="first-letter">MediaWiki</namespace>
|
||||
<namespace key="9" case="first-letter">MediaWiki talk</namespace>
|
||||
<namespace key="10" case="first-letter">Template</namespace>
|
||||
<namespace key="11" case="first-letter">Template talk</namespace>
|
||||
<namespace key="12" case="first-letter">Help</namespace>
|
||||
<namespace key="13" case="first-letter">Help talk</namespace>
|
||||
<namespace key="14" case="first-letter">Category</namespace>
|
||||
<namespace key="15" case="first-letter">Category talk</namespace>
|
||||
</namespaces>
|
||||
</siteinfo>
|
||||
|
||||
<!-- The rest of the data will be a series of page records -->
|
||||
<page>
|
||||
<!-- Titles are listed here in text form, with namespace prefix -->
|
||||
<!-- if any, and spaces rather than the underscores used in URLs. -->
|
||||
<title>Page title</title>
|
||||
|
||||
<!-- Namespace in canonical form -->
|
||||
<ns>0</ns>
|
||||
|
||||
<!-- The page's immutable page_id number in the source database. -->
|
||||
<!-- Page ID numbers are kept across page moves, but may change -->
|
||||
<!-- if a page is deleted and recreated. -->
|
||||
<id>1</id>
|
||||
|
||||
<!-- Tag whether this article is a redirect and its target -->
|
||||
<!-- This corresponds to the page_is_redirect in the page table -->
|
||||
<redirect title="Target" />
|
||||
|
||||
<!-- If restricted, the ACL is listed here raw. -->
|
||||
<restrictions>edit=sysop:move=sysop</restrictions>
|
||||
|
||||
<!-- With a series of revision records... -->
|
||||
|
||||
<!-- Remember this is XML; if you must use a regex-based extractor -->
|
||||
<!-- in place of a standard XML parser, be very careful. -->
|
||||
<!-- * Don't forget to decode character entities! -->
|
||||
<!-- * If using a 'loose' XML parser, ensure that whitespace is -->
|
||||
<!-- preserved in the <text> elements. -->
|
||||
<revision>
|
||||
<!-- Unique revision ID number (rev_id) in the source database. -->
|
||||
<!-- This number uniquely identifies the revision on that wiki. -->
|
||||
<id>100</id>
|
||||
<!-- revision id of the parent revision -->
|
||||
<parentid>99</parentid>
|
||||
<timestamp>2001-01-15T13:15:00Z</timestamp>
|
||||
<contributor>
|
||||
<username>Foobar</username>
|
||||
<id>42</id>
|
||||
</contributor>
|
||||
<minor />
|
||||
<comment>I have just one thing to say!</comment>
|
||||
<origin>100</origin>
|
||||
<model>wikitext</model>
|
||||
<format>text/x-wiki</format>
|
||||
<text xml:space="preserve" bytes="25">A bunch of [[text]] here.</text>
|
||||
<sha1>5x0ux8iwjrbmfzgv6pkketxgkcnpr7h</sha1>
|
||||
</revision>
|
||||
|
||||
<revision>
|
||||
<id>99</id>
|
||||
<timestamp>2001-01-15T13:10:27Z</timestamp>
|
||||
<contributor>
|
||||
<ip>10.0.0.2</ip>
|
||||
</contributor>
|
||||
<comment>new!</comment>
|
||||
<origin>99</origin>
|
||||
<model>wikitext</model>
|
||||
<format>text/x-wiki</format>
|
||||
<text xml:space="preserve" bytes="24">An earlier [[revision]].</text>
|
||||
<sha1>etaxt3shcge6igz1biwy3d4um2pnle4</sha1>
|
||||
</revision>
|
||||
</page>
|
||||
|
||||
<page>
|
||||
<title>Talk:Page title</title>
|
||||
<ns>1</ns>
|
||||
<id>2</id>
|
||||
<revision>
|
||||
<id>101</id>
|
||||
<timestamp>2001-01-15T14:03:00Z</timestamp>
|
||||
<contributor><ip>10.0.0.2</ip></contributor>
|
||||
<comment>hey</comment>
|
||||
<origin>101</origin>
|
||||
<model>wikitext</model>
|
||||
<format>text/x-wiki</format>
|
||||
<text xml:space="preserve" bytes="47">WHYD YOU LOCK PAGE??!!! i was editing that jerk</text>
|
||||
<sha1>ml80vmyjlixdstnywwihx003exfzq9j</sha1>
|
||||
</revision>
|
||||
</page>
|
||||
|
||||
<page>
|
||||
<title>File:Some image.jpg</title>
|
||||
<ns>6</ns>
|
||||
<id>3</id>
|
||||
<revision>
|
||||
<id>102</id>
|
||||
<timestamp>2001-01-15T20:34:12Z</timestamp>
|
||||
<contributor><username>Foobar</username><id>42</id></contributor>
|
||||
<comment>My awesomeest image!</comment>
|
||||
<origin>102</origin>
|
||||
<model>wikitext</model>
|
||||
<format>text/x-wiki</format>
|
||||
<text xml:space="preserve" bytes="52">This is an awesome little imgae. I lurves it. {{PD}}</text>
|
||||
<sha1>mehom37npwkpzhaiwu3wyr0egalumki</sha1>
|
||||
</revision>
|
||||
<upload>
|
||||
<timestamp>2001-01-15T20:34:12Z</timestamp>
|
||||
<contributor><username>Foobar</username><id>42</id></contributor>
|
||||
<comment>My awesomeest image!</comment>
|
||||
<filename>Some_image.jpg</filename>
|
||||
<src>http://upload.wikimedia.org/commons/2/22/Some_image.jpg</src>
|
||||
<size>12345</size>
|
||||
</upload>
|
||||
</page>
|
||||
|
||||
<!-- or a series of logitem records, but normaly page and logitem never exist both in one file -->
|
||||
<logitem>
|
||||
<id>15</id>
|
||||
<timestamp>2008-10-23T03:20:32Z</timestamp>
|
||||
<contributor>
|
||||
<username>Wikimedian</username>
|
||||
<id>12345</id>
|
||||
</contributor>
|
||||
<comment>content was: 'I think this was a silly edit'</comment>
|
||||
<type>delete</type>
|
||||
<action>delete</action>
|
||||
<logtitle>Silly page name</logtitle>
|
||||
<params xml:space="preserve" />
|
||||
</logitem>
|
||||
|
||||
</mediawiki>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,61 @@
|
|||
globals.txt
|
||||
|
||||
Globals are evil. The original MediaWiki code relied on globals for processing
|
||||
context far too often. MediaWiki development since then has been a story of
|
||||
slowly moving context out of global variables and into objects. Storing
|
||||
processing context in object member variables allows those objects to be reused
|
||||
in a much more flexible way. Consider the elegance of:
|
||||
|
||||
# Generate the article HTML as if viewed by a web request
|
||||
$article = new Article( Title::newFromText( $t ) );
|
||||
$article->view();
|
||||
|
||||
versus
|
||||
|
||||
# Save current globals
|
||||
$oldTitle = $wgTitle;
|
||||
$oldArticle = $wgArticle;
|
||||
|
||||
# Generate the HTML
|
||||
$wgTitle = Title::newFromText( $t );
|
||||
$wgArticle = new Article;
|
||||
$wgArticle->view();
|
||||
|
||||
# Restore globals
|
||||
$wgTitle = $oldTitle
|
||||
$wgArticle = $oldArticle
|
||||
|
||||
Some of the current MediaWiki developers have an idle fantasy that some day,
|
||||
globals will be eliminated from MediaWiki entirely, replaced by a configuration
|
||||
object which would be passed to constructors. Whether that would be an
|
||||
efficient, convenient solution remains to be seen, but certainly PHP 5 makes
|
||||
such object-oriented programming models easier than they were in previous
|
||||
versions.
|
||||
|
||||
For the time being though, MediaWiki programmers will have to work in an
|
||||
environment with some global context. At the time of writing (2008), 418 globals were
|
||||
initialised on startup by MediaWiki. 304 of these were configuration settings,
|
||||
which are defined in MainConfigSchema.php. There is no comprehensive
|
||||
documentation for the remaining 114 globals, however some of the most important
|
||||
ones are listed below. They are typically initialised either in index.php or in
|
||||
Setup.php.
|
||||
|
||||
$wgTitle
|
||||
Title object created from the request URL.
|
||||
Use IContextSource::getTitle() instead.
|
||||
|
||||
$wgOut
|
||||
OutputPage object for HTTP response.
|
||||
Use IContextSource::getOutput() instead.
|
||||
|
||||
$wgUser
|
||||
User object for the user associated with the current request.
|
||||
Use IContextSource::getAuthority() instead.
|
||||
|
||||
$wgLang
|
||||
Language object selected by user preferences.
|
||||
Use IContextSource::getLanguage() instead.
|
||||
|
||||
$wgRequest
|
||||
WebRequest object, to get request data
|
||||
Use IContextSource::getRequest() instead.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
*
|
||||
!README
|
||||
!.gitignore
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
This directory is for the auto-generated doxygen documentation.
|
||||
Run 'php mwdocgen.php' in the maintenance subdirectory to build the docs.
|
||||
|
||||
Get Doxygen from http://www.doxygen.org/
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
Magic Words {#magicword}
|
||||
====================================
|
||||
|
||||
Magic words are localizable keywords used in wikitext. They are used for many
|
||||
small fragments of text, including:
|
||||
|
||||
* The names of parser functions e.g. `{{urlencode:...}}`
|
||||
* The names of variables, e.g. `{{CURRENTDAY}}`
|
||||
* Double-underscore behavior switches, e.g. `__NOTOC__`
|
||||
* Image link parameter names
|
||||
|
||||
Magic words have a synonym list, with the canonical English word always present,
|
||||
and a case sensitivity flag. The MagicWord class provides facilities for
|
||||
matching a magic word by converting it to a regex.
|
||||
|
||||
A magic word has a unique ID. Often, the ID is the canonical English synonym in
|
||||
lowercase.
|
||||
|
||||
To add a magic word in an extension, add a file to the **ExtensionMessagesFiles**
|
||||
attribute in extension.json,
|
||||
and in that file, set a variable called **$magicWords**. This array is associative
|
||||
with the language code in the first dimension key and an ID in the second key. The
|
||||
third level array is numerically indexed: the element with key 0 contains the case
|
||||
sensitivity flag, with 0 for case-insensitive and 1 for case-sensitive. The
|
||||
subsequent elements of the array are the synonyms in the relevant language.
|
||||
|
||||
To add a magic word in core, add it to $magicWords in MessagesEn.php, following the
|
||||
comment there.
|
||||
|
||||
For example, to add a new parser function in an extension: create a file called
|
||||
**ExtensionName.i18n.magic.php** with the following contents:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$magicWords = [];
|
||||
|
||||
$magicWords['en'] = [
|
||||
// Case insensitive.
|
||||
'mag_custom' => [ 0, 'custom' ],
|
||||
];
|
||||
|
||||
$magicWords['es'] = [
|
||||
'mag_custom' => [ 0, 'aduanero' ],
|
||||
];
|
||||
```
|
||||
|
||||
Then in extension.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"ExtensionMessagesFiles": {
|
||||
"ExtensionNameMagic": "ExtensionName.i18n.magic.php"
|
||||
},
|
||||
"Hooks": {
|
||||
"ParserFirstCallInit": "MyExtensionHooks::onParserFirstCallInit"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It is important that the key "ExtensionNameMagic" is unique. It must not be used
|
||||
by another extension.
|
||||
|
||||
And in the class file:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
class MyExtensionHooks {
|
||||
public static function onParserFirstCallInit( $parser ) {
|
||||
$parser->setFunctionHook( 'mag_custom', [ self::class, 'expandCustom' ] );
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function expandCustom( $parser, $var1, $var2 ) {
|
||||
return "custom: var1 is $var1, var2 is $var2";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Online documentation (contains more information):
|
||||
- Magic words: <https://www.mediawiki.org/wiki/Manual:Magic_words>
|
||||
- Variables: <https://www.mediawiki.org/wiki/Manual:Variable>
|
||||
- Parser functions: <https://www.mediawiki.org/wiki/Manual:Parser_functions>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
Prior to version 1.16, maintenance scripts were a hodgepodge of code that
|
||||
had no cohesion or formal method of action. Beginning in 1.16, maintenance
|
||||
scripts have been cleaned up to use a unified class.
|
||||
|
||||
1. Directory structure
|
||||
2. How to run a script
|
||||
3. How to write your own
|
||||
|
||||
1. DIRECTORY STRUCTURE
|
||||
The /maintenance directory of a MediaWiki installation contains several
|
||||
subdirectories, all of which have unique purposes.
|
||||
|
||||
2. HOW TO RUN A SCRIPT
|
||||
Ridiculously simple, just call 'php someScript.php' that's in the top-
|
||||
level /maintenance directory.
|
||||
|
||||
Example:
|
||||
php clearCacheStats.php
|
||||
|
||||
The following parameters are available to all maintenance scripts
|
||||
--help : Print a help message
|
||||
--quiet : Quiet non-error output
|
||||
--dbuser : The database user to use for the script (if needed)
|
||||
--dbpass : Same as above (if needed)
|
||||
--conf : Location of LocalSettings.php, if not default
|
||||
--wiki : For specifying the wiki ID
|
||||
--batch-size : If the script supports batch operations, do this many per batch
|
||||
|
||||
3. HOW TO WRITE YOUR OWN
|
||||
Make a file in the maintenance directory called myScript.php or something.
|
||||
In it, write the following:
|
||||
|
||||
==BEGIN==
|
||||
|
||||
<?php
|
||||
|
||||
require_once 'Maintenance.php';
|
||||
|
||||
class DemoMaint extends Maintenance {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
}
|
||||
}
|
||||
|
||||
$maintClass = DemoMaint::class;
|
||||
require_once RUN_MAINTENANCE_IF_MAIN;
|
||||
|
||||
==END==
|
||||
|
||||
That's it. In the execute() method, you have access to all of the normal
|
||||
MediaWiki functions, so you can get a DB connection, use the cache, etc.
|
||||
For full docs on the Maintenance class, see the auto-generated docs at
|
||||
https://doc.wikimedia.org/mediawiki-core/master/php/classMaintenance.html
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
Memcached {#memcached}
|
||||
====================================
|
||||
|
||||
MediaWiki has optional support for memcached, a "high-performance,
|
||||
distributed memory object caching system". For general information
|
||||
on it, see: <http://www.danga.com/memcached/>
|
||||
|
||||
Memcached is likely more trouble than a small site will need, but
|
||||
for a larger site with heavy load, like Wikipedia, it should help
|
||||
lighten the load on the database servers by caching data and objects
|
||||
in memory.
|
||||
|
||||
Installation
|
||||
--------------------------------
|
||||
|
||||
Packages are available for Fedora, Debian, Ubuntu and probably other
|
||||
Linux distributions. If there's no package available for your
|
||||
distribution, you can compile it from source.
|
||||
|
||||
Compilation
|
||||
--------------------------------
|
||||
|
||||
* PHP must be compiled with --enable-sockets
|
||||
* libevent: <http://www.monkey.org/~provos/libevent/>
|
||||
(as of 2003-08-11, 0.7a is current)
|
||||
* optionally, epoll-rt patch for Linux kernel:
|
||||
<http://www.xmailserver.org/linux-patches/nio-improve.html>
|
||||
* memcached: <http://www.danga.com/memcached/download.bml>
|
||||
(as of this writing, 1.1.9 is current)
|
||||
|
||||
Memcached and libevent are under BSD-style licenses.
|
||||
|
||||
The server should run on Linux and other Unix-like systems... you
|
||||
can run multiple servers on one machine or on multiple machines on
|
||||
a network; storage can be distributed across multiple servers, and
|
||||
multiple web servers can use the same cache cluster.
|
||||
|
||||
**W A R N I N G ! ! ! ! !**
|
||||
|
||||
Memcached has no security or authentication. Please ensure that your
|
||||
server is appropriately firewalled, and that the port(s) used for
|
||||
memcached servers are not publicly accessible. Otherwise, anyone on
|
||||
the internet can put data into and read data from your cache.
|
||||
|
||||
An attacker familiar with MediaWiki internals could use this to steal
|
||||
passwords and email addresses, or to make themselves a sysop and
|
||||
install malicious javascript on the site. There may be other types
|
||||
of vulnerability, no audit has been done -- so be safe and keep it
|
||||
behind a firewall.
|
||||
|
||||
**W A R N I N G ! ! ! ! !**
|
||||
|
||||
Setup
|
||||
--------------------------------
|
||||
|
||||
If you installed memcached using a distro, the daemon should be started
|
||||
automatically using
|
||||
|
||||
/etc/init.d/memcached
|
||||
|
||||
To start the daemon manually, use something like:
|
||||
|
||||
memcached -d -l 127.0.0.1 -p 11211 -m 64
|
||||
|
||||
(to run in daemon mode, accessible only via loopback interface,
|
||||
on port 11211, using up to 64 MiB of memory)
|
||||
|
||||
In your LocalSettings.php file, set:
|
||||
|
||||
```php
|
||||
$wgMainCacheType = CACHE_MEMCACHED;
|
||||
$wgMemCachedServers = [ "127.0.0.1:11211" ];
|
||||
```
|
||||
|
||||
The wiki should then use memcached to cache various data. To use
|
||||
multiple servers (physically separate boxes or multiple caches
|
||||
on one machine on a large-memory x86 box), just add more items
|
||||
to the array. To increase the weight of a server (say, because
|
||||
it has twice the memory of the others and you want to spread
|
||||
usage evenly), make its entry a subarray:
|
||||
|
||||
```php
|
||||
$wgMemCachedServers = [
|
||||
"127.0.0.1:11211", # one gig on this box
|
||||
[ "192.168.0.1:11211", 2 ] # two gigs on the other box
|
||||
];
|
||||
```
|
||||
|
||||
PHP client for memcached
|
||||
--------------------------------
|
||||
|
||||
MediaWiki uses a fork of Ryan T. Dean's pure-PHP memcached client.
|
||||
It also supports the PECL PHP extension for memcached.
|
||||
|
||||
MediaWiki uses the ObjectCache class to retrieve instances of
|
||||
BagOStuff by purpose, controlled by the following variables:
|
||||
* $wgMainCacheType
|
||||
* $wgParserCacheType
|
||||
* $wgMessageCacheType
|
||||
|
||||
If you set one of these to CACHE_NONE, MediaWiki still creates a
|
||||
BagOStuff object, but calls it to it are no-ops. If the cache daemon
|
||||
can't be contacted, it should also disable itself fairly smoothly.
|
||||
|
||||
Keys used
|
||||
--------------------------------
|
||||
|
||||
(incomplete, out of date)
|
||||
|
||||
Date Formatter:
|
||||
|
||||
key: $wgDBname:dateformatter
|
||||
ex: wikidb:dateformatter
|
||||
stores: a single instance of the DateFormatter class
|
||||
cleared by: nothing
|
||||
expiry: one hour
|
||||
|
||||
Difference Engine:
|
||||
|
||||
key: $wgDBname:diff:version:{MW_DIFF_VERSION}:oldid:$old:newid:$new
|
||||
ex: wikidb:diff:version:1.11a:oldid:1:newid:2
|
||||
stores: body of a difference
|
||||
cleared by: nothing
|
||||
expiry: one week
|
||||
|
||||
Interwiki:
|
||||
|
||||
key: $wgDBname:interwiki:$prefix
|
||||
ex: wikidb:interwiki:w
|
||||
stores: object from the interwiki table of the database
|
||||
expiry: $wgInterwikiExpiry
|
||||
cleared by: nothing
|
||||
|
||||
Lag time of the databases:
|
||||
|
||||
key: $wgDBname:lag_times
|
||||
ex: wikidb:lag_times
|
||||
stores: array mapping the database id to its lag time
|
||||
expiry: 5 secondes
|
||||
cleared by: nothing
|
||||
|
||||
Localisation:
|
||||
|
||||
key: $wgDBname:localisation:$lang
|
||||
ex: wikidb:localisation:de
|
||||
stores: array of localisation settings
|
||||
set in: Language::loadLocalisation()
|
||||
expiry: none
|
||||
cleared by: Language::loadLocalisation()
|
||||
|
||||
Message Cache:
|
||||
|
||||
See MessageCache.php.
|
||||
|
||||
Newtalk:
|
||||
|
||||
key: $wgDBname:newtalk:ip:$ip
|
||||
ex: wikidb:newtalk:ip:123.45.67.89
|
||||
stores: integer, 0 or 1
|
||||
set in: User::loadFromDatabase()
|
||||
cleared by: User::saveSettings() # ?
|
||||
expiry: 30 minutes
|
||||
|
||||
Parser Cache:
|
||||
|
||||
access: ParserCache
|
||||
backend: $wgParserCacheType
|
||||
key: $wgDBname:pcache:idhash:$pageid-$renderkey!$hash
|
||||
$pageid: id of the page
|
||||
$renderkey: 1 if action=render, 0 otherwise
|
||||
$hash: hash of user options applied to the page, see ParserOptions::optionsHash()
|
||||
ex: wikidb:pcache:idhash:1-0!1!0!!en!2
|
||||
stores: ParserOutput object
|
||||
modified by: WikiPage::doEditUpdates() or PoolWorkArticleView::doWork()
|
||||
expiry: $wgParserCacheExpireTime or less if it contains short lived functions
|
||||
|
||||
key: $wgDBname:pcache:idoptions:$pageid
|
||||
stores: CacheTime object with an additional list of used options for the hash,
|
||||
serves as ParserCache pointer.
|
||||
modified by: ParserCache::save()
|
||||
expiry: The same as the ParserCache entry it points to.
|
||||
|
||||
Ping limiter:
|
||||
|
||||
controlled by: $wgRateLimits
|
||||
key: $wgDBname:limiter:action:$action:ip:$ip,
|
||||
$wgDBname:limiter:action:$action:user:$id,
|
||||
mediawiki:limiter:action:$action:ip:$ip and
|
||||
mediawiki:limiter:action:$action:subnet:$sub
|
||||
ex: wikidb:limiter:action:edit:ip:123.45.67.89,
|
||||
wikidb:limiter:action:edit:user:1012
|
||||
mediawiki:limiter:action:edit:ip:123.45.67.89 and
|
||||
mediawiki:limiter:action:$action:subnet:123.45.67
|
||||
stores: number of action made by user/ip/subnet
|
||||
cleared by: nothing
|
||||
expiry: expiry set for the action and group in $wgRateLimits
|
||||
|
||||
|
||||
Proxy Check: (deprecated)
|
||||
|
||||
key: $wgDBname:proxy:ip:$ip
|
||||
ex: wikidb:proxy:ip:123.45.67.89
|
||||
stores: 1 if the ip is a proxy
|
||||
cleared by: nothing
|
||||
expiry: $wgProxyMemcExpiry
|
||||
|
||||
Revision text:
|
||||
|
||||
key: $wgDBname:revisiontext:textid:$id
|
||||
ex: wikidb:revisiontext:textid:1012
|
||||
stores: text of a revision
|
||||
cleared by: nothing
|
||||
expiry: $wgRevisionCacheExpiry
|
||||
|
||||
Sessions:
|
||||
|
||||
controlled by: $wgSessionsInObjectCache
|
||||
key: $wgBDname:session:$id
|
||||
ex: wikidb:session:38d7c5b8d3bfc51egf40c69bc40f8be3
|
||||
stores: $SESSION, useful when using a multi-sever wiki
|
||||
expiry: one hour
|
||||
cleared by: session_destroy()
|
||||
|
||||
Sidebar:
|
||||
|
||||
access: WANObjectCache
|
||||
controlled by: $wgEnableSidebarCache
|
||||
key: $wgDBname:sidebar
|
||||
ex: wikidb:sidebar
|
||||
stores: the html output of the sidebar
|
||||
expiry: $wgSidebarCacheExpiry
|
||||
cleared by: MessageCache::replace()
|
||||
|
||||
Special:Allpages:
|
||||
|
||||
key: $wgDBname:allpages:ns:$ns
|
||||
ex: wikidb:allpages:ns:0
|
||||
stores: array of pages in a namespace
|
||||
expiry: one hour
|
||||
cleared by: nothing
|
||||
|
||||
Special:Recentchanges (feed):
|
||||
|
||||
backend: $wgMessageCacheType
|
||||
key: $wgDBname:rcfeed:$format:$limit:$hideminor:$target and
|
||||
rcfeed:$format:timestamp
|
||||
ex: wikidb:rcfeed:rss:50:: and rcfeed:rss:timestamp
|
||||
stores: xml output of feed
|
||||
expiry: one day
|
||||
clear by: maintenance/rebuildrecentchanges.php script, or
|
||||
calling Special:Recentchanges?action=purge&feed=rss,
|
||||
Special:Recentchanges?action=purge&feed=atom,
|
||||
but note need $wgGroupPermissions[...]['purge'] permission.
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE rdf:RDF [
|
||||
<!ENTITY cc "http://creativecommons.org/ns#">
|
||||
<!ENTITY xsd "http://www.w3.org/2001/XMLSchema#">
|
||||
<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#">
|
||||
<!ENTITY owl "http://www.w3.org/2002/07/owl#">
|
||||
<!ENTITY mediawiki "https://www.mediawiki.org/ontology#">
|
||||
]>
|
||||
|
||||
<rdf:RDF
|
||||
xmlns:xsd="&xsd;"
|
||||
xmlns:rdf="&rdf;"
|
||||
xmlns:rdfs="&rdfs;"
|
||||
xmlns:owl="&owl;"
|
||||
xmlns:cc="&cc;"
|
||||
>
|
||||
|
||||
<owl:Ontology rdf:about="&mediawiki;">
|
||||
<rdfs:label>MediaWiki ontology</rdfs:label>
|
||||
<rdfs:comment>The ontology of MediaWiki</rdfs:comment>
|
||||
<cc:licence rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
|
||||
</owl:Ontology>
|
||||
|
||||
<!--
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Classes
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
-->
|
||||
|
||||
<owl:Class rdf:about="&mediawiki;Dump">
|
||||
<rdfs:label>Dump</rdfs:label>
|
||||
<rdfs:comment>A dump of MediaWiki content.</rdfs:comment>
|
||||
</owl:Class>
|
||||
|
||||
<owl:Class rdf:about="&mediawiki;Category">
|
||||
<rdfs:label>Category</rdfs:label>
|
||||
<rdfs:comment>MediaWiki category.</rdfs:comment>
|
||||
</owl:Class>
|
||||
|
||||
<owl:Class rdf:about="&mediawiki;HiddenCategory">
|
||||
<rdfs:label>HiddenCategory</rdfs:label>
|
||||
<rdfs:comment>MediaWiki hidden category.</rdfs:comment>
|
||||
</owl:Class>
|
||||
|
||||
<!--
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Properties
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
-->
|
||||
|
||||
<owl:ObjectProperty rdf:about="&mediawiki;isInCategory">
|
||||
<rdfs:label>isInCategory</rdfs:label>
|
||||
<rdfs:comment>One category is the parent of another.</rdfs:comment>
|
||||
<rdfs:range rdf:resource="&mediawiki;Category"/>
|
||||
<rdfs:domain rdf:resource="&mediawiki;Category"/>
|
||||
</owl:ObjectProperty>
|
||||
|
||||
<owl:DatatypeProperty rdf:about="&mediawiki;pages">
|
||||
<rdfs:label>pages</rdfs:label>
|
||||
<rdfs:comment>Number of articles belonging to this category.</rdfs:comment>
|
||||
<rdfs:range rdf:resource="&mediawiki;Category"/>
|
||||
<rdfs:range rdf:resource="&xsd;integer"/>
|
||||
</owl:DatatypeProperty>
|
||||
|
||||
<owl:DatatypeProperty rdf:about="&mediawiki;subcategories">
|
||||
<rdfs:label>subcategories</rdfs:label>
|
||||
<rdfs:comment>Number of subcategories belonging to this category.</rdfs:comment>
|
||||
<rdfs:range rdf:resource="&mediawiki;Category"/>
|
||||
<rdfs:range rdf:resource="&xsd;integer"/>
|
||||
</owl:DatatypeProperty>
|
||||
|
||||
</rdf:RDF>
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
PageUpdater {#pageupdater}
|
||||
===========
|
||||
|
||||
This document provides an overview of the usage of PageUpdater and DerivedPageDataUpdater.
|
||||
|
||||
## PageUpdater
|
||||
|
||||
`PageUpdater` is the canonical way to create page revisions, that is, to perform edits.
|
||||
|
||||
`PageUpdater` is a stateful, handle-like object that allows new revisions to be created on a given wiki page using the `saveRevision()` method. `PageUpdater` provides setters for defining the new revision's content as well as meta-data such as change tags. `saveRevision()` stores the new revision's primary content and metadata, and triggers the necessary updates to derived secondary data and cached artifacts e.g. in the `ParserCache` and the CDN layer, using a `DerivedPageDataUpdater`.
|
||||
|
||||
`PageUpdater` instances follow the below life cycle, defined by a number of methods:
|
||||
|
||||
+----------------------------+
|
||||
| |
|
||||
| new |
|
||||
| |
|
||||
+------|--------------|------+
|
||||
| |
|
||||
grabParentRevision()-| |
|
||||
or hasEditConflict()-| |
|
||||
| |
|
||||
+--------v-------+ |
|
||||
| | |
|
||||
| parent known | |
|
||||
| | |
|
||||
Enables---------------+--------|-------+ |
|
||||
safe operations based on | |-saveRevision()
|
||||
the parent revision, e.g. | |
|
||||
section replacement or | |
|
||||
edit conflict resolution. | |
|
||||
| |
|
||||
saveRevision()-| |
|
||||
| |
|
||||
+------v--------------v------+
|
||||
| |
|
||||
| creation committed |
|
||||
| |
|
||||
Enables-----------------+----------------------------+
|
||||
wasSuccess()
|
||||
isUnchanged()
|
||||
isNew()
|
||||
getState()
|
||||
getNewRevision()
|
||||
etc.
|
||||
|
||||
The stateful nature of `PageUpdater` allows it to be used to safely perform transformations that depend on the new revision's parent revision, such as replacing sections or applying 3-way conflict resolution, while protecting against race conditions using a compare-and-swap (CAS) mechanism: after calling code used the `grabParentRevision()` method to access the edit's logical parent, `PageUpdater` remembers that revision, and ensure that that revision is still the page's current revision when performing the atomic database update for the revision's primary meta-data when `saveRevision()` is called. If another revision was created concurrently, `saveRevision()` will fail, indicating the problem with the "edit-conflict" code in the status object.
|
||||
|
||||
Typical usage for programmatic revision creation (with `$page` being a WikiPage as of 1.32, to be replaced by a repository service later):
|
||||
|
||||
```php
|
||||
$updater = $page->newPageUpdater( $user );
|
||||
$updater->setContent( SlotRecord::MAIN, $content );
|
||||
$updater->setRcPatrolStatus( RecentChange::PRC_PATROLLED );
|
||||
$newRev = $updater->saveRevision( $comment );
|
||||
```
|
||||
|
||||
Usage with content depending on the parent revision
|
||||
|
||||
```php
|
||||
$updater = $page->newPageUpdater( $user );
|
||||
$parent = $updater->grabParentRevision();
|
||||
$content = $parent->getContent( SlotRecord::MAIN )->replaceSection( $section, $sectionContent );
|
||||
$updater->setContent( SlotRecord::MAIN, $content );
|
||||
$newRev = $updater->saveRevision( $comment, EDIT_UPDATE );
|
||||
```
|
||||
|
||||
In both cases, all secondary updates will be triggered automatically.
|
||||
|
||||
## DerivedPageDataUpdater
|
||||
|
||||
`DerivedPageDataUpdater` is a stateful, handle-like object that caches derived data representing a revision, and can trigger updates of cached copies of that data, e.g. in the links tables, `page_props`, the `ParserCache`, and the CDN layer.
|
||||
|
||||
`DerivedPageDataUpdater` is used by `PageUpdater` when creating new revisions, but can also be used independently when performing meta data updates during undeletion, import, or when puring a page. It's a stepping stone on the way to a more complete refactoring of WikiPage.
|
||||
|
||||
**NOTE**: Avoid direct usage of `DerivedPageDataUpdater`. In the future, we want to define interfaces for the different use cases of `DerivedPageDataUpdater`, particularly providing access to post-PST content and `ParserOutput` to callbacks during revision creation, which currently use `WikiPage::prepareContentForEdit`, and allowing updates to be triggered on purge, import, and undeletion, which currently use `WikiPage::doEditUpdates()` and `Content::getSecondaryDataUpdates()`.
|
||||
|
||||
The primary reason for `DerivedPageDataUpdater` to be stateful is internal caching of state that avoids the re-generation of `ParserOutput` and re-application of pre-save-transformations (PST).
|
||||
|
||||
`DerivedPageDataUpdater` instances follow the below life cycle, defined by a number of methods:
|
||||
|
||||
+---------------------------------------------------------------------+
|
||||
| |
|
||||
| new |
|
||||
| |
|
||||
+---------------|------------------|------------------|---------------+
|
||||
| | |
|
||||
grabCurrentRevision()-| | |
|
||||
| | |
|
||||
+-----------v----------+ | |
|
||||
| | |-prepareContent() |
|
||||
| knows current | | |
|
||||
| | | |
|
||||
Enables------------------+-----|-----|----------+ | |
|
||||
pageExisted() | | | |
|
||||
wasRedirect() | |-prepareContent() | |-prepareUpdate()
|
||||
| | | |
|
||||
| | +-------------v------------+ |
|
||||
| | | | |
|
||||
| +----> has content | |
|
||||
| | | |
|
||||
Enables------------------------|----------+--------------------------+ |
|
||||
isChange() | | |
|
||||
isCreation() |-prepareUpdate() | |
|
||||
getSlots() | prepareUpdate()-| |
|
||||
getTouchedSlotRoles() | | |
|
||||
getCanonicalParserOutput() | +-----------v------------v-----------------+
|
||||
| | |
|
||||
+------------------> has revision |
|
||||
| |
|
||||
Enables-------------------------------------------+------------------------|-----------------+
|
||||
updateParserCache() |
|
||||
runSecondaryDataUpdates() |-doUpdates()
|
||||
|
|
||||
+-----------v---------+
|
||||
| |
|
||||
| updates done |
|
||||
| |
|
||||
+---------------------+
|
||||
|
||||
|
||||
- `grabCurrentRevision()` returns the logical parent revision of the target revision. It is guaranteed to always return the same revision for a given `DerivedPageDataUpdater` instance. If called before `prepareUpdate()`, this fixates the logical parent to be the page's current revision. If called for the first time after `prepareUpdate()`, it returns the revision passed as the 'oldrevision' option to `prepareUpdate()`, or, if that wasn't given, the parent of $revision parameter passed to `prepareUpdate()`.
|
||||
|
||||
- `prepareContent()` is called before the new revision is created, to apply pre-save-transformation (PST) and allow subsequent access to the canonical `ParserOutput` of the revision. `getSlots()` and `getCanonicalParserOutput()` as well as `getSecondaryDataUpdates()` may be used after `prepareContent()` was called. Calling `prepareContent()` with the same parameters again has no effect. Calling it again with mismatching parameters, or calling it after `prepareUpdate()` was called, triggers a `LogicException`.
|
||||
|
||||
- `prepareUpdate()` is called after the new revision has been created. This may happen right after the revision was created, on the same instance on which `prepareContent()` was called, or later (possibly much later), on a fresh instance in a different process, due to deferred or asynchronous updates, or during import, undeletion, purging, etc. `prepareUpdate()` is required before a call to `doUpdates()`, and it also enables calls to `getSlots()` and `getCanonicalParserOutput()` as well as `getSecondaryDataUpdates()`. Calling `prepareUpdate()` with the same parameters again has no effect. Calling it again with mismatching parameters, or calling it with parameters mismatching the ones `prepareContent()` was called with, triggers a `LogicException`.
|
||||
|
||||
- `getSecondaryDataUpdates()` returns `DataUpdates` that represent derived data for the revision. These may be used to update such data, e.g. in `ApiPurge`, `RefreshLinksJob`, and the `refreshLinks` script.
|
||||
|
||||
- `doUpdates()` triggers the updates defined by `getSecondaryDataUpdates()`, and also causes updates to cached artifacts in the `ParserCache`, the CDN layer, etc. This is primarily used by PageUpdater, but also by `UndeletePage` during undeletion, and when importing revisions from XML. `doUpdates()` can only be called after `prepareUpdate()` was used to initialize the `DerivedPageDataUpdater` instance for a specific revision. Calling it before `prepareUpdate()` is called raises a `LogicException`.
|
||||
|
||||
A `DerivedPageDataUpdater` instance is intended to be re-used during different stages of complex update operations that often involve callbacks to extension code via
|
||||
MediaWiki's hook mechanism, or deferred or even asynchronous execution of Jobs and `DeferredUpdates`. Since these mechanisms typically do not provide a way to pass a
|
||||
`DerivedPageDataUpdater` directly, `WikiPage::getDerivedDataUpdater()` has to be used to obtain a `DerivedPageDataUpdater` for the update currently in progress - re-using the same `DerivedPageDataUpdater` if possible avoids re-generation of `ParserOutput` objects
|
||||
and other expensively derived artifacts.
|
||||
|
||||
This mechanism for re-using a `DerivedPageDataUpdater` instance without passing it directly requires a way to ensure that a given `DerivedPageDataUpdater` instance can actually be used in the calling code's context. For this purpose, `WikiPage::getDerivedDataUpdater()` calls the `isReusableFor()` method on `DerivedPageDataUpdater`, which ensures that the given instance is applicable to the given parameters. In other words, `isReusableFor()` predicts whether calling `prepareContent()` or `prepareUpdate()` with a given set of parameters will trigger a `LogicException`. In that case, `WikiPage::getDerivedDataUpdater()` creates a fresh `DerivedPageDataUpdater` instance.
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-06/schema#",
|
||||
"$id": "https://www.mediawiki.org/schema/discovery-1.0",
|
||||
"title": "MediaWiki REST API discovery document",
|
||||
"description": "Discovery documents provide all information needed to locate and access REST APIs on a given wiki.",
|
||||
"type": "object",
|
||||
"required": [ "info", "servers", "modules" ],
|
||||
"properties": {
|
||||
"mw-discovery": {
|
||||
"description": "The version of the MediaWiki discovery schema used by the discovery document.",
|
||||
"type": "string"
|
||||
},
|
||||
"info": {
|
||||
"$ref": "#/definitions/Info"
|
||||
},
|
||||
"servers": {
|
||||
"description": "A list of servers that can be used to access the APIs.",
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"item": { "$ref": "https://spec.openapis.org/oas/3.0/schema/2021-09-28#/definitions/Server" }
|
||||
},
|
||||
"modules": {
|
||||
"description": "Information about the API modules available for interacting with the wiki. Depends on the extensions installed on the wiki, and may further vary with the wiki's version and configuration.",
|
||||
"type": "object",
|
||||
"minProperties": 1,
|
||||
"additionalProperties": { "$ref": "#/definitions/Module" }
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Info": {
|
||||
"description": "Information about the wiki site that offers the API",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"title",
|
||||
"mediawiki"
|
||||
],
|
||||
"properties": {
|
||||
"title": {
|
||||
"description": "The name of the wiki",
|
||||
"type": "string"
|
||||
},
|
||||
"license": {
|
||||
"$ref": "https://spec.openapis.org/oas/3.0/schema/2021-09-28#/definitions/License"
|
||||
},
|
||||
"contact": {
|
||||
"$ref": "https://spec.openapis.org/oas/3.0/schema/2021-09-28#/definitions/Contact"
|
||||
},
|
||||
"mediawiki": {
|
||||
"description": "The version of the MediaWiki software serving the document",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Module": {
|
||||
"title": "REST API Module",
|
||||
"description": "Information about a given REST module available of the wiki. Corresponds to the https://www.mediawiki.org/schema/mwapi-1.0 schema.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"info",
|
||||
"base",
|
||||
"spec"
|
||||
],
|
||||
"properties": {
|
||||
"info": {
|
||||
"$ref": "#/definitions/ModuleInfo"
|
||||
},
|
||||
"base": {
|
||||
"description": "The base path of the module, to be appended to the server URL. This may or may not be a functioning endpoint, as defined by the module's specification.",
|
||||
"type": "string"
|
||||
},
|
||||
"spec": {
|
||||
"description": "URL of the module's OpenAPI specification. The version of OpenAPI used may vary.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ModuleInfo": {
|
||||
"$ref": "https://www.mediawiki.org/schema/mwapi-1.0#/definitions/Info"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"$id": "https://www.mediawiki.org/schema/mwapi-1.0",
|
||||
"title": "MediaWiki REST API module definition",
|
||||
"description": "Module definition files provide meta-data about modules and define the available routes. They are similar to OpenAPI specs.",
|
||||
"type": "object",
|
||||
"required": [ "mwapi", "info", "moduleId", "paths" ],
|
||||
"properties": {
|
||||
"mwapi": {
|
||||
"description": "The version of the MediaWiki module definition schema used by the document.",
|
||||
"type": "string"
|
||||
},
|
||||
"moduleId": {
|
||||
"description": "The module name, also used as the path prefix",
|
||||
"type": "string"
|
||||
},
|
||||
"info": {
|
||||
"$ref": "#/definitions/Info"
|
||||
},
|
||||
"paths": {
|
||||
"description": "Information about the API routes available for interacting with the wiki.",
|
||||
"type": "object",
|
||||
"minProperties": 1,
|
||||
"additionalProperties": { "$ref": "#/definitions/Path" }
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Info": {
|
||||
"allOf": [
|
||||
{ "$ref": "https://spec.openapis.org/oas/3.0/schema/2021-09-28#/definitions/Info" },
|
||||
{ "$ref": "#/definitions/ExtraInfo" }
|
||||
]
|
||||
},
|
||||
"ExtraInfo": {
|
||||
"type": "object"
|
||||
},
|
||||
"Path": {
|
||||
"title": "REST API Path",
|
||||
"description": "The operations available for a given path",
|
||||
"type": "object",
|
||||
"minProperties": 1,
|
||||
"additionalProperties": { "$ref": "#/definitions/Operation" }
|
||||
},
|
||||
"Operation": {
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/OperationInfo" },
|
||||
{ "$ref": "#/definitions/OperationImpl" }
|
||||
]
|
||||
},
|
||||
"OperationInfo": {
|
||||
"properties": {
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"summary": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"externalDocs": {
|
||||
"$ref": "https://spec.openapis.org/oas/3.0/schema/2021-09-28#/definitions/ExternalDocumentation"
|
||||
}
|
||||
}
|
||||
},
|
||||
"OperationImpl": {
|
||||
"oneOf": [
|
||||
{ "$ref": "#/definitions/WithHandler" },
|
||||
{ "$ref": "#/definitions/WithRedirect" }
|
||||
]
|
||||
},
|
||||
"WithHandler": {
|
||||
"required": [ "handler" ],
|
||||
"properties": {
|
||||
"handler": {
|
||||
"$ref": "#/definitions/MWObjectSpec"
|
||||
}
|
||||
}
|
||||
},
|
||||
"MWObjectSpec": {
|
||||
"type": "object",
|
||||
"description": "An object-spec for use with the wikimedia/object-factory package.",
|
||||
"properties": {
|
||||
"class": {
|
||||
"type": "string",
|
||||
"description": "PHP class name of the object to create. If 'factory' is also specified, it will be used to validate the object."
|
||||
},
|
||||
"factory": {
|
||||
"type": [ "string", "array" ],
|
||||
"description": "Factory method for creating the object (a PHP callable)."
|
||||
},
|
||||
"args": {
|
||||
"type": "array",
|
||||
"description": "Arguments to pass to the constructor or the factory method."
|
||||
},
|
||||
"services": {
|
||||
"type": "array",
|
||||
"item": { "type": "string" },
|
||||
"description": "List of services to pass as arguments. Each name will be looked up in MediaWikiServices."
|
||||
},
|
||||
"optional_services": {
|
||||
"type": "array",
|
||||
"item": { "type": "string" },
|
||||
"description": "List of services to pass as arguments. Each name will be looked up in MediaWikiServices. If the service is unknown the parameter is set to 'null' instead of causing an error."
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"WithRedirect": {
|
||||
"required": [ "redirect" ],
|
||||
"properties": {
|
||||
"redirect": {
|
||||
"type": "object",
|
||||
"required": [ "path" ],
|
||||
"properties": {
|
||||
"path": { "type": "string" },
|
||||
"code": { "type": "integer" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
Schema {#schema}
|
||||
======
|
||||
|
||||
The most up-to-date schema for the tables in the database
|
||||
will always be `tables.sql` in the maintenance directory,
|
||||
which is called from the installation script.
|
||||
|
||||
That file has been commented with details of the usage for
|
||||
each table and field.
|
||||
|
||||
Historical information and some other notes are available at
|
||||
<https://www.mediawiki.org/wiki/Manual:Database_layout>.
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
This is an XML Schema description of the format
|
||||
used by MediaWiki's exportSites.php and importSites.php
|
||||
scripts.
|
||||
-->
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:mwsl="http://www.mediawiki.org/xml/sitelist-1.0/"
|
||||
targetNamespace="http://www.mediawiki.org/xml/sitelist-1.0/"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation xml:lang="en">
|
||||
MediaWiki's export format for site definitions.
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<!-- Our root element -->
|
||||
<element name="sites" type="mwsl:MediaWikiSiteListType">
|
||||
<unique name="GlobalIDConstraint">
|
||||
<selector xpath="mwsl:Site" />
|
||||
<field xpath="mwsl:GlobalID" />
|
||||
</unique>
|
||||
</element>
|
||||
|
||||
<simpleType name="EmptyTagType">
|
||||
<restriction base="string">
|
||||
<length value="0"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="TypedIDType">
|
||||
<simpleContent>
|
||||
<extension base="NCName">
|
||||
<attribute name="type" use="required" type="NCName" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="TypedURIType">
|
||||
<simpleContent>
|
||||
<extension base="anyURI">
|
||||
<attribute name="type" use="required" type="NCName" />
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<complexType name="MediaWikiSiteListType">
|
||||
<sequence>
|
||||
<element name="site" type="mwsl:SiteType"
|
||||
minOccurs="0" maxOccurs="unbounded" />
|
||||
</sequence>
|
||||
<attribute name="version" type="string" use="optional" />
|
||||
</complexType>
|
||||
|
||||
<complexType name="SiteType">
|
||||
<choice maxOccurs="unbounded">
|
||||
<element name="globalid" type="ID" minOccurs="1" maxOccurs="1" />
|
||||
<element name="localid" type="mwsl:TypedIDType" minOccurs="0" />
|
||||
<element name="group" type="NCName" minOccurs="0" maxOccurs="1" />
|
||||
<element name="source" type="NCName" minOccurs="0" maxOccurs="1" />
|
||||
<element name="forward" type="mwsl:EmptyTagType" minOccurs="0" maxOccurs="1" />
|
||||
<element name="path" type="mwsl:TypedURIType" minOccurs="0" />
|
||||
</choice>
|
||||
<attribute name="type" use="optional" type="NCName" />
|
||||
</complexType>
|
||||
|
||||
</schema>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
Sitelist {#sitelist}
|
||||
========
|
||||
|
||||
This document describes the XML format used to represent information about external sites known to a MediaWiki installation. This information about external sites is used to allow "inter-wiki" links, cross-language navigation, as well as close integration via direct access to the other site's web API or even directly to their database.
|
||||
|
||||
Lists of external sites can be imported and exported using the *importSites.php* and *exportSites.php* scripts. In the database, external sites are described by the `sites` and `site_ids` tables.
|
||||
|
||||
The formal specification of the format used by *importSites.php* and *exportSites.php* can be found in the *sitelist-1.0.xsd* file. Below is an example and a brief description of what the individual XML elements and attributes mean:
|
||||
|
||||
```xml
|
||||
<sites version="1.0">
|
||||
<site>
|
||||
<globalid>acme.com</globalid>
|
||||
<localid type="interwiki">acme</localid>
|
||||
<group>Vendor</group>
|
||||
<path type="link">http://acme.com/</path>
|
||||
<source>meta.wikimedia.org</source>
|
||||
</site>
|
||||
<site type="mediawiki">
|
||||
<globalid>de.wikidik.example</globalid>
|
||||
<localid type="equivalent">de</localid>
|
||||
<group>Dictionary</group>
|
||||
<forward/>
|
||||
<path type="page_path">http://acme.com/</path>
|
||||
</site>
|
||||
</sites>
|
||||
```
|
||||
|
||||
|
||||
The XML elements are used as follows:
|
||||
|
||||
- `sites`: The root element, containing a set of site tags. May have a `version` attribute with the value `1.0`.
|
||||
- `site`: A site entry, representing an external website. May have a `type` attribute with one of the following values:
|
||||
+ `unknown`: (default) any website
|
||||
+ `mediawiki`: A MediaWiki site
|
||||
- `globalid`: A unique identifier for the site. For a given site, the same unique global ID must be used across all wikis in a wiki farm (aka wiki family).
|
||||
- `localid`: An identifier for the site, for use on the local wiki. Multiple local IDs may be assigned to a given site. The same local ID can be used to refer to different sites by different wikis on the same farm/family. The `localid` element may have a type attribute with one of the following values:
|
||||
+ `interwiki`: Used as an "interwiki" link prefix, for creating cross-wiki links.
|
||||
+ `equivalent`: Used as a "language" link prefix, for cross-linking equivalent content in different languages.
|
||||
- `group`: The site group (e.g. wiki family) the site belongs to.
|
||||
- `path`: A URL template for accessing resources on the site. Several paths may be defined for a given site, for accessing different kinds of resources, identified by the `type` attribute, using one of the following values:
|
||||
+ `link`: Generic URL template, often the document root.
|
||||
+ `page_path`: (for `mediawiki` sites) URL template for wiki pages (corresponds to the target wiki's `$wgArticlePath` setting)
|
||||
+ `file_path`: (for `mediawiki` sites) URL pattern for application entry points and resources (corresponds to the target wiki's `$wgScriptPath` setting).
|
||||
- `forward`: Whether using a prefix defined by a `localid` tag in the URL will cause the request to be redirected to the corresponding page on the target wiki (currently unused). E.g. whether <http://wiki.acme.com/wiki/foo:Buzz> should be forwarded to <http://wiki.foo.com/read/Buzz>. (CAVEAT: not yet implement, can be specified but has no effect)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
!README
|
||||
!.gitignore
|
||||
!/.vsls.json
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"$schema": "http://json.schemastore.org/vsls",
|
||||
"gitignore":"hide",
|
||||
"excludeFiles":[
|
||||
"!*"
|
||||
],
|
||||
"hideFiles":[
|
||||
"!*"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"wikimedia/client-es5",
|
||||
"wikimedia/jquery",
|
||||
"wikimedia/mediawiki"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
node_modules/
|
||||
vendor/
|
||||
composer.lock
|
||||
|
||||
# Editors
|
||||
*.kate-swp
|
||||
*~
|
||||
\#*#
|
||||
.#*
|
||||
.*.swp
|
||||
.project
|
||||
.buildpath
|
||||
.classpath
|
||||
.settings
|
||||
cscope.files
|
||||
cscope.out
|
||||
*.orig
|
||||
## NetBeans
|
||||
nbproject*
|
||||
project.index
|
||||
## Sublime
|
||||
sublime-*
|
||||
sftp-config.json
|
||||
/.eslintcache
|
||||
/.stylelintcache
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue