Manual:开发扩展

本頁面是針對MediaWiki開發扩展的指南。 在您開始之前,請先瀏覽 complete list in: Category:Extensions by category zh,看看是否已經存在適用於您使用情況的扩展。
扩展的開發包括這些部份:
设置
若要設定新的扩展,請先從設定一個針對MediaWiki的本機開發環境開始,並依照指示安裝及複製BoilerPlate扩展。
$wgMainCacheType = CACHE_NONE和$wgCacheDirectory = false以关闭缓存,否则系统消息和其它变化可能不会出现。
结构
一个最小的扩展有下列结构:
- MyExtension/extension.json
- 存储设置的指令。 文件名必须为
extension.json。 (在MediaWiki 1.25版之前,设置指令位于一个以扩展名命名的MyExtension/MyExtension.php文件中。 许多扩展在此PHP文件中仍然具有向后兼容的裕度。) - MyExtension/includes/ (or MyExtension/src/)
- 存储扩展的PHP可执行代码。
- MyExtension/resources/ (or MyExtension/modules/)
- 存储扩展的客户端资源,例如JavaScript、CSS和LESS。
- MyExtension/i18n/*.json
- 存储扩展的本地化信息。
- MyExtension/README.md
- 良好的做法是新增一個 README 檔案,其中包含如何安裝和設定扩展的基本資訊。 使用純文字或Markdown。 純文字範例,請參閱Phabricator Diffusion頁面上Extension:Page Forms(页面表单)。 如果使用 markdown,請加入檔案的副檔名
.md。 例如,請參閱Phabricator Diffusion上Parsoid的README.md檔案。
当您在开发扩展时,请将上文中的MyExtension替换为您开发的扩展的名字。 請使用「大驼峰式命名法」来命名文件夹和PHP文件,这是文件命名的通常惯例。[1]
注册
| MediaWiki版本: | ≥ 1.25 |
extension.json檔案包含扩展的配置資料。以下是一個最小的$2的範例:
Here is an example of a minimal extension.json:
{
"name": "MyExtension",
"author": "John Doe",
"url": "https://www.mediawiki.org/wiki/Extension:MyExtension",
"description": "This extension is an example.",
"version": "1.5",
"license-name": "GPL-2.0-or-later",
"type": "validextensiontype",
"manifest_version": 2
}
字段消得人憔悴,填写它们終不悔(许多字段都是可选擇性的,但填写它们仍然是一个好习惯)。
有關extension.json的更完整範例,請參閱BoilerPlate扩展。
manifest_version指的是extension.json文件所针对的架构版本。
请参见此功能的文档。
除非您需要去支持较旧版本的MediaWiki,否则请选择最新版本。
一旦您為您的擴充功能設定了 extension.json 檔案,該擴充功能就會出現在您本機的 Special:Version 頁面上。
许可证
MediaWiki is an open-source project and users are encouraged to make any MediaWiki extensions under an Open Source Initiative (OSI) approved license compatible with GPL-2.0-or-later (Wikimedia's standard software license).
We recommend adopting one of the following compatible licenses for your projects in Gerrit:
- GNU General Public License, version 2 or later (GPL-2.0-or-later)
- MIT License (MIT)
- BSD License (BSD-3-Clause)
- Apache License 2.0 (Apache-2.0)
For extensions that have a compatible license, you can request developer access to the MediaWiki source repositories for extensions.
To specify the licence in code and with "license-name" a key should be used to provide its short name, e.g. "GPL-2.0-or-later" or "MIT" adhering to the list of identifiers at spdx.org.
讓您的扩展可由用户配置
理想的情況是,使用者只需在 LocalSettings.php 中加入一行即可安裝您的扩展:
wfLoadExtension( 'MyExtension' );
如果你要讓你的扩展是用户可配置的,则需要定义和记录一些配置参数,并且用户的设置应如下所示:
wfLoadExtension( 'MyExtension' );
$wgMyExtensionConfigThis = 1;
$wgMyExtensionConfigThat = false;
如果您希望用户能够配置您的扩展,则需要提供一个或多个配置变量。 最好能给这些变量起一个唯一的名称。 同样需要遵循MediaWiki命名常规(例如,全局变量名应以$wg作为开始)。
例如,如果您扩展的名字为MyExtension,您可能想要以$wgMyExtension作为所有相关的配置变量命名的开始。
重要的是,沒有任何一個MediaWiki核心是以這種方式開始它的變數,而且你也做了合理的檢查工作,去看看是否沒有任何一個已發佈的扩展以這種方式開始它們的變數。
用户們不会因为您選擇使用了重叠的变量名而欣然接受在您的扩展和其它扩展之间选择。
將所有配置变量的详尽文档包含在安装註解中也是個不錯的點子。
以下是如何在 extension.json 中設定設定變數的範例:
{
"config": {
"BoilerPlateEnableFoo": {
"value": true,
"description": "Enables the foo functionality"
}
}
}
注意:在调用wfLoadExtension( 'BoilerPlate' );之后,全局变量$wgBoilerPlateEnableFoo不會存在。
如果您为变量赋值(例如在LocalSettings.php中),则将不会使用来自extension.json的值。
关于在扩展中使用通用变量,请参考Configuration for developers。
准备类給自动加载使用
如果您選擇使用类來开发您的扩展,MediaWiki提供了一個簡化的機制來幫助PHP找到你的类所在的原始檔案。
在大多数情况下,这可免去开发自己的__autoload($classname)的需要。
如想使用MediaWiki的自动加载機制,您需要添加入口到AutoloadClasses字段。 "鍵"是每個入口的类名稱;"值"是儲存类的定義的檔案。 对于一个简单的单一类文件扩展,经常將类与扩展同名。所以您的自动加载段落的内容可能是如下(扩展名為MyExtension):
{
"AutoloadClasses": {
"MyExtension": "includes/MyExtension.php"
}
}
文件名的路径是相对於extension.json文件所在目录。
对于更复杂的扩展,應該要將命名空間列入考虑。 参见Manual:Extension.json/Schema#AutoloadNamespaces以获取更多细节。
處理依存
Some extensions require other extensions to be installed. For example, TemplateStylesExtender depends on TemplateStyles(模板样式).
To enforce hard dependencies of this sort, use the requires key in extension.json.
In other cases, some extensions provide additional optional functionality if other extensions are installed.
For example MobileFrontend(移动版前端) will display short descriptions only if Wikibase Client is installed.
These optional dependencies can be implemented using the isLoaded method of the ExtensionRegistry class.
For example:
if ( ExtensionRegistry::getInstance()->isLoaded( 'WikibaseClient' ) ) {
/* 做一些額外的事,如果扩展HitCounters存在於1.1版本或以上 */
}
目前(截至2024年2月,MediaWiki 1.41.0版),要檢查的扩展的名稱需要與其 extension.json 中的名稱完全匹配。[2][3]
如果您要檢查扩展OpenIDConnect的載入狀態,您必須在使用時加上一個「空格」。
if ( ExtensionRegistry::getInstance()->isLoaded( 'OpenID Connect' ) ) {
...
}
实现
對於扩展的程式碼架構、結構、和慣例的概述,請參閱扩展的最佳实践.
扩展入口点
MediaWiki 核心提供了幾種方式讓扩展改變wiki的行為、機能、和外觀。 大多數的扩展都會使用一個以上的扩展入口點。 如需extension.json中所支援的完整扩展入口點清單,請參閱模式參考。
通用
- 钩子: 在MediaWiki核心程式碼的關鍵點注入自訂的程式碼,例如當使用者登入或儲存頁面時。 扩展也可以定義新鉤點。
- Domain events: 對 wiki 狀態的變化做出反應,例如當一個頁面被編輯時。 擴充功能也可以定義自己的事件。 1.44
- API模块: 根據Action API或REST API定義API模組。 這些模組可由機器人或用戶端呼叫。
- 工作: 在MediaWiki的JobQueue中加入工作,以非同步方式執行流程密集型任務,例如發送通知郵件。
页面
- 顯示一個特殊頁面: 特殊頁面會提供動態產生的內容,這些通常是基於系統狀態、資料庫查詢、和使用者輸入。
- 執行一個頁面動作:
actionURL參數會根據目前頁面產生自訂頁面,通常是為了提供資訊 (例如頁面歷史) 或執行動作 (例如編輯頁面)。 除了MediaWiki核心提供的預設動作之外,扩展可以定義新的頁面動作。 - 新增一個追蹤分類: 透過自動將頁面加入自訂分類,協助使用者找到具有類似特徵的頁面。
內容
- 擴充 wiki 標記: 扩展可以使用模板語法(
{{...}})或標籤(<example />),在MediaWiki的wikitext標記中加入自訂機能。 這些自訂機能用來產生內容,並在頁面渲染時與MediaWiki互動。 - 支援一種內容模型: 預設情況下,wiki 頁面可以使用一些標準的內容模型來儲存,例如wikitext和JSON。 擴充功能可透過新增內容處理程式,提供對新內容模型的支援。
- 支援一種媒體類型: 擴充功能可透過新增媒體處理程式,加入到預設的支援媒體檔案類型。
調節工具
- 記錄使用者或系統的動作: 在 wiki 上,其行動是可追蹤的,以提高透明度和協作性。 為了支援此功能,擴充功能可以在 Special:Log 中加入自訂項目和功能。
- 新增最近變更標誌: 擴充功能可以在下列特殊頁面中加入自訂旗標,以協助仲裁人追蹤頁面變更: Special:RecentChanges, Special:Watchlist, Special:RecentChangesLinked
- 新增修訂標籤: 擴充功能可以新增與版本或記錄項目相關的註解,例如使用VisualEditor擴充功能進行的編輯。
验证
- 新增一個提供者: 擴充功能可以新增對新登入機制及工作階段管理方法的支援。
添加数据库表格
確保擴充功能不會修改核心資料庫的資料表。 取而代之的是,擴充功能應該建立新的資料表,並將外鍵連接到相關的MW資料表。
如果您的擴充功能需要新增自己的資料庫表,請使用LoadExtensionSchemaUpdates鉤點。 有關使用的詳細資訊,請參閱手冊頁面。
為其他擴充功能註冊屬性
屬性可讓擴充功能去向其他擴充功能註冊某個東西,例如模組。 例如,擴充功能可以使用屬性來向VisualEditor擴充功能註冊外掛模組。 更多信息,请参见扩展注册。
本地化
|
$wgMainCacheType = CACHE_NONE 和 $wgCacheDirectory = false 來停用這兩個快取,否則您的系統訊息變更可能無法顯示。如果您希望您的擴充功能用在有多國語言讀者的 wiki 上,您需要將本地化支援加入到擴充功能中。
在<language-key>.json中儲存訊息
將訊息定義儲存在本地化的JSON檔案中,您的擴充功能要翻譯成的每種語言都要有一個。 訊息會以標準 JSON 格式儲存訊息鍵和訊息本身。 每個訊息 ID 應該是小寫,並且不可包含空格。 每個鍵都應該以小寫的擴充功能的名稱為開頭。 您可以在 MobileFrontend 擴充功能中找到一個範例。 以下是最小 JSON 檔案的範例 (在此例中為 en.json):
en.json
{
"myextension-desc": "Adds the MyExtension great functionality.",
"myextension-action-message": "This is a test message"
}
在qqq.json中儲存訊息文件
訊息鍵的文件可以儲存在偽語言的 JSON 檔案中,代碼為qqq。 上述範例的文件可以是:
qqq.json:
{
"myextension-desc": "The description of MyExtension used in Extension credits.",
"myextension-action-message": "Adds 'message' after 'action' triggered by user."
}
載入本地化檔案
在您的 extension.json 中,定義訊息檔案的位置 (例如在目錄 i18n/ 中):
{
"MessagesDirs": {
"MyExtension": [
"i18n"
]
}
}
在PHP中使用wfMessage
在您的設定和實作程式碼中,將訊息的每個字面用法換成呼叫 wfMessage( $msgID, $param1, $param2, ... )。
在實作 IContextSource 的類別中(以及其他一些類別,例如 SpecialPage 的子類別),您可以使用 $this->msg( $msgID, $param1, $param2, ... ) 來取代。
例如:
wfMessage( 'myextension-addition', '1', '2', '3' )->parse()
在JavaScript中使用mw.message
在JavaScript中也可以使用i18n函式。 詳情請參閱 Manual:系统消息API。
发佈
若要自動歸類和標準化您現有擴充功能的文件,請參閱 Template:扩展. 將您的新擴充功能加入此Wiki:
在MediaWiki代碼庫中分享其代碼的開發者應該會期待:
- 反饋/批評/程式碼檢閱
- 由其他開發人員針對架構使用、安全性、效率、與可用性等事項進行檢閱與評論。
- 開發人員的調校
- 其他開發人員修改您提交的程式,以改善或清理您的程式碼,以符合新的架構類別和方法、編碼慣例和翻譯。
- 改善wiki的系統管理員的存取權限
- 如果您決定將您的程式碼放在wiki上,其他開發者可能會決定將它移到MediaWiki程式碼儲存庫來方便維護。 然後,您可以建立一個开发者账户來繼續維護。
- 由其他開發人員貢獻的未來版本
- 當MediaWiki推出新版本時,您的程式碼會自動建立新的分支。 如果您想要支援舊版,應該向後移植到這些分支。
- 將您的程式碼併入具有重複或類似目的的其他扩展--納入到每個扩展的最佳功能。
- 归功于
- 在未來版本中歸功於您的工作成果--包括任何合併的扩展。
- 同樣地,如果您借用了任何扩展的程式碼,您應該將其歸功於該功能的開發者--尤其是在執行合併時。
任何開發人員如果對發生的任何這些行為感到不舒服,就不應該寄存在程式碼儲存庫中。 我們仍然鼓勵您在wiki上為您的扩展建立一個摘要頁面,讓人們認識這個扩展,並且知道哪裡可以下載。
部署與註冊
如果您打算將您的擴充功能部署在各個維基媒體網站(可能包括維基百科),則需要在效能和安全性方面進行額外的仔細檢查。 請諮詢 编写一個部署用的扩展.
如果您的擴充功能增加了命名空間,您可能希望註冊其預設命名空間;同樣地,如果您的擴充功能增加了資料庫表或欄位,您可能希望在 数据库字段前缀註冊這些資料庫表或欄位。
請知悉,在維基媒體網站上,新擴充功能的審核和部署可能會極度慢條斯禮,在某些情況下需要长达兩年以上的時間。[4]
說明文件
您應該針對您的擴充功能所提供的功能,提供公有領域說明文件。
根據慣例,擴充功能應在Help:Extension:<ExtensionName>的假性名稱空間下建立以使用者為中心的說明網頁,並隨附所需的子頁面 (如果存在的話,頂層頁面會自動從擴充功能的資訊框連結)。
Help:CirrusSearch 是一個良好文件的範例。
您應該透過 addHelpLink() 函式提供給使用者指向文件的連結。
發佈更新
有許多常見的方法可發佈擴充功能的更新。
這些通常是根據擴充功能(master、rel或ltsrel)的相容政策來定義的:
master– 版本可以在主分支上標示版本號,並在擴充功能的首頁提供說明文件,描述哪些擴充功能版本與哪些核心版本相容。 發行版的分支仍會自動建立,如果您不打算使用這些分支,不妨將其刪除。rel和ltsrel– 透過將變更向後移植到REL1_*分支來發佈 (可以是所有變更,也可以只釋放重要的變更)。 除非擴充功能是另一個擴充功能的依存套件,否則一般不需要版本號(這時可以在其他擴充功能的設定中提供版本號,以確保不會安裝不相容的組合)。 許多擴充功能多年來都維持相同的版本號碼。
支援其他核心版本
支援舊版MediaWiki的核心有兩種廣泛的慣例:
- 主分支:擴充功能的主分支與盡可能多的舊版核心相容。這會造成維護上的負擔(向後相容的文書工作需要持續一段長的時間,擴充功能的變更也需要在多個版本的 MediaWiki 上進行測試),但是執行舊版 MediaWiki 的網站可以從擴充功能最近新增的功能中獲益。
- 釋出分支:擴充功能的釋出分支與匹配的核心分支相容,例如使用 MediaWiki 1.45 的網站需要使用擴充功能的 REL1_45 分支。 (對於託管在Gerrit上的擴充功能,會在MediaWiki推出新版本時自動建立這些分支)。 這會使程式碼更乾淨、開發速度更快,但使用舊核心版本的使用者無法受惠於錯誤修正和新功能,除非手動將它們向後移植。
擴充功能的維護者應該在{{扩展}}模版的compatibility policy參數中聲明他們所遵循的慣例。
提供支援/协作
擴充功能的開發者應該在維基媒體的Phabricator中開立一個帳號,並為該擴充功能申請一個新的项目。 這提供了一個公共場所,使用者可以在此提交問題和建議,您也可以與使用者和其他開發人員合作,以處理bug並規劃你的擴充功能。
参见
- Manual:扩展注册 – 提供進一步的開發人員文件,說明如何註冊擴充功能和外觀。
- API:扩展 – 說明您的擴充功能如何提供 API 給用戶端
- Manual:Extending wiki markup
- Manual:代码编写约定
- 擴充功能的最佳實作
- 资源加载器
從範例中學習
- 扩展:Examples – 實作一些範例功能,並提供擴充功能的內嵌說明文件
- Extension:BoilerPlate – 是個可運作的範本擴充功能,可作為您自己的擴充功能的起點 (git存储库).
- 請「參照」範本擴充功能,以樣本擴充功能「做為您自己的程式碼的基礎」。
- cookiecutter-mediawiki-extension – 是個cookiecutter模板,它會產生一個樣本擴充功能 (包含變數等)
- ** 可讓您快速開始使用自己的擴充功能。
- 也可產生樣本擴充功能。
- 簡單擴充功能的列表 – 複製其中的特定程式碼
參考資料
- ↑ mailarchive:wikitech-l/2011-August/054839.html
- ↑ https://www.mediawiki.org/wiki/Project%3ASupport%20desk/Flow/2024/02#h-%5BDeveloper_question%5D_ExtensionRegistry%3A%3AgetInstance%28%29-%3EisLoaded%28_%27OpenIDConnect%27-20240204084500
- ↑ https://phabricator.wikimedia.org/T356596
- ↑ phabricator:T148848