MediaWiki Introduction 2023: Difference between revisions
mNo edit summary |
save VE corrupted edit surface |
||
| Line 133: | Line 133: | ||
Before you write your first patch: |
Before you write your first patch: |
||
# Download MediaWiki. I recommend [[Quickstart]] to install MediaWiki with only Git and PHP. No Docker, Apache, or MySQL! |
# Download MediaWiki. I recommend [[Quickstart]] to install MediaWiki with only Git and PHP. ''(No Docker, Apache, or MySQL needed!)'' |
||
# [[Manual:PHP unit testing/Running the tests|Run PHPUnit]] |
# [[Manual:PHP unit testing/Running the tests|Run PHPUnit]]. This checks that everything got installed correctly. From your mediawiki directory, run <code>composer phpunit -- tests/phpunit/includes/ResourceLoader/</code> |
||
# [[Manual:JavaScript unit testing|Run QUnit]] |
# [[Manual:JavaScript unit testing|Run QUnit]], by browsing to http://localhost:4000/index.php/Special:JavaScriptTest |
||
# Add the [[Extension:Examples|Examples extension]] to your MediaWiki site. |
# Add the [[Extension:Examples|Examples extension]] to your MediaWiki site. |
||
=== Excercise 1: Edit a localisation message === |
=== Excercise 1: Edit a localisation message === |
||
# Browse http://localhost:4000/index.php/Special:HelloWorld |
# Browse to http://localhost:4000/index.php/Special:HelloWorld |
||
# Change the |
# Change the page title by editing the "example-helloworld" message in the <code>mediawiki/extensions/examples/i18n/en.json</code> file. |
||
# Refresh Special:HelloWorld in the browser and notice the change. |
# Refresh Special:HelloWorld in the browser and notice the change. |
||
✅ Done! |
✅ Done! Now, how and why did that work? |
||
==== '''How do extensions work?''' ==== |
==== '''How do extensions work?''' ==== |
||
The <code>wfLoadExtension</code> line you added to LocalSettings, instructs MediaWiki to load <code>extension.json</code> from a given extension. This is the one-stop shop for everything |
The <code>wfLoadExtension</code> line you added to LocalSettings, instructs MediaWiki to load <code>extension.json</code> from a given extension. This is the one-stop shop for everything related to an extension. Everything an extension can do starts in, and is discoverable from, this file. Have a look at <code>mediawiki/extensions/examples/extension.json</code>. |
||
The first few fields are metadata you may recognise from Special:Version, such as the authors, the url, and the "type" that each extension is grouped under. "SpecialPages" is the registry where |
The first few fields are metadata you may recognise from [http://localhost:4000/index.php/Special:Version Special:Version], such as the authors, the url, and the "type" that each extension is grouped under. The "SpecialPages" field is the registry where we declare our special pages. "AutoloadNamespaces" is similarly a registry, where we define a PHP namespace the PHP classes in our repository. These are then discovered and loaded automatically by MediaWiki. |
||
For later: [[Manual:Extension registration]], [[Manual:Extension.json/Schema]], [[Best practices for extensions]], [[Manual:Coding conventions/PHP]]. |
|||
==== How do special pages work? ==== |
==== How do special pages work? ==== |
||
As we learned in Part 1, [[Special:SpecialPages]] enumerates all special pages. Both |
As we learned in Part 1, [[Special:SpecialPages]] enumerates all special pages. Both from MediaWiki core, and from any extensions you've installed. The <code>examples/extension.json</code> file registers "Special:HelloWorld", which you can visit in your browser at http://localhost:4000/index.php/Special:HelloWorld. |
||
| ⚫ | MediaWiki takes care of interpreting and routing URLs. This URL is for the "Special" namespace, which MediaWiki looks up in the SpecialPages registry. MediaWiki loves registries like these, which automatically take care of the heavy-lifting, allowing you to focus on business logic instead of boilerplate. |
||
The <code>examples/extension.json</code> file registers "Special:HelloWorld" which you can visit in your browser at http://localhost:4000/index.php/Special:HelloWorld |
|||
| ⚫ | |||
| ⚫ | MediaWiki takes care of interpreting and routing URLs. This URL is for the "Special" namespace, which MediaWiki looks up in the SpecialPages registry. MediaWiki loves |
||
| ⚫ | |||
==== How does localisation work? ==== |
==== How does localisation work? ==== |
||
* You can debug the localisation system any time by using <code>uselang=qqx</code>. This is harmless and works on the [https://en.wikipedia.org/wiki/Sandpit?uselang=qqx |
* You can debug the localisation system any time by using <code>uselang=qqx</code>. This is harmless and works on the [https://en.wikipedia.org/wiki/Sandpit?uselang=qqx&safemode=on live Wikipedia], too. |
||
* Visit [http://localhost:4000/index.php/Special:HelloWorld?uselang=qqx Special:HelloWorld?uselang=qqx] to see which message keys are used. |
* Visit [http://localhost:4000/index.php/Special:HelloWorld?uselang=qqx Special:HelloWorld?uselang=qqx] to see which message keys are used. |
||
* |
* These messages come from the <code>/i18n/en.json</code> file in the examples repo. |
||
=== Excercise 2: Create a |
=== Excercise 2: Create a localisation message === |
||
# Add a key to <code>/i18n/en.json</code> with a short sentence as the value. For example "example-goodbye": "That's all Folks!". |
# Add a new key to <code>/i18n/en.json</code> with a short sentence as the value. For example <code>"example-goodbye": "That's all Folks!"</code>. |
||
# |
# Render this message as the second paragraph on the page, by adding a statement to SpecialHelloWorld::execute. Look at the existing intro message for how to do this. |
||
# Refresh Special:HelloWorld in the browser and notice the |
# Refresh Special:HelloWorld in the browser and notice the second paragraph. |
||
✅ Done! |
✅ Done! |
||
| Line 177: | Line 175: | ||
#Browse to your wiki's Main Page at http://localhost:4000/ and notice the "Hi there" banner. |
#Browse to your wiki's Main Page at http://localhost:4000/ and notice the "Hi there" banner. |
||
#Edit LocalSettings.php and disable this feature by adding <code>$wgExampleEnableWelcome = false;</code> . |
#Edit LocalSettings.php and disable this feature by adding <code>$wgExampleEnableWelcome = false;</code> . |
||
# |
# Hard-refresh your wikis' Main Page in the browser and notice the the banner is gone. |
||
# Comment out or remove the line |
# Comment out or remove the LocalSettings line to re-enable the banner. Refresh to see it come back. |
||
✅ Done! How did |
✅ Done! How did that work? |
||
==== |
==== Extensions can be configurable ==== |
||
This feature flag is defined in <code>examples/extension.json</code> as "ExampleEnableWelcome", under "config". |
This feature flag is defined in <code>examples/extension.json</code> as "ExampleEnableWelcome", under "config". This flag has a default of <code>true</code>. |
||
This "config" map is another one of those automated registries that does heavy lifting for you. It takes care of validation, documentation, default values, applying LocalSettings, and letting you access the result in PHP code (for the current wiki) via <code>MediaWikiServices->getMainConfig</code>. |
This "config" map is another one of those automated registries that does heavy lifting for you. It takes care of validation, documentation, default values, applying LocalSettings, and letting you access the result in PHP code (for the current wiki) via <code>MediaWikiServices->getMainConfig</code>. |
||
As the site admin, you can change the value of any configuration value |
As the site admin, you can change the value of any configuration value by editing LocalSettings, and setting variables named as "wg" (wiki global) + the configuration key. For example, $wgExampleEnableWelcome in this case. |
||
For later: [[Manual:Configuration for developers]], [[Manual:Extension.json/Schema#config]]. |
|||
=== Excercise 4: Edit a hook handler === |
=== Excercise 4: Edit a hook handler === |
||
We're going to change the "Hi there" banner to display on special pages instead of articles. Notice the banner is currently shown on the [http://localhost:4000/ Main Page], but not at [http://localhost:4000/index.php/Special:HelloWorld Special:HelloWorld]. |
|||
#Edit <code>function onBeforePageDisplay</code> in <code>examples/includes/Hooks.php</code>, and change the conditi on |
|||
#Make it "welcome" you on special pages instead of articles. |
|||
# |
#Refresh and noti See also [[Manual:Namespace#Built-in namespaces|Namespaces]] (remember from Part 1) the change on Special:HelloWorld and Main Page. |
||
✅ Done! |
✅ Done! |
||
Revision as of 14:42, 8 October 2024
MediaWiki Introduction 2023 is a 3-part video series by Timo Tijhof, recorded in December 2023 for the MediaWiki Code Jam.
Part 1: MediaWiki core concepts
Watch on Wikimedia Commons. • Watch on YouTube
Timestamps:
00:00 Outline 00:50 Database schema 01:37 Users 02:55 Preferences 04:12 Localisation 05:02 Permissions 08:50 Bot passwords 10:10 Logging 11:58 Comments 12:35 Recent changes 15:39 Pages 16:00 Namespaces 18:14 Revisions 18:20 Example: Save an edit 19:59 Example: View a page 20:52 Link tables 21:02 Categories 24:20 Templates 25:05 Image links 25:59 GLAM 26:43 External links 27:40 Statistics 28:02 Search 29:14 JobQueue 31:58 Multimedia
High-level product and architecture perspective. Component walk-through.
- Database layout
- Who writes Wikipedia
- Why create an account
- CSSJanus docs
- CSSJanus demo
- Permissions
- Change user rights
- Bot passwords
- Logging
- No original research
- Recent changes
- RCFeed
- Listen to Wikipedia
- CodePen
- ClueBot
- Namespaces
- Special pages
- Page table
- Revision table
- Text table
- External storage
- Example category
- Everything is a wiki page
- GLAM
- Glamorous tool
- Example photo
- Statistics
- JobQueue
- MediaWiki Engineering - Performance practices
- Multimedia
Part 2: Wikipedia's extensions
Watch on Wikimedia Commons. • Watch on YouTube
Timestamps:
00:00 Outline 00:25 What is an extension? 01:52 How to install an extension? 02:01 Install WikiEditor 02:54 Install VisualEditor 03:58 Wikipedia's extensions 04:10 CentralAuth 04:38 Echo 04:56 OAuth for MediaWiki 05:40 Editor extensions 05:48 Parser extensions 06:37 Cite extension 07:37 EasyTimeline 07:56 InputBox extension 08:38 Scribunto 09:38 Faster editing performance 11:24 Media handlers 11:31 TimedMediaHandler 11:42 3D extension for MediaWiki 11:57 Spam prevention extensions 12:35 Gadgets 13:05 Gadget demo 13:41 Gadget examples
What is an extension?
How to install an extension in two easy steps.
Walk-through the installed extensions via Wikipedia's Special:Version page.
- What is an extension
- WikiEditor extension
- VisualEditor extension
- Wikipedia's extensions
- CentralAuth
- Echo
- Cite
- EasyTimeline
- EasyTimeline example: Version lifecycle
- InputBox
- InputBox example: Incident status
- Scribunto
- Lua example: SchemaDiagram
- What Lua scripting means for Wikimedia (2013)
- How we made editing Wikipedia twice as fast (2014)
- Save Timing in Grafana
- TimedMediaHandler
- 3D extension
- AbuseFilter
- Gadgets
- Gadget example: RTRC
- Gadget example: Stockphoto
- Half-timbered mansion, by Radomianin
Part 3: Write your first patch
Are you ready to write your first "meaningful" patch?
This is not a minimal example for learning Git, or contributing a typo-fix to MediaWiki (which you could do by cloning the Git repo, directly modifying a file, and relying on a code reviewer to test/merge it for you). Rather, the below prepares you to understand other people's patches (as manager), or to prepare you for becoming an active MediaWki developer. As such, it includes learning how to preview the impact of your change in a web browser, and running the unit tests on your machine.
Homework
Before you write your first patch:
- Download MediaWiki. I recommend Quickstart to install MediaWiki with only Git and PHP. (No Docker, Apache, or MySQL needed!)
- Run PHPUnit. This checks that everything got installed correctly. From your mediawiki directory, run
composer phpunit -- tests/phpunit/includes/ResourceLoader/ - Run QUnit, by browsing to http://localhost:4000/index.php/Special:JavaScriptTest
- Add the Examples extension to your MediaWiki site.
Excercise 1: Edit a localisation message
- Browse to http://localhost:4000/index.php/Special:HelloWorld
- Change the page title by editing the "example-helloworld" message in the
mediawiki/extensions/examples/i18n/en.jsonfile. - Refresh Special:HelloWorld in the browser and notice the change.
✅ Done! Now, how and why did that work?
How do extensions work?
The wfLoadExtension line you added to LocalSettings, instructs MediaWiki to load extension.json from a given extension. This is the one-stop shop for everything related to an extension. Everything an extension can do starts in, and is discoverable from, this file. Have a look at mediawiki/extensions/examples/extension.json.
The first few fields are metadata you may recognise from Special:Version, such as the authors, the url, and the "type" that each extension is grouped under. The "SpecialPages" field is the registry where we declare our special pages. "AutoloadNamespaces" is similarly a registry, where we define a PHP namespace the PHP classes in our repository. These are then discovered and loaded automatically by MediaWiki.
For later: Manual:Extension registration, Manual:Extension.json/Schema, Best practices for extensions, Manual:Coding conventions/PHP.
How do special pages work?
As we learned in Part 1, Special:SpecialPages enumerates all special pages. Both from MediaWiki core, and from any extensions you've installed. The examples/extension.json file registers "Special:HelloWorld", which you can visit in your browser at http://localhost:4000/index.php/Special:HelloWorld.
MediaWiki takes care of interpreting and routing URLs. This URL is for the "Special" namespace, which MediaWiki looks up in the SpecialPages registry. MediaWiki loves registries like these, which automatically take care of the heavy-lifting, allowing you to focus on business logic instead of boilerplate.
MediaWiki found and instantiated the SpecialHelloWorld class for you, and wrapped the skin (sidebar, navigation, styling etc) around its output. It hands control over to you in the SpecialHelloWorld::execute() method. Have a look in examples/includes/SpecialHelloWorld.php.
How does localisation work?
- You can debug the localisation system any time by using
uselang=qqx. This is harmless and works on the live Wikipedia, too. - Visit Special:HelloWorld?uselang=qqx to see which message keys are used.
- These messages come from the
/i18n/en.jsonfile in the examples repo.
Excercise 2: Create a localisation message
- Add a new key to
/i18n/en.jsonwith a short sentence as the value. For example"example-goodbye": "That's all Folks!". - Render this message as the second paragraph on the page, by adding a statement to SpecialHelloWorld::execute. Look at the existing intro message for how to do this.
- Refresh Special:HelloWorld in the browser and notice the second paragraph.
✅ Done!
Excercise 3: Make a config change
- Browse to your wiki's Main Page at http://localhost:4000/ and notice the "Hi there" banner.
- Edit LocalSettings.php and disable this feature by adding
$wgExampleEnableWelcome = false;. - Hard-refresh your wikis' Main Page in the browser and notice the the banner is gone.
- Comment out or remove the LocalSettings line to re-enable the banner. Refresh to see it come back.
✅ Done! How did that work?
Extensions can be configurable
This feature flag is defined in examples/extension.json as "ExampleEnableWelcome", under "config". This flag has a default of true.
This "config" map is another one of those automated registries that does heavy lifting for you. It takes care of validation, documentation, default values, applying LocalSettings, and letting you access the result in PHP code (for the current wiki) via MediaWikiServices->getMainConfig.
As the site admin, you can change the value of any configuration value by editing LocalSettings, and setting variables named as "wg" (wiki global) + the configuration key. For example, $wgExampleEnableWelcome in this case.
For later: Manual:Configuration for developers, Manual:Extension.json/Schema#config.
Excercise 4: Edit a hook handler
We're going to change the "Hi there" banner to display on special pages instead of articles. Notice the banner is currently shown on the Main Page, but not at Special:HelloWorld.
- Edit
function onBeforePageDisplayinexamples/includes/Hooks.php, and change the conditi on - Refresh and noti See also Namespaces (remember from Part 1) the change on Special:HelloWorld and Main Page.
✅ Done!
How do hooks work?
In extension.json, "Hooks" adds to a central registry, "HookHandlers" is a mapping local to your own extension.
MediaWiki will call your Hooks.php#onSomething method, now it's our turn. Follow mentions of "BeforePageDisplay" from extension.json to Hooks.php
Excercise 5: Improve test and fix the bug
- The welcome message currently greets you with the wrong day. Improve the QUnit test by using assert.strictEquals.
- Copy the "actual" value from Special:JavaScriptTest, and edit the test file to make it the "expected" value, except with the correct day. The test should now fail.
- Try to fix this bug in
welcome.js, and notice the tests passing afterwards. Also verify that it works correctly on the Main Page (or Special:HelloWorld, depending on whether you changed $wgExampleEnableWelcome earlier).
✅ Done! Now let's take a look underneath.
How do extensions define extra ResourceLoader modules?
- extension.json ("ResourceModules" is another registry, "dependencies", "packageFiles")
- ResourceLoader/Developing with ResourceLoader
- onBeforePageDisplay calls OutputPage::addModule, which is responsible for changing the HTML so that your module is loaded on the page.
- The
welcome.jsfile andstyles.cssfiles are part of this module.
How do extension define frontend unit tests?
- ext.Example.welcome.test.js (find it in extension.json)
- Run via Special:JavaScriptTest?filter=welcome (filter optional, but helps focus and runs faster)
🎉 Congratulations, you are well on your journey to becoming a MediaWiki hacker!
If you have a mentor or onboarding buddy, you can share your work via a Phabricator paste:
- Copy the output from
git diff. For example,git diff | pbcopyon macOS. Or on Linux/Windows, save it as a temporary file withgit diff > tmp.txt, then open that file in your text editor, select all, and copy that to your clipboard. - Create Phabricator paste