Manuel:Comment créer un habillage MediaWiki/Migration des habillages basés sur SkinTemplate vers SkinMustache

From mediawiki.org

Déjà présente sans la version MW 1.35 en 2020, la classe SkinMustache a été ajoutée au noyau de MediaWiki. Ce développement rend possible l'utilisation des modèles Mustache pour créer des habillages. Il s'adresse aux développeurs d'habillages qui ne veulent pas utiliser PHP, ou qui souhaitent réduire leur dépendance avec PHP. Le but de ce tutoriel est donc de montrer les étapes dont vous aurez besoin pour convertir un habillage SkinTemplate PHP en SkinMustache.

Etape 1 : enregistrer un habillage

Auparavent un habillage devait déclarer une classe PHP Skin qui étendait la classe SkinTemplate. Il fallait alors déclarer plusieurs propriétés utilisées pour définir les clés internes des habillages ainsi que les modèles PHP associés.

Depuis MW 1.35, cette information peut être fournie au moment de l'enregistrement de l'habillage.

Le nouveau processus d'enregistrement des habillages est plus puissant.
Fichier SkinTemplate - ancien processus d'enregistrement SkinTemplate - nouveau processus d'enregistrement
skin.json
{
    "ValidSkinNames": {
        "monobook": "MonoBook"
    }
}
{
    "ValidSkinNames": {
        "monobook": {
			"class": "SkinMonoBook",
			"args": [
				{
					"scripts": [
					    "skins.monobook.scripts"
					],
					"styles": [
					    "skins.monobook.styles"
					],
					"name": "monobook",
					"template": "MonoBookTemplate"
				}
			]
        }
    }
}
SkinMonobook.php
class SkinMonoBook extends SkinTemplate {
	/** En utilisant MonoBook. */
	public $skinname = 'monobook';
	public $stylename = 'MonoBook';
	public $template = 'MonoBookTemplate';

	public function initPage( OutputPage $out ) {
	    parent::initPage( $out );
	    $out->addModules( 'skins.monobook.scripts' );
		$out->addModuleStyles( 'skins.monobook.styles' );
	}
}
class SkinMonoBook extends SkinTemplate {
}

Historiquement, les habillages nécessitaient la création de deux classes PHP. Avec le nouveau processus d'enregistrement, il vous faut au plus une classe PHP.

Lorsque vous déclarez un habillage, il est possible d'initialiser class avec SkinTemplate pour utiliser l'interface noyau par défaut :

{
    "ValidSkinNames": {
        "monobook": {
			"class": "SkinTemplate",
			"args": [
				{
					"name": "monobook",
					"template": "MonoBookTemplate"
				}
			]
        }
    }
}

Si votre habillage contient des accroches, nous vous recommandons de les sortir dans un fichier séparé.

Voici un exemple pour l'habillage Monobook : gerrit:701142

Etape 2 : décupler la puissance de la modélisation

Pour suivre cette nouvelle étape, on suppose que vous possédez quelques connaissances du langage des modèles Mustache. Au minimum vous devez comprendre les bases suivantes de Mustache présentes dans l'exemple ci-dessous :

{{ str }} <!-- rendu de la chaîne échappée -->
{{{ html-str }}} <!-- rendu du HTML brut -->

<!-- accès aux données du tableau associatif sous la forme  { 'key' => 'hello' } -->
{{#array-data}} 
{{ key }} <!-- rend hello -->
{{/array-data}}

<!-- pour les valeurs booléennes -->
{{#is-talk-page}}
<!-- rendu conditionnel si is-talk-page vaut 'true' -->
{{/is-talk-page}}

Hello World !

Créer un fichier Mustache avec le chemin relatif templates/skin.mustache

<div>
    <h1>My first Mustache skin</h1>
    <p><strong>Hello world!</strong></p>
</div>

Pour utiliser la classe SkinMustache, déclarer la propriété class avec pour valeur SkinMustache.

{
    "ValidSkinNames": {
        "monobook": {
			"class": "SkinMustache",
			"args": [
				{
					"name": "monobook"
				}
			]
        }
    }
}

Chargez l'habillage dans votre navigateur et vous devriez voir le contenu de votre fichier Mustache.

Pour les versions de MediaWiki plus anciennes que la 1.37, vous devez également définir templateDirectory et template.
{
    "ValidSkinNames": {
        "monobook": {
			"class": "SkinMustache",
			"args": [
				{
					"name": "monobook",
					"templateDirectory": "skins/Monobook/templates/",
                    "template": "skin"
				}
			]
        }
    }
}

Utiliser une classe personnalisée

Pour faciliter la migration, vous pouvez utiliser votre propre classe personnalisée en étendant la classe SkinMustache, tout au moins dans une étape intermédiaire, puis commencer la redirection du code à partir du modèle de votre habillage vers les nouveaux modèles.

Créer une nouvelle classe d'habillage qui étend SkinMustache, par exemple pour l'habillage MonoBook, elle pourrait s'appeler SkinMonoBook.

Lorsque vous utilisez un modèle basé sur PHP tel que MonoBookTemplate, on s'attend à ce que le développeur d'habillage implémente une fonction execute qui renvoie le HTML.

<?php
class MonoBookTemplate extends BaseTemplate {
    public function execute() {
        $html = $this->get( 'headelement' );
        $html .= $this->get( 'bodytext' );
        $html .= $this->getTrail();
		$html .= Html::closeElement( 'body' );
		$html .= Html::closeElement( 'html' );
        echo $html;
    }
}

Dans SkinMustache, l'approche est différente. Nous fournissons un tableau associatif de template data qui est passé au modèle Mustache.

Dans l'exemple suivant, de nouvelles données sont initialisées et passées au modèle Mustache :

<?php
class SkinMonoBook extends SkinMustache {
    public function getTemplateData() {
        $data = parent::getTemplateData();
        $data['html-hello'] = '<strong>HELLO WORLD</strong>';
        return $data;
    }
}

Avec cette modification nous pouvons faire la correction suivante sur notre modèle pour produire les données.

Modèle qui n'utilise pas les template data Modèle utilisant les template data ajoutées récemment
<div>
    <h1>My first Mustache skin</h1>
    <p><strong>Hello world!</strong></p>
</div>
<div>
    <h1>My first Mustache skin</h1>
    <p>{{{ html-hello }}}</p>
</div>

En utilisant cette technique nous pouvons relier notre ancien habillage à SkinMustache.

D'abord il nous faudra peut être refactoriser notre méthode execute pour en détacher une fonction qui renvoie la chaîne de caractères contenant le corps de l'habillage. Il est important de remarquer que dans SkinMustache, vous ne pouvez modéliser que le contenu de la balise body.

BaseTemplate originale BaseTemplate pour utilisation dans SkinMustache
<?php
class MonoBookTemplate extends BaseTemplate {
    public function execute() {
        $html = $this->get( 'headelement' );
        $html .= $this->get( 'bodytext' );
        $html .= $this->getTrail();
		$html .= Html::closeElement( 'body' );
		$html .= Html::closeElement( 'html' );
        echo $html;
    }
}
<?php
class MonoBookTemplate extends BaseTemplate {
    public function getHTML() {
        return $this->get( 'bodytext' );
    }
    public function execute() {
       /* Cette fonction doit exister pour implémenter BaseTemplate
         mais n'est pas utilisée car nous avons SkinMustache.
         Les balises getTrail, headelement et le body fermant
         sont gérées par SkinMustache.
       */
    }
}

Dans SkinMustache, une fois la refactorisation faite, nous pouvons étendre les données passées à un modèle comme démontré ci-dessus avec l'exemple html-hello. Nous pouvons ajouter une nouvelle variable de modèle html-quick-template-migration qui peut être rendue à l'intérieur de notre skin.mustache en tant de HTML brut.

<?php
class SkinMonoBook extends SkinMustache {
    public function getTemplateData() {
        $data = parent::getTemplateData();
        $tpl = $this->prepareQuickTemplate();
		return $data + [ 'html-quick-template-migration' => $tpl->getHTML() ];
    }
}

Etape 3 : donnée entre accolades

Maintenant vous devriez avoir un habillage qui implémente SkinMustache et qui utilise BaseTemplate pour générer le HTML. Le PHP à l'intérieur de votre modèle PHP qui implémente BaseTemplate doit être possible avec Mustache.

Les habillages SkinMustache sont dirigés par les données, ce qui nous le pensons, donne une meilleure souplesse quant à la manière de présenter les données. Les données sont informées par les habillages au fur et à mesure. Ces données sont documentée dans la section Template data.

Il y a peu de conseils sur cette étape, à part explorer comment vous pouvez générer un code HTML identique à votre code dans BaseTemplate en utilisant uniquement les données et les modèles. Les problèmes que vous rencontrez en faisant cela doivent être signalés sur la page de discussion pour aider les autres utilisateurs.

Etape 4 : renseigner les données manquantes

Pendant l'étape 3 vous pouvez observer que le HTML que vous essayez de générer ne peut pas être mis en forme en utilisant les données à l'intérieur de SkinMustache. Heureusement grâce à l'étape 2 nous savons que l'on n'est pas limité par les données passées à notre modèle.

Néanmoins il est utile pour nous de savoir quelles sont les données manquantes car il est probable que votre habillage fait quelque chose d'unique qui pourrait être utile aux autres habillages.

Simplement par l'existence de votre code, vous avez communiqué des informations qui seraient utiles, mais nous vous invitons à créer un ticket explicitement sur Phabricator pour demander les données dont vous avez besoin.