Příručka:Modely obsahu stránek
ContentHandler představený v MediaWiki 1.21 vám umožňuje přidávat nové modely obsahu jiné než wikitext. Umožňuje, aby stránky wiki byly složeny z jiných dat než wikitext a byly reprezentovány jakýmkoli způsobem – například: Markdown, reStructuredText, icalendar nebo vlastní formát XML. Zobrazení a úpravy těchto modelů obsahu lze provádět vlastními způsoby (např. různé zvýraznění syntaxe nebo zcela nové formuláře pro zadávání dat).
Tato stránka popisuje, jak vytvořit nový model obsahu v rozšíření. Předpokládá určitou znalost obecných postupů vývoje rozšíření. Stručné shrnutí požadavků naleznete v sekci Souhrn ve spodní části této stránky.
Pro příklady bude použit nesmyslný obsahový model "Goat". Můžete také prozkoumat rozšíření DataPages, které je součástí Extension:Examples .
Registrace
Nejprve přidejte název modelu obsahu a třídu manipulátoru do svého extension.json:
"ContentHandlers": {
"goat": "MediaWiki\\Extension\\GoatExt\\GoatContentHandler"
}
- Hodnota vlevo je zde název typu obsahu, může to být libovolný jedinečný řetězec, který chcete, a existuje vedle pěti vestavěných typů obsahu: 'wikitext', 'JavaScript', 'CSS', 'plain text', 'JSON'. Tato hodnota je uživatelům vystavena na místech, jako jsou Special:ChangeContentModel a informace o stránce.
- Hodnota napravo je plně kvalifikovaný název třídy, která přesahuje ContentHandler.
To bude vyžadovat vytvoření dvou nových tříd, například \MediaWiki\Extension\GoatExt\GoatContent
a \MediaWiki\Extension\GoatExt\GoatContentHandler
(ujistěte se, že jejich jmenný prostor je registrován v AutoloadNamespaces).
Další informace o těchto třídách jsou uvedeny níže.
Volitelné konstanty modelu obsahu
Řetězec 'goat' výše je model obsahu IS (v kódu se obecně nazývá $modelId
) a je obvykle také definován jako konstanta.
Tyto konstanty jsou definovány pro všechny modely vestavěného obsahu a mnoho dokumentace odkazuje na konstanty "CONTENT_MODEL_XXX".
Pokud jste je nedefinovali, může to být trochu matoucí.
Definice by měla být provedena prostřednictvím položky zpětné volání v extension.json
. Například:
V extension.json
:
"callback": "MediaWiki\\Extension\\GoatExt\\Hooks::registrationCallback"
V includes/Hooks.php
:
namespace MediaWiki\Extension\GoatExt;
class Hooks {
public static function registrationCallback() {
// Must match the name used in the 'ContentHandlers' section of extension.json
define( 'CONTENT_MODEL_GOAT', 'goat' );
}
}
Nemusíte to dělat tímto způsobem a můžete použít pouze řetězec.
Přiřazení modelů obsahu ke stránkám
U stránek lze ručně změnit typ obsahu, ale je užitečné mít je jako výchozí na správný. Dva běžné způsoby, jak toho dosáhnout, jsou podle jmenného prostoru a podle přípony souboru.
Podle jmenného prostoru: Pokud chcete, aby měl celý jmenný prostor wiki výchozí model obsahu, můžete jej jako takový definovat v 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"
}
]
Upozorňujeme, že publikovaná rozšíření by měla zaregistrovat ID jmenného prostoru, která používají (550
a 551
výše) na stránce Výchozí jmenné prostory rozšíření .
Podle přípony souboru: Pokud chcete určit typ obsahu přidáním přípony typu kvazi souboru k názvu stránky wiki, můžete použít háček ContentHandlerDefaultModelFor . Například:
namespace MediaWiki\Extension\GoatExt;
class Hooks {
public static function onContentHandlerDefaultModelFor( \Title $title, &$model ) {
// Any page title (in any namespace) ending in '.goat'.
$ext = '.goat';
if ( substr( $title->getText(), -strlen( $ext ) ) === $ext ) {
// This is the constant you defined earlier.
$model = CONTENT_MODEL_GOAT;
// If you change the content model, return false.
return false;
}
// If you don't change it, return true.
return true;
}
}
ContentHandler
Další věcí, kterou je třeba definovat, je třída GoatContentHandler, kde také určujeme, v jakém formátu bude tento typ obsahu uložen (v tomto případě text). ContentHandlers nevědí nic o žádném konkrétním obsahu stránky, ale určují obecnou strukturu a uložení obsahu.
<?php
namespace MediaWiki\Extension\GoatExt;
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;
}
}
Obsah
Třída GoatContent
představuje data obsahu a neví nic o stránkách, revizích ani o tom, jak jsou uloženy v databázi.
Kromě požadovaných sedmi zděděných metod můžete přidat další veřejné metody, které jsou specifické pro doménu. V tomto případě chceme být schopni získat jméno Goat.
<?php
namespace MediaWiki\Extension\GoatExt;
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 getNativeData() {
}
public function getSize() {
}
public function copy() {
}
public function isCountable( $hasLinks = null ) {
}
public function getName() {
return 'Garry';
}
}
Úprava formuláře
Teď už máme kostru nastavenou, budeme chtít zkusit upravit Goat.
Za tímto účelem vytvoříme GoatContentHandler::getActionOverrides()
a určíme, jaké akce chceme mapovat na jaké třídy.
Pro začátek se budeme zabývat pouze 'edit' (což odpovídá ?action=edit
v URL).
public function getActionOverrides() {
return [
'edit' => GoatEditAction::class,
];
}
A vytvoříme naši novou třídu GoatEditAction
, v podstatě stejnou jako základní EditAction
, ale použijeme naše vlastní GoatEditPage
:
<?php
namespace MediaWiki\Extension\GoatExt;
class GoatEditAction extends \EditAction {
public function show() {
$this->useTransactionalTimeLimit();
$editPage = new GoatEditPage( $this->getArticle() );
$editPage->setContextTitle( $this->getTitle() );
$editPage->edit();
}
}
Naše nová třída GoatEditPage
je místem, kde se akce odehrává (omluvte slovní hříčku):
<?php
namespace MediaWiki\Extension\GoatExt;
class GoatEditPage extends \MediaWiki\EditPage\EditPage {
protected function showContentForm() {
$out = $this->context->getOutput();
// Get the data.
$name = $this->getCurrentContent()->getGoatName();
// Create the form.
$nameField = new \OOUI\FieldLayout(
new \OOUI\TextInputWidget( [ 'name' => 'goat_name', 'value' => $name ] ),
[ 'label' => 'Name', 'align' => 'left' ]
);
$out->addHTML( $nameField );
}
}
Nyní byste měli být schopni upravit stránku a zobrazit svůj formulář. Ale když do něj vložíte data a stisknete 'náhled', uvidíte, že věci ještě nefungují plně a že nemáte žádný výstup, ani se váš odeslaný text znovu nezobrazuje ve formuláři.
Musíme tedy přepsat i akci 'odeslat' novou třídou GoatSubmitAction
a přidáním 'submit' => GoatSubmitAction::class,
k naší metodě GoatContentHandler::getActionOverrides()
.
Naše třída GoatSubmitAction
by měla být stejná jako třída core, ale dědit z našich GoatEditAction
.
Zobrazení
Model obsahu je odpovědný za vytváření jakéhokoli požadovaného výstupu pro zobrazení. To obvykle zahrnuje práci s jeho daty a vytváření HTML nějakým způsobem, který se přidá k výstupu analyzátoru.
<?php
namespace MediaWiki\Extension\GoatExt;
class GoatContentHandler extends \AbstractContentHandler {
protected function fillParserOutput(
Title $title, $revId, ParserOptions $options, $generateHtml, ParserOutput &$output
) {
// e.g. $output->setText( $html );
}
}
Zobrazení popis/dokumentace
Někdy můžete chtít zobrazit nějaké informace nebo dokumentaci pro stránku wiki, která má vlastní model obsahu, jako je JSON. Neexistují žádné systémové zprávy pro zobrazení textu nad takovými stránkami (kromě MediaWiki:Clearyourcache zobrazených pouze nad stránkami JavaScript a CSS). Možná budete chtít vidět phab:T206395 pro další podrobnosti.
Porovnání revizí
Třída GoatDifferenceEngine
představuje rozdíl mezi obsahem Goat.
Přepíšeme výchozí metodu generateContentDiffBody
pro generování rozdílu.
<?php
namespace MediaWiki\Extension\GoatExt;
class GoatDifferenceEngine extends \DifferenceEngine {
public function generateContentDiffBody( Content $old, Content $new ) {
}
}
Abychom MediaWiki řekli, aby použila náš GoatDifferenceEngine
, přepíšeme getDiffEngineClass
na naše GoatContentHandler
.
<?php
namespace MediaWiki\Extension\GoatExt;
class GoatContentHandler extends \ContentHandler {
public function getDiffEngineClass() {
return GoatDifferenceEngine::class;
}
}
Shrnutí
Chcete-li implementovat nový model obsahu s vlastním formulářem pro úpravy, vytvořte následující:
<?php
namespace MediaWiki\Extension\GoatExt;
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 getNativeData() {}
public function getSize() {}
public function copy() {}
public function isCountable( $hasLinks = null ) {}
}
<?php
namespace MediaWiki\Extension\GoatExt;
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( \Title $title, $revId, \ParserOptions $options, $generateHtml, \ParserOutput &$output) {}
}
Checklist (kontrolní seznam)
Akce | Příklad | |
---|---|---|
Definujte ID modelu obsahu (a další typ obsahu) a konstantu modelu obsahu | goat CONTENT_MODEL_GOAT
| |
Vyberte si preferovaný mechanismus použití modelu obsahu: | ||
(a) Podle jmenného prostoru. Definujte konstanty jmenného prostoru, ID a jména za předpokladu, že žádné z nich ještě není obsazeno |
NS_GOAT (id: 550, name 'Goat')NS_GOAT_TALK (id: 551, name: 'Goat talk')
| |
(b) Podle přípony v názvu stránky | .goat
| |
(c) Ostatní | through 'Page information' interface (&action=info )
| |
extension.json
| ||
ContentHandlers - zaregistruje podtřídu ContentHandler pro nový model obsahu
|
"ContentHandlers": {
"goat": "GoatExt\\GoatContentHandler"
}
|
↑ |
callback - pojmenuje svou metodu třídy pro zpětná volání, obvykle v souboru Hooks
|
"callback": "GoatExt\\Hooks::registrationCallback"
|
↑ |
Hooks - poskytnout metodu háčku na ContentHandlerDefaultModelFor
|
"Hooks": {
"ContentHandlerDefaultModelFor": [ "GoatExt\\Hooks::onContentHandlerDefaultModelFor" ]
}
| |
namespaces - definuje jmenné prostory s příslušnou hodnotou pro defaultcontentmodel .
Pro více možností použijte místo toho háček |
"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 - načíst podtřídy Content a ContentHandler v podadresáři
|
"AutoloadNamespaces": {
"GoatExt\\": "includes/"
}
| |
[[Special:MyLanguage/Manual:Extension.json/Schema#AutoloadClasses|]] - explicitně načíst podtřídy Content a ContentHandler
|
"AutoloadClasses": {
"GoatExt\\Hooks": "includes/Hooks.php",
"GoatExt\\GoatContent": "includes/GoatContent.php",
"GoatExt\\GoatContentHandler": "includes/GoatContentHandler.php"
}
| |
Soubor háčků | GoatExt\\Hooks
| |
Přidat metodu pro zpětné volání | public static function registrationCallback() {
// Must match the name used in the 'ContentHandlers' section of extension.json
define( 'CONTENT_MODEL_GOAT', 'goat' );
}
| |
Přidejte metodu pro háček ContentHandlerDefaultModelFor pro stránky wiki v zamýšleném jmenném prostoru
|
public static function onContentHandlerDefaultModelFor( \Title $title, &$model ) {
if ( $title->inNamespace( NS_GOAT ) {
$model = CONTENT_MODEL_GOAT;
return false;
}
return true;
}
|
|
Nebo přidejte metodu pro háček ContentHandlerDefaultModelFor pro stránky wiki se zamýšlenou příponou souboru
|
public static function onContentHandlerDefaultModelFor( \Title $title, &$model ) {
$ext = '.goat';
if ( substr( $title->getText(), -strlen( $ext ) ) === $ext ) {
$model = CONTENT_MODEL_GOAT;
return false;
}
return true;
}
|
↑ |
Content and ContentHandler subclasses | ||
Add a Content subclass by extending AbstractContent or one of the subclasses available (e.g. TextContent ) | namespace GoatExt;
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 getNativeData() {
}
public function getSize() {
}
public function copy() {
}
public function isCountable( $hasLinks = null ) {
}
// etc. See documentation for details.
}
|
↑ |
Add a ContentHandler subclass by extending either ContentHandler or one of its subclasses (e.g. TextContentHandler or CodeContentHandler ) | namespace GoatExt;
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(
Title $title, $revId, ParserOptions $options, $generateHtml, ParserOutput &$output
) {
// e.g. $output->setText( $html );
}
// etc. See documentation for details
}
|
↑ |
Compare revisions | Override ContentHandler::getDiffEngineClass() and DifferenceEngine::generateContentDiffBody() | ↑ |
Modify associated actions such as 'edit' | Override ContentHandler::getActionOverrides() and EditAction::show() | ↑ |
Související odkazy
- Manual:Hooks/ContentHandlerDefaultModelFor
- Nápověda:ChangeContentModel - pro dokumentaci pro koncového uživatele o změně modelu obsahu.
- Extension:Examples - pro příklad vlastního modelu obsahu (ale zatím ne pro vlastní editační formulář).