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
edit

Testing

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"
	}
}