User:Samwilson/Blog/MediaWiki skins

From Wikiversity
Jump to navigation Jump to search

.

I was attempting to create a new skin for MediaWiki 1.19.1 and found the official documentation a bit lacking for the new ways of working, especially with regard to the ResourceLoader. These are some notes I made while figuring it out (which I did, in the end).

Reading list[edit]

Notes[edit]

The new file layout for a skin is supposed to be (according to [Dantman]):

skins/skinname/skinname.php
skins/skinname/SkinName.skin.php
skins/skinname/SkinName.i18n.php

but this is not used for the skins that come with MediaWiki; they use the old-style layout of:

skins/SkinName.php
skins/SkinName.deps.php
skins/skinname/screen.css
skins/skinname/scripts.js
skins/skinname/[etc.]

So after a brief play with the former (because it seems a cleaner layout, and more amenable to revision control) and not being able to get it to work, I set up the latter and had no problems. It's pretty simple to copy an existing skin (as [Freek] recommends), and I got that up and working fine, but was unable to get the new ResourceLoader working.

The minimum structure of SkinName.php is:

<?php
class SkinSkinName extends SkinTemplate {
    var $skinname = 'skinname', $stylename = 'skinname', $template = 'SkinNameTemplate', $useHeadElement = true;
    public function initPage(OutputPage $out) {
        parent::initPage($out);
        $out->addModuleScripts('skins.skinname');
    }
    function setupSkinUserCss(OutputPage $out){
        parent::setupSkinUserCss($out);
        $out->addModuleStyles('skins.skinname');
    }
}
class SkinNameTemplate extends BaseTemplate {
    public function execute() {
        $this->html('headelement');
        ?>

<!-- HTML page goes here. -->

        <?php
        echo '</body></html>';
    }
}

But the problem is that the $out->addModuleStyles('skins.skinname') line (and similar script-adding line) requires that a module called skins.skinname be registered, by adding a element to the $wgResourceModules array. This is usually done in /resources/Resources.php, but we don't want to modify that. We could use the ResourceLoaderRegisterModules hook, but that's discouraged. The problem is that we can't just put $wgResourceModules['skin.skinname'] = array( /* etc. */ ); at the top of SkinName.php because that file isn't loaded by the ResourceLoader (via load.php).

[Freek] recommends creating a new file and including it from LocalSettings.php:

require_once("$IP/skins/skinname/resources.php");

And this works fine. It's just a shame that an extra line has to be added to LocalSettings, because it'd be nice if skins could be quite self-contained and swappable. There's some discussion of this at [VectorTalk].

Lastly, in cleaning up, I found that the SkinSkinName class can actually be reduced to just calling addModules() in the initPage() method.

Conclusion[edit]

So, in the end, a skeleton skin contains the following. Obviously, the placeholder skin name is 'skinname' and 'SkinName'. The two files 'style.css' and 'scripts.js' have been omitted.

/LocalSettings.php[edit]

Other parts omitted.

$wgDefaultSkin = 'skinname';
require_once("$IP/skins/$wgDefaultSkin/resources.php");

/skins/SkinName.php[edit]

<?php
if(!defined('MEDIAWIKI')) die(-1);
class SkinSkinName extends SkinTemplate {
    var $skinname = 'skinname', $stylename = 'skinname', $template = 'SkinNameTemplate', $useHeadElement = true;
        public function initPage(OutputPage $out) {
            parent::initPage($out);
            $out->addModules('skins.skinname');
    }
}
class SkinNameTemplate extends BaseTemplate {
    public function execute() {
        $this->html('headelement');
        ?>

<!-- HTML page goes here. -->

        <?php
        echo '</body></html>';
    }
}

/skins/skinname/SkinName.deps.php[edit]

<?php
if(!defined('MEDIAWIKI')) die(-1);
require_once( dirname( dirname( __FILE__ ) ) . '/includes/SkinTemplate.php' );

/skins/skinname/resources.php[edit]

<?php
if(!defined('MEDIAWIKI')) die(-1);
global $wgResourceModules;
$skinname = 'skinname';
$wgResourceModules["skins.$skinname"] = array(
    'styles' => array(
        'screen.css' => array( 'media' => 'screen' ),
    ),
    'scripts' => array(
        'scripts.js',
    ),
    'remoteBasePath' => "$wgScriptPath/skins/$skinname/",
    'localBasePath' => "$IP/skins/$skinname/",
);