Creating a MediaWiki Skin

From Exterior Memory
Jump to: navigation, search
This article was written in February 2012. This article is no longer updated, and may be outdated.
MediaWiki's manual in Skinning is out-of-date; this page contains some advice how to create a custom skin in MediaWiki 1.18. Daniel Friesen created a similar Mediawiki subskin tutorial as well as a Mediawiki custom skinning tutorial. Given that Daniel is rather knowledgeable on the topic (while this was my first skinning attempt), I recommend you check it out.

File Locations

All skin files are located in the skins subfolder of the MediaWiki installation directory (see $wgStylePath and $wgStyleDirectory for actual location.)

There are two files for each skin in that folder:

  • MySkin.php: The main file, defining the page layout.
  • MySkin.deps.php: a workaround for a bug in the APC opcode cache on PHP 5

For all other files, a subfolder with the skin's name should be created - for example:

  • skins/myskin/Resources.php: The skin's resource description, as used by MediaWiki's ResourceLoader
  • skins/myskin/screen.css: The skin's main style sheet for screens (desktops and phones)
  • skins/myskin/print.css: The skin's main style sheet for printed media
  • skins/myskin/myskin.js: The skin's JavaScript code.

Creating a Custom Skin

The easiest start is to copy an existing skin, such as Vector, and start from there:

cp skins/Vector.php skins/MySkin.php
cp skins/Vector.deps.php skins/MySkin.deps.php
cp -r skins/vector skins/myskin

Open skins/MySkin.php and replace occurrences of Vector with the name of your skin (MySkin in this example). Be careful about case dependencies (The name of your skin is CamelCased, such as MySkin; The identifier of your skin is lowercase, such as myskin).

Add a header:

/*
 * Memory - Custom skin based on Vector, with simplified layout and brighter colours
 *
 * @file
 * @ingroup Skins
 * @version 0.2.0
 * @author Freek Dijkstra (http://www.macfreek.nl/memory/Exterior_Memory:Skin)
 * @license public domain (http://creativecommons.org/publicdomain/zero/1.0/)
 */

Change the SkinVector and VectorTemplate:

/**
 * SkinTemplate class for MySkin skin
 * @ingroup Skins
 */
class SkinMySkin extends SkinTemplate {

    var $skinname = 'myskin', $stylename = 'myskin',
        $template = 'MySkinTemplate', $useHeadElement = true;

    /**
     * Initializes output page and sets up skin-specific parameters
     * @param $out OutputPage object to initialize
     */
    public function initPage( OutputPage $out ) {
        parent::initPage( $out );
        $out->addModuleScripts( 'skins.myskin' );
    }

    /**
     * Load skin and user CSS files in the correct order
     * @param $out OutputPage object
     */
    function setupSkinUserCss( OutputPage $out ){
        parent::setupSkinUserCss( $out );
        $out->addModuleStyles( 'skins.myskin' );
    }
}

/**
 * QuickTemplate class for MySkin skin
 * @ingroup Skins
 */
class MySkinTemplate extends BaseTemplate {
    ...
}

The variables have the following meaning:

skinname
Name of the skin. Should probably be lowercase. Used for example in mw:Manual:$wgDefaultSkin in LocalSettings.php.
stylename
Name of the stylesheet. Seems no longer used with the ResourceLoader since MediaWiki 1.17. I recommend to set it to the same value as skinname.
template
Name of the template class that defines the actual layout of a webpage. In this example MySkinTemplate

You also want to set the module name in the addModuleScripts() and addModuleStyles() to the name of a new resource loader module associated with your skin. A good choice is skin. followed by $skinname. In this example skin.myskin. The next section described how to define a resource loader module.

Resource Loader File Specification

MediaWiki 1.17 and higher use the Resource Loader, which optimises the loading of CSS stylesheets and Javascripts.

ResourceLoader defines modules, which have associated files. A module can be an extension, Special page, JSON query or skin. The default modules are defined in resources/Resource.php.

If you change the module name in the addModuleScripts() or addModuleStyles() functions, but do not define an module, you will get this error:

PHP Fatal error: Call to a member function getGroup() on a non-object in /var/www/macfreek.nl/memory/includes/OutputPage.php on line 2958

You can either add your module definition to resources/Resource.php, but it is recommended to create a short PHP file in the skin directory called Resources.php, which defines $wgResourceModules, and include this file from LocalSettings.php. The syntax of $wgResourceModules is decribed in the $wgResourceModules manual page.

Create skins/myskin/resourcemodules.php:

<?php
/*
 * Definition of resources (CSS and Javascript) required for this skin.
 * This file must be included from LocalSettings.php since that is the only way
 * that this file is included by loader.php
 */
global $wgResourceModules, $wgStylePath, $wgStyleDirectory;
$wgResourceModules['skins.myskin'] = array(
   'styles' => array( 'vector/screen.css' => array( 'media' => 'screen' ),
                      'myskin/screen.css' => array( 'media' => 'screen') ),
   'scripts' => 'vector/vector.js',
   'remoteBasePath' => $wgStylePath,
   'localBasePath' => $wgStyleDirectory,
);
?>

Add to LocalSettings.php:

 require_once("$IP/skins/myskin/resourcemodules.php");

You should not define $wgResourceModules in MySkin.php as some sources suggest. The reason is that load.php, the script that actually delivers the stylesheet or JavaScript does not include MySkin.php, resulting in an empty stylesheet or JavaScript, at least for MediaWiki 1.18.