Jump to content

Manuel:Modèles de pages de contenu

From mediawiki.org
This page is a translated version of the page Manual:Page content models and the translation is 98% complete.
Outdated translations are marked like this.
Pour content pages vs. non-content pages, voir : Manual:Using custom namespaces#Content namespaces.

Le ContentHandler introduit dans MediaWiki 1.21 vous permet d'ajouter de nouveaux modèles de contenu qui ne sont pas du wikicode. Ce qui permet aux pages des wikis à contenir des données autres que du wikicode et présentées à leur manière — par exemple : Markdown, reStructuredText, icalendar, ou un format XML personnalisé. L'affichage et la modification de ces modèles de contenu peut être géré de manière personnalisée (par exemple en changeant la mise en valeur, ou en adoptant des formulaires d'entrée de données complètement nouveaux).

Cette page décrit les étapes à parcourir pour créer un nouveau modèle de contenu dans une extension. Cela suppose que vous êtes familiarisé avec les pratiques du développement des extensions. Pour un aperçu rapide des contraintes, voir la section du résumé à la fin de cette page.

Un modèle de contenu quelconque non significatif, Goat (la chèvre) sera utilisé pour les exemples. Vous pouvez aussi examiner l'extension DataPages, qui est une partie de Extension:Examples .

Enregistrement

D'abord, ajoutez le nom du modèle de contenu de la classe du gestionnaire à votre extension.json :

"ContentHandlers": {
	"goat": "MediaWiki\\Extension\\GoatExt\\Content\\GoatContentHandler"
}
  • La valeur du membre de gauche ici est le nom du type de contenu, cela peut être n'importe quelle chaîne unique que vous souhaitez, avec toujours ses cinq types de contenu intégrés : 'wikitext', 'JavaScript', 'CSS', 'plain text', 'JSON'. Cette valeur est exposée aux utilisateurs à des endroits tels que Special:ChangeContentModel et les informations de page.
  • La valeur du membre de droite est le nom entièrement qualifié d'une classe qui étend MediaWiki\Content\ContentHandler.

Ceci nécessite la création de deux nouvelles classes comme \MediaWiki\Extension\GoatExt\Content\GoatContent et \MediaWiki\Extension\GoatExt\Content\GoatContentHandler (vérifiez que leur espace de noms est enregistré dans AutoloadNamespaces). D'autres informations concernant ces classes sont données ci-dessous.

Constantes optionnelles du modèle de contenu

La chaîne de notre chèvre goat ci-dessus est l'ID du modèle de contenu (généralement appelé $modelId dans le code), et elle est généralement définie aussi comme une constante. Ces constantes sont définies pour tous les modèles de contenu intégrés et beaucoup de documents se réfèrent aux constantes CONTENT_MODEL_XXX. Si vous ne les avez pas définis, ceci peut être un peu gênant. La définition doit être faite via l'élément de rappel (callback) dans extension.json. Par exemple :

Dans extension.json :

"callback": "MediaWiki\\Extension\\GoatExt\\Hooks::registrationCallback"

Dans src/Hooks.php :

<?php

namespace MediaWiki\Extension\GoatExt;

class Hooks {
    public static function registrationCallback() {
        // doit correspondre au nom utilisé dans la section 'ContentHandlers' de extension.json
        define( 'CONTENT_MODEL_GOAT', 'goat' );
    }
}

Vous ne devez pas le faire de cette façon, mais simplement utiliser la chaîne de caractères.

Assigner des modèles de contenu aux pages

Les pages peuvent avoir leur type de contenu modifié manuellement, mais il est utile d'avoir les bonnes valeurs par défaut. Deux façons communes d'obtenir cela est de faire par espace de noms et par extension de fichier.

Par espace de noms

Si vous voulez que tout un espace de noms du wiki ait un modèle de contenu par défaut, vous pouvez le définir ainsi dans extension.json :

"namespaces": [
	{
		"id": 550,
		"constant": "NS_GOAT",
		"name": "Goat",
		"subpages": false,
		"content": true,
		"defaultcontentmodel": "goat"
	},
	{
		"id": 551,
		"constant": "NS_GOAT_TALK",
		"name": "Goat_talk",
		"subpages": true,
		"content": false,
		"defaultcontentmodel": "wikitext"
	}
]

Notez que les extensions publiées doivent enregistrer les identifiants de l'espace de noms qu'elles utilisent (550 et 551 ci-dessus) sur la page Espaces de noms par défaut des extensions .

Par l'extension de fichier

Si vous voulez déterminer le type de contenu en ajoutant le quasi-suffixe du type de fichier au nom de la page du wiki, vous pouvez utiliser l'accroche ContentHandlerDefaultModelFor . Par exemple :

<?php

namespace MediaWiki\Extension\GoatExt;

use MediaWiki\Revision\Hook\ContentHandlerDefaultModelForHook;
use MediaWiki\Title\Title;

class Hooks implements ContentHandlerDefaultModelForHook {
	/**
	 * @param Title $title
	 * @param string &$model
	 */
	public function onContentHandlerDefaultModelFor( $title, &$model ) {
		// tout titre de page (dans n'importe quel espace de noms) se terminant par '.goat'.
		$ext = '.goat';

		if ( str_ends_with( $title->getText(), $ext ) ) {
			// c'est la constante que vous avez définie plus tôt.
			$model = CONTENT_MODEL_GOAT;
			// si vous modifiez le modèle de contenu, retourner 'false'.
			return false;
		}
		// si vous ne le modifiez pas, renvoyer 'true'.
		return true;
	}
}

Gestionnaire de contenu

La prochaine chose à définir est la classe GoatContentHandler, où nous spécifions également le format de stockage de ce type de contenu (dans ce cas ce sera du texte). ContentHandlers ne connait rien du contenu particulier d'une page donnée mais détermine la structure générale et le stockage du contenu.

<?php

namespace MediaWiki\Extension\GoatExt\Content;

use MediaWiki\Content\Content;
use MediaWiki\Content\ContentHandler;

class GoatContentHandler extends ContentHandler {

	public function __construct( $modelId = 'goat' ) {
		parent::__construct( $modelId, [ CONTENT_FORMAT_TEXT ] );
	}

	public function serializeContent( Content $content, $format = null ) {
	}

	public function unserializeContent( $blob, $format = null ) {
	}

	public function makeEmptyContent() {
		return new GoatContent();
	}

	public function supportsDirectEditing() {
		return true;
	}
}

Contenu

La classe GoatContent est la représentation des données du contenu, sans rapport avec les pages, les révisions, ou du format de stockage dans la base de données. Outre les sept méthodes héritées requises, vous pouvez ajouter d'autres méthodes publiques spécifiques à un domaine; dans ce cas, nous voulons pouvoir récupérer le nom de la chèvre.

Notably, AbstractContent::getNativeData() has been deprecated since 1.33. If you're extending MediaWiki\Content\TextContent instead, then you could use the getText() method. If you're extending MediaWiki\Content\JsonContent, the parent class provides the getData() method.

<?php

namespace MediaWiki\Extension\GoatExt;

use MediaWiki\Content\AbstractContent;

class GoatContent extends AbstractContent {

	public function __construct( $modelId = 'goat' ) {
		parent::__construct( $modelId );
	}

	public function getTextForSearchIndex() {
	}

	public function getWikitextForTransclusion() {
	}

	public function getTextForSummary( $maxLength = 250 ) {
	}

	public function getSize() {
	}

	public function copy() {
	}

	public function isCountable( $hasLinks = null ) {
	}

	public function getName() {
		return 'Garry';
	}
}

Formulaire de modification

Maintenant que nous avons configuré le squelette, nous allons essayer de modifier une chèvre. Pour faire ceci, nous créons GoatContentHandler::getActionOverrides() en spécifiant quelles actions que nous voulons associer aux classes. Nous commencerons ici par la modification (ce qui correspond à ?action=edit dans l'URL).

	public function getActionOverrides() {
		return [
			'edit' => GoatEditAction::class,
		];
	}

Et nous allons créer notre nouvelle classe GoatEditAction, fondamentalement la même que EditAction du noyau, mais en utilisant notre propre GoatEditPage :

<?php

namespace MediaWiki\Extension\GoatExt\Action;

use MediaWiki\Actions\EditAction;
use MediaWiki\Extension\GoatExt\EditPage;

class GoatEditAction extends EditAction {

	public function show() {
		$this->useTransactionalTimeLimit();
		$editPage = new GoatEditPage( $this->getArticle() );
		$editPage->setContextTitle( $this->getTitle() );
		$editPage->edit();
	}

}

Notre nouvelle classe GoatEditPage est là où se produit l'action (excusez le jeu de mots) :

<?php

namespace MediaWiki\Extension\GoatExt;

use MediaWiki\EditPage\EditPage;
use OOUI\FieldLayout;
use OOUI\TextInputWidget;

class GoatEditPage extends EditPage {

	protected function showContentForm() {
		$out = $this->context->getOutput();

		// obtenir les données.
		$name = $this->getCurrentContent()->getGoatName();

		// créer le formulaire.
		$nameField = new FieldLayout(
			new TextInputWidget( [ 'name' => 'goat_name', 'value' => $name ] ),
			[ 'label' => 'Name', 'align' => 'left' ]
		);
		$out->addHTML( $nameField );
	}

}

Maintenant vous pouvez modifier une page et voir votre formulaire. Mais quand vous y placez des données et que vous cliquez sur Aperçu, vous verrez que les choses ne fonctionnent pas encore pleinement : vous n'obtenez pas de sortie et le texte que vous avez soumi n'est pas réaffiché dans le formulaire.

Nous devons donc redéfinir aussi l'action soumettre, avec une nouvelle classe GoatSubmitAction et l'ajout de 'submit' => GoatSubmitAction::class, à notre méthode GoatContentHandler::getActionOverrides(). Notre classe GoatSubmitAction doit être la même que celle du noyau, mais en héritant de notre GoatEditAction.

Affichage

Un modèle de contenu a la charge de produire toute sortie nécessaire à l'affichage. Cela implique généralement de travailler avec ses données et de produire le HTML d'une certaine manière, pour l'ajouter à la sortie de l'analyseur syntaxique.

<?php

namespace MediaWiki\Extension\GoatExt\Content;

use MediaWiki\Content\ContentHandler;
use MediaWiki\Content\ContentParseParams;
use MediaWiki\Parser\ParserOutput;

class GoatContentHandler extends ContentHandler {

	protected function fillParserOutput(
		Content $content,
		ContentParseParams $cpoParams,
		ParserOutput &$output
	) {
		// define $html somewhere
		// e.g. $output->setText( $html );
	}

}

Afficher une description/documentation

Parfois, vous voudrez peut-être afficher des informations ou de la documentation pour une page wiki qui a un modèle de contenu personnalisé tel que JSON. Il n'existe pas de messages système pour afficher du texte sur ces pages (sauf pour MediaWiki:Clearyourcache affiché seulement sur les pages JavaScript et CSS). Voir phab:T355159 pour plus de détails.

Comparer les versions

Extending DifferenceEngine (deprecated in 1.32)

La classe GoatDifferenceEngine est la représentation de la différence entre le contenu de la chèvre. Nous redéfinissons la méthode par défaut generateContentDiffBody pour générer un diff.

<?php

namespace MediaWiki\Extension\GoatExt\Diff;

use DifferenceEngine;
use MediaWiki\Content\Content;

class GoatDifferenceEngine extends DifferenceEngine {

	public function generateContentDiffBody( Content $oldContent, Content $newContent ) {
	}
}

Pour dire à MediaWiki d'utiliser notre GoatDifferenceEngine, nous redéfinissons le getDiffEngineClass dans notre GoatContentHandler.

<?php

namespace MediaWiki\Extension\GoatExt\Content;

use MediaWiki\Content\ContentHandler;
use MediaWiki\Extension\GoatExt\Diff\GoatDifferenceEngine;

class GoatContentHandler extends ContentHandler {

	public function getDiffEngineClass() {
		return GoatDifferenceEngine::class;
	}
}

Extending SlotDiffRenderer

Using the newer method, we can extend SlotDiffRenderer instead. This follows the above pretty similarly:

<?php

namespace MediaWiki\Extension\GoatExt\Diff;

use MediaWiki\Content\Content;
use SlotDiffRenderer;

class GoatSlotDiffRenderer extends SlotDiffRenderer {

	public function getDiff( ?Content $oldContent = null, ?Content $newContent = null ) {
	}
}

Then, we tell our custom GoatContentHandler to use our custom GoatSlotDiffRenderer:

<?php

namespace MediaWiki\Extension\GoatExt\Content;

use MediaWiki\Content\ContentHandler;
use MediaWiki\Context\IContextSource;
use MediaWiki\Extension\GoatExt\Diff\GoatSlotDiffRenderer;

class GoatContentHandler extends ContentHandler {

	protected function getSlotDiffRendererWithOptions( IContextSource $context, $options = [] ) {
		return new GoatSlotDiffRenderer();
	}
}

Résumé

Pour implémenter un nouveau modèle de contenu avec un formulaire d'édition personnalisé, créez ceci :

<?php

namespace MediaWiki\Extension\GoatExt\Content;

use MediaWiki\Content\AbstractContent;

class GoatContent extends AbstractContent  {
	public function __construct( $modelId = 'goat' ) {
		parent::__construct( $modelId );
	}
	public function getTextForSearchIndex() {}
	public function getWikitextForTransclusion() {}
	public function getTextForSummary( $maxLength = 250 ) {}
	public function getSize() {}
	public function copy() {}
	public function isCountable( $hasLinks = null ) {}
}
<?php

namespace MediaWiki\Extension\GoatExt\Content;

use MediaWiki\Content\Content;
use MediaWiki\Content\ContentHandler;
use MediaWiki\Content\ContentParseParams;

class GoatContentHandler extends ContentHandler {	
	public function __construct( $modelId = CONTENT_MODEL_GOAT, $formats = ['text/x-goat'] ) {
		parent::__construct($modelId, $formats);
	}
	protected function getContentClass() {}
	public function supportsDirectEditing() {}
	public function serializeContent( Content $content, $format = null ) {}
	public function unserializeContent( $blob, $format = null ) {}
	public function makeEmptyContent() {}
	public function getActionOverrides() {}
	protected function fillParserOutput(
		Content $content,
		ContentParseParams $cpoParams,
		ParserOutput &$output
	) {}

}

Liste de contrôle

Action Exemple
Définir un identifiant du modèle de contenu (pour le type de contenu) et une constante pour le modèle de contenu goat
CONTENT_MODEL_GOAT
Choisissez votre mécanisme préféré pour appliquer un modèle de contenu :
(a) Par espace de noms. Définir les constantes des espaces de noms, les identifiants et les noms
on ne peut pas encore les donner
NS_GOAT (id: 550, name 'Goat')
NS_GOAT_TALK (id: 551, name: 'Goat talk')
(b) Par extension dans le nom de page .goat
(c) Autre through 'Page information' interface (&action=info)
extension.json
ContentHandlers - enregistrer une sous-classe ContentHandler pour le nouveau modèle de contenu
"ContentHandlers": {
	"goat": "MediaWiki\\Extension\\GoatExt\\Content\\GoatContentHandler"
}
callback - nommer votre méthode de classe pour les procédures de rappels, conventionnellement dans votre fichier d'accroches
"callback": "MediaWiki\Extension\\GoatExt\\Hooks::registrationCallback"
Hooks , HookHandlers - fournir une méthode d'accroche pour ContentHandlerDefaultModelFor
"Hooks": {
   "ContentHandlerDefaultModelFor": "main"
},
"HookHandlers": {
   "main": {
      "class": "MediaWiki\\Extension\\GoatExt\\Hooks"
   }
}
namespaces - définir les espaces de noms avec la valeur appropriée de defaultcontentmodel.

Pour davantage d'options, utiliser à la place l'accroche ContentHandlerDefaultModelFor.

"namespaces": [
	{
		"id": 550,
		"constant": "NS_GOAT",
		"name": "Goat",
		"subpages": false,
		"content": false,
		"defaultcontentmodel": "goat"
	},
	{
		"id": 551,
		"constant": "NS_GOAT_TALK",
		"name": "Goat_talk",
		"subpages": true,
		"content": false,
		"defaultcontentmodel": "wikitext"
	}
]
AutoloadNamespaces - charger les sous-classes de Content et ContentHandler dans le sous-répertoire
"AutoloadNamespaces": {
   "MediaWiki\\Extension\\GoatExt\\": "src/"
}
AutoloadClasses - charger les sous-classes de Content et ContentHandler explicitement
"AutoloadClasses": {
   "MediaWiki\\Extension\\GoatExt\\Hooks": "src/Hooks.php",
   "MediaWiki\\Extension\\GoatExt\\Content\\GoatContent": "src/Content/GoatContent.php",
   "MediaWiki\\Extension\\GoatExt\\Content\\GoatContentHandler": "src/Content/GoatContentHandler.php"
}
Fichier des accroches MediaWiki\\Extension\\GoatExt\\Hooks
Ajouter une méthode de rappel
public static function registrationCallback() {
   // doit correspondre au nom utilisé dans la section 'ContentHandlers' de extension.json
   define( 'CONTENT_MODEL_GOAT', 'goat' );
}
Ajouter la méthode de l'accroche ContentHandlerDefaultModelFor pour les pages wiki dans l'espace de noms prévu
public function onContentHandlerDefaultModelFor( $title, &$model ) {
   if ( $title->inNamespace( NS_GOAT ) {
      $model = CONTENT_MODEL_GOAT;
      return false;
   }
   return true;
}
Ou ajouter la méthode de l'accroche ContentHandlerDefaultModelFor pour les pages wiki avec l'extension de fichier prévue
public function onContentHandlerDefaultModelFor( $title, &$model ) {
   $ext = '.goat';
   if ( str_ends_with( $title->getText(), $ext ) ) {
      $model = CONTENT_MODEL_GOAT;
      return false;
   }
   return true;
}
Sous-classes de Content et ContentHandler
Ajouter une sous-classe Content en étendant AbstractContent ou l'une des sous-classes disponibles (par exemple TextContent )
namespace MediaWiki\Extension\GoatExt\Content;

use MediaWiki\Content\AbstractContent;

class GoatContent extends AbstractContent {

	public function __construct( $modelId = 'goat' ) {
		parent::__construct( $modelId );
	}

	public function getTextForSearchIndex() {}
	public function getWikitextForTransclusion() {}
	public function getTextForSummary( $maxLength = 250 ) {}
	public function getSize() {}
	public function copy() {}
	public function isCountable( $hasLinks = null ) {}

   // etc. - voir la documentation pour les détails.
}
Ajouter une sous-classe ContentHandler en étendant soit ContentHandler ou l'une de ses sous-classes (comme TextContentHandler ou CodeContentHandler )
<?php

namespace MediaWiki\Extension\GoatExt;

use MediaWiki\Content\Content;
use MediaWiki\Content\ContentHandler;

class GoatContentHandler extends ContentHandler {

	public function __construct( $modelId = 'goat' ) {
		parent::__construct( $modelId, [ CONTENT_FORMAT_TEXT ] );
	}

	public function serializeContent( Content $content, $format = null ) {
	}

	public function unserializeContent( $blob, $format = null ) {
	}

	public function makeEmptyContent() {
		return new GoatContent();
	}

	public function supportsDirectEditing() {
		return true;
	}

	protected function fillParserOutput(
		Content $content,
		ContentParseParams $cpoParams,
		ParserOutput &$output
	) {
		// define $html somewhere
		// e.g. $output->setText( $html );
	}

    // etc. - voir la documentation pour les détails.
}
Comparer les révisions Redéfinir ContentHandler::getDiffEngineClass() et DifferenceEngine::generateContentDiffBody()
Modify associated actions such as 'edit' Redéfinir ContentHandler::getActionOverrides() et EditAction::show()

Voir aussi