Příručka:Modely obsahu stránek

This page is a translated version of the page Manual:Page content models and the translation is 94% complete.
Pro content pages vs. non-content pages se podívejte na stránku: Manual:Using custom namespaces#Content namespaces.

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 .

Varování Varování: Některé části této stránky jsou zastaralé. V MW 1,38 byly Content::getParserOutput a AbstractContent::fillParserOutput tvrdě znehodnoceny ve prospěch ContentRenderer::getParserOutput. Rozšíření definující model obsahu by měla přepsat ContentHandler::fillParserOutput.

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 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 - 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