User:TChin (WMF)/MediaWiki Tidbits

Useful MediaWiki Dev Tidbits edit

Disclaimer: This is a brain dump. Most of this stuff I'm writing from memory and the information can be outdated.

MediaWiki edit

Internationalization vs Localization edit

  • Internationalization: Designing software so it can be adapted to different languages without engineering changes
    • MediaWiki passes keys and params around that represent localizable strings
  • Localization: The process of adapting internationalized software for a language/region
    • MediaWiki then converts the key into the localized string using a metric crap ton of json files
  • We are currently trying to separate the logic that does internationalization from the logic that does localization
Message vs MessageValue edit
  • Message does both internationalization and localization (messy and bad, uses global state which is terrible for testing)
  • MessageValue is a new way to store message data independent of MediaWiki and without the messy formatting logic
  • Formatter logic now stored in a separate TextFormatter
  • Old Way:
wfMessage( 'message-key' )->params( ... )
  ->inContentLanguage()
  ->text();

  • New Way:
$textFormatter = MediaWikiServices::getMessageFormatterFactory()
  ->getTextFormatter( 'en' );
$textFormatter->format(
  MessageValue::new( 'message-key' )->textParams( ... )
);

Interface Explanations edit

  • PageReference: Potentially viewable or linkable object (could be an interwiki link)
  • PageIdentity: A page that may exist (could be a special page)
  • ProperPageIdentity: An editable page (not special page) that could exist (may not be created yet)
  • PageRecord: A loaded page from the database

Revision Confusion edit

  • Null edit - edit with nothing that triggers a page to be re-parsed, so may change content but don’t do a revision (i.e: a transcluded template was updated)
  • Null revision - create a revision with the exact same content as before, so no update, but just to put a marker into the history (i.e: restoring the history)
  • PageUpdater is a builder that does page updates. DerivedPageDataUpdater is the state of the page update from the page update builder and a service that executes updates (although we want to split them)
  • RevisionRecord is how revisions are stored for a page
    • Slots are what specific sections have been saved

When Does Parsing Happen? edit

  • MediaWiki uses the roundtrip time from saving a page and redirecting the user to actually render the page
  • We have a lot of mechanisms to defer the parsing
  • But in reality, certain things have to happen before you save the page
    • For example, hooks that look at what links are being added, so you have to parse the page to get them
  • Parsing always happen before saving, even though MediaWiki is designed to do it afterwards
  • If parsing is triggered, we make sure to reuse the parsing output so we don’t parse again, but sometimes it doesn’t work
    • Pages can render their own revision id, which isn’t known until it’s save so we’d have to re-render it again
  • The current way to avoid re-rendering is weird state management in WikiPage

Misc edit

  • You can play with MediaWiki objects and functions with the maintenance/shell.php script (docs)
  • If MediaWiki can't find a newly-created class, run maintenance/generateLocalAutoload.php
  • When modifying extensions, pay attention to any extension under MediaWiki's Language Extension Bundle, as they must be backwards compatible to at least two stable MediaWiki releases

Useful Links edit

Testing edit

PHP edit

  • If you're using XDebug, remember to export XDEBUG_SESSION=1 to enable step debugging for tests
  • You can filter PHP tests using --filter and then part of some testing function
  • Use TestingAccessWrapper to access private and protected methods
  • Data providers can return either an array or yield values
  • Data providers are run before the fake databases are set up, so don't use any code that hits the database (i.e: Title::newFromText)
  • Remember to add the @group Database tag to the top comment block of any MediaWikiIntegrationTestCase tests if you're using the database
  • MediaWikiUnitTestCase does not have access to MediaWikiServices but you can use DummyServicesTrait
  • Mocking static methods is a pain in the ass so try to avoid it
  • If you're testing an extension and it throws an error saying it requires some class within the extension, remember to register the extension in LocalSettings.php
  • If you're testing an extension and it throws an error saying it can't find a database, remember to run the maintenance/update.php script after registering the extension
  • If you're testing something and it throws an error saying something about a 'poolwiki' database, you have WikiBase installed and copied the example settings so you can just comment all that stuff out :P

Javascript edit

  • For Javascript API testing, the secret key you need in .api-testing-config.json can be set in LocalSettings.php with the variable $wgSecretKey
  • If you're using mediawiki-docker-dev (note: different from mediawiki-docker), everything is already set for you and the .api-testing-config.json is:
{
	"base_uri": "http://default.web.mw.localhost:8080/mediawiki/",
	"main_page": "Main_Page",
	"root_user": {
		"name": "Admin",
		"password": "dockerpass"
	},
	"secret_key": "a5dca55190e1c3927e098c317dd74e85c7eced36f959275114773b188fbabdbc",
	"extra_parameters": {
		"xdebug_session": "PHPSTORM"
	}
}