User:SamanthaNguyen/Guides/Writing an extension

The very first stepEdit

To ease this process of writing your very own extension, you will be using the BoilerPlate extension. It is intended to provide a template for new extensions. This extension follows the best practices for extensions, such as using the standard directory structure and following Wikimedia's standard coding conventions. We will remove Git information from BoilerPlate. In your local MediaWiki environment, run the following commands, starting from the very top to the very bottom:

cd extensions
git clone https://gerrit.wikimedia.org/r/mediawiki/extensions/BoilerPlate.git
cp -r BoilerPlate ./MyExtension
rm -rf ./MyExtension/.git

After these steps, you should rename the /MyExtension folder to the name of your actual extension. After you have finished renaming your folder, continue reading on!

Understanding the filesEdit

MediaWiki's directory and file structure is unique for extensions, and may contain many files you may not be familiar with yet. This section attempts to help clarify what each folder and file is meant to do.

Files have a unique meaning based on their file extension, which are the letters after the dot symbol. Here are some file types explained:

  • Files ending in the .md file extension mean they are written in Markdown, a language for formatting plain text.
  • Files ending in the .json file extension mean they are written in JSON, an open format for storing information. These are meant to be readably by humans as well as machines.
  • Files ending in the .xml file extension mean they are written in XML, a markup language meant for also storing information. These are meant to be readable by humans as well as machines. The XML syntax looks similar to HTML, but is not exactly the same.

Markdown and text filesEdit

  • README.md: This file is the default file that users go to to see a summary of what the extension is about.
  • CODE_OF_CONDUCT.md: All software hosted on Wikimedia are covered under the Code of Conduct. If your software is hosted on Wikimedia, this file must be included to explicitly denote this fact.

Software license files (COPYING or LICENSE)Edit

  • The COPYING (or LICENSE) file contains legal information about the license this software is covered under. For an open-source extension, you must use an open-source license, such as the MIT License, GNU GPL license, or the Apache License. You can read more about licensing your software at https://choosealicense.com/. Most MediaWiki extensions use GNU GPL version 2 or later, but you are free to choose any open-source license.

.gitignore, .gitreviewEdit

These files are both related to Git, where Git is a tool (known as a version-control system) that helps keep track of changes made in software.

  • The .gitignore file specifies which files should be ignored by Git. For the most part, you will usually not need to modify this file, and can freely ignore it.
  • The .gitreview file is a file used by Gerrit, which is the platform that Wikimedia uses to review code. Feel free to also ignore this file. You will never need to modify this file.

extension.jsonEdit

This file is used by MediaWiki to allow registering an extension or skin. The extension.json is defined by a schema, so that the MediaWiki knows how to work with it. This allows loading the extension or skin in LocalSettings.php.

Your extension.json file should look like the file below. You should also do the following things:

  • Replace instances of "BoilerPlate" with the name of your own extension. Keep the letter casing consistent. The name of the extension should be in CamelCase.
  • Replace "Your Name" with the name that you prefer to go by. This can be your chosen name or an online username/nickname. This is completely up to you!
{
	"name": "BoilerPlate",
	"author": [
		"Your Name"
	],
	"url": "https://www.mediawiki.org/wiki/Extension:BoilerPlate",
	"descriptionmsg": "boilerplate-desc",
	"license-name": "GPL-2.0-or-later",
	"type": "other",
	"requires": {
		"MediaWiki": ">= 1.32.0"
	},
	"AutoloadNamespaces": {
		"MediaWiki\\Extension\\BoilerPlate\\": "includes/"
	},
	"config": {
		"BoilerPlateEnableFoo": {
			"description": "Enable the Foo feature.",
			"value": true
		},
		"BoilerPlateVandalizeEachPage": {
			"description": "Write 'BoilerPlate was here' on each page",
			"value": false
		}
	},
	"HookHandlers": {
		"BoilerPlateHooks": {
			"class": "MediaWiki\\Extension\\BoilerPlate\\Hooks"
		}
	},
	"Hooks": {
		"BeforePageDisplay": "BoilerPlateHooks"
	},
	"MessagesDirs": {
		"BoilerPlate": [
			"i18n"
		]
	},
	"ResourceFileModulePaths": {
		"localBasePath": "resources",
		"remoteExtPath": "BoilerPlate/resources"
	},
	"ResourceModules": {
		"ext.boilerPlate": {
			"dependencies": [],
			"messages": [],
			"styles": [],
			"scripts": []
		}
	},
	"manifest_version": 2
}

Files related to package managementEdit

composer.jsonEdit

The composer.json file is a file for managing PHP packages published under Composer, a package manager for PHP. In MediaWiki, we use this file to install tools to help us lint our code to conform to the standard PHP coding conventions using Codesniffer, as well as check for executable files with MinusX.

As an extension developer, you usually don't have to worry about keeping up with the latest version for each package. When an extension is hosted in Wikimedia, a tool called Libraryupgrader will periodically update all repositories to use the latest versions of the packages.

You will need to run composer update when you copy the BoilerPlate extension into your own extension, as Composer allows running automated tasks that can be defined in the composer.json file, under "scripts".

Your composer.json file should look like this:

{
	"require-dev": {
		"mediawiki/mediawiki-codesniffer": "31.0.0",
		"mediawiki/minus-x": "1.1.0",
		"php-parallel-lint/php-console-highlighter": "0.5.0",
		"php-parallel-lint/php-parallel-lint": "1.2.0"
	},
	"scripts": {
		"test": [
			"parallel-lint . --exclude vendor --exclude node_modules",
			"minus-x check .",
			"phpcs -p -s"
		],
		"fix": [
			"minus-x fix .",
			"phpcbf"
		]
	}
}

package.json, package-lock.jsonEdit

Both of these files are files defined by npm, a package manager for JavaScript (known as JS for short). If you write JS, you may be familar with these two files. MediaWiki is however unique in that (most) extensions are not published npm packages; rather, MediaWiki uses package.json to provide tools for the developer in linting their JS and CSS code. It is also used to validate the i18n JSON files.

  • You will not need to update these packages yourself. As mentioned above, Libraryupgrader will periodically upgrade all packages to the latest stable version, for software repositories that are hosted on Wikimedia.
  • For security, the package-lock.json file is always committed to Git. You should not manually edit this file. This will be automatically updated by npm, by running npm update / npm install.
  • Your package.json file should look similar to this:
{
	"private": true,
	"scripts": {
		"test": "grunt test"
	},
	"devDependencies": {
		"eslint-config-wikimedia": "0.17.0",
		"grunt": "1.3.0",
		"grunt-banana-checker": "0.9.0",
		"grunt-eslint": "23.0.0",
		"grunt-stylelint": "0.15.0",
		"stylelint-config-wikimedia": "0.10.1"
	}
}

Files related to code stylingEdit

.phpcs.xmlEdit

This file is the configuration file used by Codesniffer. A sniff is a unit of code meant to look for code styling issues in PHP, and let the developer know how they should format their code.

  • Developers can detect code style issues automatically by running composer test, which will automatically run PHPCS as well as MinusX.
  • Some code styling issues in PHP can be automatically fixed, which can be done by running composer fix. MinusX will also fix any issues with files that are detected to be executable.

Gruntfile.js, .eslintrc.json, .stylelintrc.jsonEdit

  • Gruntfile.js is a configuration file used by Grunt, which is a tool written in JS meant to help run automated tasks. It is also used to detect undocumented i18n messages, which will be discussed later.
  • .eslintrc.json is a configuration file used by ESLint, which is a tool used to detect code style issues in JS files.
  • .stylelintrc.json is a configuration file used by Stylelint, which is a tool used to detect code style issues in CSS and Less. (Stylelint can also detect other CSS-like languages, but CSS and Less are the only types used in MediaWiki).

Wikimedia has two npm packages to help developers confirm with these styles:

Understanding the directoriesEdit

/i18nEdit

This folder is called i18n, and stands for internationalization (“i”, 18 letters, “n”). It contains all localization files. Every localization file is in JSON format, and uses a standard language code as the file name to identify the language. By default, this will contain two files:

  • /i18n/en.json: This file contains all messages defined by the extension in English.
  • /i18n/qqq.json: This file contains documentation for every message in en.json. For every message key in English, there should be an equivalent message key in this file. It should provide contextual information on how the message is used, where the message is used, and describe each parameter, if there are any parameters.
Examples
If you want to translate messages into Vietnamese, you would create a file named vi.json.
If you want to translate messages into Spanish, you would create a file named es.json.

/includes (or /src)Edit

This folder is where all PHP files go. This file can also be called src, which stands for "source", as in source code.

To provide some history: This folder been coined includes in the past as PHP originally didn't have a system for autoloading classes since Composer did not exist at the time. PHP's way of loading files is using the include keyword (official PHP manual on "include" keyword).

/resources (or /modules)Edit

This folder is where all CSS/Less and JS files go. If the extensions provides any images, they can also provide them under here.

/testsEdit

This folder contains unit tests and integration tests.

  • Unit testing is a way of testing a single unit of code, or component of code, in software. This method of testing is intended to make sure there aren't any bugs and that the unit of code works the way it is designed.
  • Integration testing is a way of testing multiple units of code to make sure they work together, and do what they are designed to do together.

Choosing the type of extension to createEdit

  • APIs:
    • Action API:
    • REST API:
  • Content handlers:
  • Parser-related extensions:
    • Extension tags:
    • Magic words:
    • Parser functions:
    • Variables:
  • Special pages: