Manual:Sayfa içerik modelleri

This page is a translated version of the page Manual:Page content models and the translation is 51% complete.
Outdated translations are marked like this.
content pages vs. non-content pages, Manual:Using custom namespaces#Content namespaces sayfasına bakın.

MediaWiki 1.21 ile sunulan ContentHandler , vikimetin dışında yeni içerik modelleri eklemenize izin verir. Viki sayfalarının vikimetin dışındaki verilerden oluşmasını ve herhangi bir şekilde temsil edilmesini mümkün kılar. Örneğin: Markdown, reStructuredText, icalendar veya özel bir XML biçimi. Bu içerik modellerinin görüntülenmesi ve düzenlenmesi özel yollarla (örn. farklı sözdizimi vurgulama veya tamamen yeni veri giriş formları) ele alınabilir.

Bu sayfada, bir uzantıda yeni bir içerik modelinin nasıl oluşturulacağı açıklanmaktadır. Genel uzantı geliştirme uygulamalarına biraz aşinalık olduğunu varsayar. Gereksinimlerin kısa bir özeti için, bu sayfanın altındaki Özet bölümüne bakın.

Örnekler için anlamsız bir "Goat" içerik modeli kullanılacaktır. Extension:Examples parçası olan DataPages uzantısını da inceleyebilirsiniz.

Kayıt

Her şeyden önce, içerik modelinin adını ve işleyici sınıfını extension.json dosyanıza ekleyin:

"ContentHandlers": {
	"goat": "MediaWiki\\Extension\\GoatExt\\Content\\GoatContentHandler"
}
  • Buradaki sol taraftaki değer içerik türünün adıdır, istediğiniz herhangi bir benzersiz dize olabilir ve beş yerleşik içerik türü ile birlikte yaşar: 'wikitext', 'JavaScript', 'CSS', 'plain text', 'JSON'. Bu değer, Special:ChangeContentModel ve sayfa bilgisi ​​gibi yerlerde kullanıcılara gösterilir.
  • Sağ taraftaki değer, MediaWiki\Content\ContentHandler genişleyen bir sınıfın tam nitelikli adıdır.

Bu, \MediaWiki\Extension\GoatExt\Content\GoatContent ve \MediaWiki\Extension\GoatExt\Content\GoatContentHandler olmak üzere iki yeni sınıfın $3 ile eklenmesini gerektirecektir (ad alanları AutoloadNamespaces değilse). Bu sınıflar hakkında daha fazla bilgi aşağıda verilmiştir.

İsteğe bağlı içerik modeli sabitleri

Yukarıdaki 'goat' dizesi içerik modelidir (genellikle kodda $modelId olarak adlandırılır) ve genellikle sabit olarak da tanımlanır. Bu sabitler tüm yerleşik içerik modelleri için tanımlanmıştır ve birçok belge "CONTENT_MODEL_XXX" sabitlerini ifade eder. Onları tanımlamadıysanız, bu biraz kafa karıştırıcı olabilir. Tanım, extension.json içindeki geri çağrı öğesi aracılığıyla yapılmalıdır. Örneğin:

extension.json içinde:

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

src/Hooks.php içinde:

<?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' );
    }
}

Bunu bu şekilde yapmak zorunda değilsiniz ve yalnızca dizeyi kullanabilirsiniz.

İçerik modellerini sayfalara atama

Pages can have their content type manually changed, but it's useful to have them default to the correct one. Two common ways of doing this are by namespace, and by file extension.

Tüm bir viki ad alanının varsayılan içerik modeline sahip olmasını istiyorsanız, bunu $1 içinde olduğu gibi tanımlayabilirsiniz:

If you want an entire wiki namespace to have a default content model, you can define it as such in 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"
	}
]

Note that published extensions should register the namespace IDs they use (550 and 551 above) on the extension default namespaces page.

By file extension

Ya da, viki sayfası adına yarı dosya türü bir sonek ekleyerek içerik türünü belirlemek istiyorsanız, ContentHandlerDefaultModelFor kancasını kullanabilirsiniz. Örneğin:

<?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 ) {
		// Any page title (in any namespace) ending in '.goat'.
		$ext = '.goat';

		if ( str_ends_with( $title->getText(), $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

Tanımlanacak bir sonraki şey, bu içerik türünün hangi formatta (bu durumda metin) depolanacağını da belirlediğimiz GoatContentHandler sınıfıdır. ContentHandlers, herhangi bir belirli sayfa içeriği hakkında hiçbir şey bilmiyor, ancak içeriğin genel yapısını ve depolanmasını belirliyor.

<?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;
	}
}

İçerik

GoatContent sınıfı, içeriğin verilerinin temsilidir ve sayfalar, revizyonlar veya veritabanında nasıl depolandığı hakkında hiçbir şey bilmiyor. Gerekli yedi kalıtımsal yöntemin yanı sıra, etki alanına özgü diğer genel yöntemler de ekleyebilirsiniz; bu durumda keçinin adını alabilmek istiyoruz.

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';
	}
}

Düzenleme formu

Şimdi iskeleti kurduk, bir Goat düzenlemeyi denemek isteyeceğiz. Bunu yapmak için, GoatContentHandler::getActionOverrides() oluştururuz ve hangi eylemleri hangi sınıflara eşlemek istediğimizi belirleriz. Başlangıç ​​olarak, sadece 'düzenle' ile ilgileneceğiz (URL'de ?action=edit ile karşılık gelir).

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

Ve yeni GoatEditAction sınıfımızı oluşturacağız, temelde EditAction ile aynı, ancak kendi GoatEditPage kullanarak:

<?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();
	}

}

Yeni GoatEditPage sınıfımız, eylemin gerçekleştiği yerdir (kelime oyununu bağışlayın):

<?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();

		// Get the data.
		$name = $this->getCurrentContent()->getGoatName();

		// Create the form.
		$nameField = new FieldLayout(
			new TextInputWidget( [ 'name' => 'goat_name', 'value' => $name ] ),
			[ 'label' => 'Name', 'align' => 'left' ]
		);
		$out->addHTML( $nameField );
	}

}

Artık bir sayfayı düzenleyebilmeli ve formunuzu görebilmelisiniz. Ancak içine veri koyduğunuzda ve 'önizleme' düğmesine tıkladığınızda, işlerin henüz tam olarak çalışmadığını ve çıkış alamadığınızı veya gönderdiğiniz metnin formda tekrar gösterilmediğini göreceksiniz.

Bu nedenle, yeni bir GoatSubmitAction sınıfı ve GoatContentHandler::getActionOverrides() yöntemimize 'submit' => GoatSubmitAction::class, ilavesi ile 'gönder' eylemini de geçersiz kılmalıyız. GoatSubmitAction sınıfımız çekirdek sınıfımızla aynı olmalı, ancak GoatEditAction üzerinden miras almalıdır.

Görüntüleme

Görüntü için gerekli herhangi bir çıkışının üretilmesinden bir içerik modeli sorumludur. Bu genellikle, ayrıştırıcı çıkışına eklemek için verileriyle çalışmayı ve bir şekilde HTML üretmeyi içerir.

<?php

namespace MediaWiki\Extension\GoatExt\Content;

use MediaWiki\Content\ContentHandler;
use MediaWiki\Content\Renderer\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 );
	}

}

Bir açıklama/belgelendirme görüntüle

Bazen, JSON gibi özel bir içerik modeline sahip bir makale için bazı bilgileri veya bazı belgeleri görüntülemek isteyebilirsiniz. Aslında, bu tür sayfaların üzerinde bazı metinleri görüntülemek için sistem mesajları yoktur (yalnızca JavaScript ve CSS sayfalarının üzerinde gösterilen MediaWiki:Clearyourcache haricinde). Daha fazla ayrıntı için phab:T355159 görmek isteyebilirsiniz.

Revizyonları karşılaştırma

Extending DifferenceEngine (deprecated in 1.32)

GoatDifferenceEngine sınıfı, keçi içerikleri arasındaki farkın temsilidir. Bir fark oluşturmak için varsayılan generateContentDiffBody yöntemini geçersiz kılıyoruz.

<?php

namespace MediaWiki\Extension\GoatExt\Diff;

use DifferenceEngine;
use MediaWiki\Content\Content;

class GoatDifferenceEngine extends DifferenceEngine {

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

MediaWiki'ye GoatDifferenceEngine kullanmasını söylemek için GoatContentHandler sınıfımızdaki getDiffEngineClass üzerine yazıyoruz.

<?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();
	}
}

Özet

Özel bir düzenleme formuyla yeni bir içerik modeli uygulamak için aşağıdakileri oluşturun:

<?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\Renderer\ContentParseParams;
use MediaWiki\Parser\ParserOutput;

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
	) {}

}

Checklist

Action Example
Define a content model id (al. content type) and content model constant goat
CONTENT_MODEL_GOAT
Choose your preferred mechanism of applying a content model:
(a) By namespace. Define namespace constants, ids and names
given any of them is not already taken
NS_GOAT (id: 550, name 'Goat')
NS_GOAT_TALK (id: 551, name: 'Goat talk')
(b) By extension in pagename .goat
(c) Other through 'Page information' interface (&action=info)
extension.json
ContentHandlers - register a ContentHandler subclass for the new content model
"ContentHandlers": {
	"goat": "MediaWiki\\Extension\\GoatExt\\Content\\GoatContentHandler"
}
callback - name your class method for callbacks, conventionally in your Hooks file
"callback": "MediaWiki\Extension\\GoatExt\\Hooks::registrationCallback"
Hooks , HookHandlers - provide a hook method for ContentHandlerDefaultModelFor
"Hooks": {
   "ContentHandlerDefaultModelFor": "main"
},
"HookHandlers": {
   "main": {
      "class": "MediaWiki\\Extension\\GoatExt\\Hooks"
   }
}
namespaces - define namespaces with the appropriate value for defaultcontentmodel.

For more options, use ContentHandlerDefaultModelFor hook instead.

"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 - load Content and ContentHandler subclasses in subdirectory
"AutoloadNamespaces": {
   "MediaWiki\\Extension\\GoatExt\\": "src/"
}
AutoloadClasses - load Content and ContentHandler subclasses explicitly
"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"
}
Hooks file MediaWiki\\Extension\\GoatExt\\Hooks
Add method for the callback
public static function registrationCallback() {
   // Must match the name used in the 'ContentHandlers' section of extension.json
   define( 'CONTENT_MODEL_GOAT', 'goat' );
}
Add method for the ContentHandlerDefaultModelFor hook for wiki pages in the intended namespace
public function onContentHandlerDefaultModelFor( $title, &$model ) {
   if ( $title->inNamespace( NS_GOAT ) {
      $model = CONTENT_MODEL_GOAT;
      return false;
   }
   return true;
}
Or add method for the ContentHandlerDefaultModelFor hook for wiki pages with the intended file extension
public function onContentHandlerDefaultModelFor( $title, &$model ) {
   $ext = '.goat';
   if ( str_ends_with( $title->getText(), $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 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. See documentation for details.
}
Add a ContentHandler subclass by extending either ContentHandler or one of its subclasses (e.g. TextContentHandler or CodeContentHandler )
<?php

namespace MediaWiki\Extension\GoatExt;

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

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. See documentation for details
}
Compare revisions Either override ContentHandler::getDiffEngineClass() and DifferenceEngine::generateContentDiffBody(), or override ContentHandler::getSlotDiffRendererWithOptions() and SlotDiffRenderer::getDiff
Modify associated actions such as 'edit' Override ContentHandler::getActionOverrides() and EditAction::show()

Ayrıca bakınız