Manual:内容处理器

This page is a translated version of the page Manual:ContentHandler and the translation is 98% complete.
Outdated translations are marked like this.

内容处理器(ContentHandler)是一种在维基页面上支持任意内容类型的机制,而不是一切都依赖于维基文本来处理所有内容。 这原先是作为维基数据项目的一部份开发的,而从1.21版本开始成了MediaWiki核心的一部分。

有关内容处理器架构的典型概述,请参阅MediaWiki代码文档中的内容处理器

有关可用的内容处理器的列表,请参阅内容处理器

关于

这一相当激进的改变背后的原因是,在MediaWiki中,被迫依赖wikitext来获取所有内容使得很多事情变得相当麻烦。 新的可插拔架构适用于任意类型的页面内容,这将使我们能够:

  • 在部分或全部页面上使用不同的标记语言,如TeX或Markdown。
  • 取消CSS和JavaScrip 页面的特例。
  • 存储和编辑结构化配置数据的方式比Gadgets扩展在MediaWiki:Gadgets-definition页面或 LanguageConverter在MediaWiki:Conversiontable***页面上使用的方式更合理。
  • 为 wikitext 页面提供数据“附件”,例如地理数据(使用页面的“多部分”内容模型,类似于使用多部分信息格式实现电子邮件附件的方式)。 (注:该计划从未实现,现已被Multi-Content Revisions 取代)。
  • 过渡到不在维基文本中维护类别等内容的系统,但仍以通常的方式进行存储和版本控制(再次使用多部分内容模型)。
  • 維基數據轻松存储结构化数据,并将其作为页面内容。


设计理念

我们的想法是,以与目前存储 wikitext 完全相同的方式存储其他类型的数据,但要让MediaWiki知道每个页面所处理的内容类型。 这样,任何类型的数据都可以用作维基页面的内容,而且其存储和版本控制都与以前完全一样。 为了实现这一目标,我们在MediaWiki核心中实现了以下功能:

  • 追踪每个页面的“内容模型”。 这主要是在数据库中的page表(也包括revisionarchive表)中完成的,并可通过TitleRevision、和WikiPage等相关核心类別访问。 “内容模型”定义了内容的“原生形式”,无论是包含文本的字符串、嵌套数组结构,还是PHP对象。 对内容的所有操作都是在其“原生形式”上进行的。
  • 跟踪每次修订的“内容格式”(序列化格式)。 这主要是在数据库中的revision表(也包括archive表,但不包括page表)中完成的,并可通过相关的核心类(如Revision)访问。 请注意,序列化格式只与加载和存储修订版时相关,不会对内容的序列化形式执行任何操作。
    • 注意:对于平面文本内容(如 wikitext),内容的原始形式与序列化形式(即字符串)相同。 不过,可以想象,维基文本的原生形式将来可能是某种形式的 AST 或 DOM。
    • 注:page表记录当前修订版的内容模型,而revision表记录内容模型和序列化格式。 从理论上讲,模型和格式都可以从一个修订版变为另一个修订版,但这可能会造成混淆,而且无法实现有意义的差异。

这意味着所有需要对内容执行任何操作的代码都必须了解内容的原生形式。 这些知识通过基于两个类别的可插拔处理器框架进行封装:

  • Content类別表示内容本身,并为在内容原生形式上执行所有标准操作提供接口。 它不知道内容属于哪个页面或版本。 内容对象一般是、但不必然是,不可变的。
  • ContentHandler类別,代表有关内容模型具体内容的知识,但不能访问具体的内容。 最重要的是,内容处理器的实例可作为内容对象的工厂,并提供序列化/反序列化功能。 内容对象是无状态的單例模式,每个内容模型都有一个。

内容处理器也用于生成Article,EditPage,DifferenceEngine等子类別的合适实例。 这样,就可以通过内容处理器接口轻松为每种内容类型插入专门的用户界面。

所有以任何方式访问修订文本的代码都应修改为使用内容对象所提供的方法。 访问修订文本的核心类別(最重要的是RevisionWikiPage类)已进行调整,以提供对相应内容对象的访问,而不是对文本的访问。

向后兼容

在MediaWiki代码库中,页面包含有维基文本的假设是非常普遍的。因此,与仍然如此假设的部分代码,尤其是与扩展,保持兼容是非常重要的。 当然,提供良好兼容性的正确方法是不去更改公共接口。 因此,所有提供访问修订内容的方法(就像Revision::getText()等)仍然保留,而是以允许访问内容对象的替代方法(如Revision::getContent())辅助。 基于文本的方法现已弃用,但对所有包含维基文本的页面/修订版而言,其功能与以前完全相同。 这也同樣适用于Action API

我们提供了一个方便的方法--ContentHandler::getContentText(),以方便獲取某個页面的文本。 对于平坦的基于文本内容模型,如维基文本(也包括 JS 和 CSS),对于此类修订,getContentText()将只返回文本,旧的基于文本方法也将返回相同的结果,如同以前一樣。 不过,如果在不包含维基文本(或其他如 CSS的平坦文本内容模型)的页面/修订版上调用基于文本的向后兼容方法,其行为取决于$wgContentHandlerTextFallback的设置:“ignore”(忽略)使其返回空值,“fail”(失败)使其引发异常,而 “serialize”(序列化)则使其返回默认的序列化内容。 默认设置为“ignore”(忽略),这可能是大多数情况下最保守的选择。

但对于编辑,默认情况下不支持非文本内容。 EditPage和Action API中的相应处理器将无法处理非文本内容。

链接

ContentContentHandler类別
设置
使用内容处理器的扩展

代碼維護