
multicontentsave 钩子是mediawiki提供的一个关键扩展点,它在页面内容被保存(无论是新建、编辑还是回退)之后触发。这个钩子为开发者提供了在内容持久化到数据库后,对页面内容进行进一步处理、分析或记录的机会。
钩子的签名如下:
public static function onMultiContentSave(
RenderedRevision $renderedRevision,
UserIdentity $user,
CommentStoreComment $summary,
$flags,
Status $hookStatus
)其中,$renderedRevision 参数是核心,它包含了当前保存的修订版本的所有信息,包括新内容。
获取页面编辑后的新内容相对直接。$renderedRevision 对象封装了当前保存的修订版本 (Revision)。我们可以通过它来访问新内容。
use MediaWiki\Revision\RenderedRevision;
use MediaWiki\Revision\RevisionRecord;
use Wikimedia\Content\SlotRecord;
class MyExtensionHooks {
public static function onMultiContentSave(
RenderedRevision $renderedRevision,
UserIdentity $user,
CommentStoreComment $summary,
$flags,
Status $hookStatus
) {
// 获取当前修订版本对象
$revision = $renderedRevision->getRevision();
// 获取页面的 LinkTarget 对象(包含页面标题信息,非直接字符串)
$title = $revision->getPageAsLinkTarget();
// 获取编辑后的新内容
// SlotRecord::MAIN 表示主内容槽
// RevisionRecord::RAW 表示获取原始维基文本内容
$new_content_object = $revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW);
$new_content_text = $new_content_object ? $new_content_object->getNativeData() : '';
// $new_content_text 现在包含了编辑后的页面内容
return true;
}
}上述代码中,$revision-youjiankuohaophpcngetContent(SlotRecord::MAIN, RevisionRecord::RAW) 返回一个 Content 对象。通过调用 $new_content_object->getNativeData(),我们可以获取到其原始的字符串表示(通常是维基文本)。
获取编辑前的旧内容是本教程的核心挑战。MediaWiki的修订版本系统通过父子关系来跟踪历史。当前修订版本对象 ($revision) 包含了对其父版本(即编辑前的版本)的引用。
以下是获取旧内容的步骤:
获取父版本ID: 每个修订版本都有一个父版本ID,指向它所基于的上一版本。我们可以通过 $revision->getParentId() 方法获取这个ID。
通过ID加载前一个修订版本: 一旦我们有了父版本ID,就可以使用 MediaWiki\Revision\RevisionStore 服务来加载对应的修订版本对象。RevisionStore::getRevisionById() 方法可以根据ID检索修订版本。
从前一个修订版本中提取内容: 加载到前一个修订版本对象后,获取其内容的方式与获取新内容类似。
下面是获取旧内容的具体实现:
use MediaWiki\Revision\RenderedRevision;
use MediaWiki\WikiPage\Revision\RevisionStore; // 确保引入正确的 RevisionStore
use MediaWiki\Revision\RevisionRecord;
use Wikimedia\Content\SlotRecord;
use MediaWiki\Content\ContentHandler; // 用于将Content对象转换为文本
class MyExtensionHooks {
public static function onMultiContentSave(
RenderedRevision $renderedRevision,
UserIdentity $user,
CommentStoreComment $summary,
$flags,
Status $hookStatus
) {
$revision = $renderedRevision->getRevision();
$title = $revision->getPageAsLinkTarget(); // 获取页面的 LinkTarget 对象
// 获取编辑后的新内容
$new_content_object = $revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW);
$new_content_text = $new_content_object ? $new_content_object->getNativeData() : '';
// --- 获取编辑前的旧内容 ---
$old_content_text = ''; // 初始化旧内容为空字符串
// 1. 获取父版本ID
$parent_id = $revision->getParentId();
// 2. 检查是否存在父版本(即不是首次创建)
if ($parent_id !== 0 && $parent_id !== null) {
// 3. 通过父版本ID加载前一个修订版本
// RevisionStore 是一个服务,通常通过 MediaWiki\MediaWikiServices::getInstance()->getRevisionStore() 获取
// 但在钩子环境中,可以直接访问静态方法 RevisionStore::getRevisionById()
$previous_revision = RevisionStore::getRevisionById($parent_id);
// 4. 检查是否成功加载到前一个修订版本
if ($previous_revision) {
// 5. 从前一个修订版本中提取内容
// Revision::RAW 获取原始内容
$old_content_object = $previous_revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW);
// 6. 将内容对象转换为文本
// ContentHandler::getContentText() 是一个通用的转换方法
$old_content_text = $old_content_object ? ContentHandler::getContentText($old_content_object) : '';
}
}
// $old_content_text 现在包含了编辑前的页面内容
// ... 在这里可以对 $new_content_text 和 $old_content_text 进行比较或处理
return true;
}
}将新旧内容获取逻辑整合在一起,可以方便地进行内容比较,例如实现一个简单的内容差异检测或审计功能。
<?php
// 导入必要的类
use MediaWiki\Hook\MultiContentSaveHook;
use MediaWiki\Revision\RenderedRevision;
use MediaWiki\User\UserIdentity;
use CommentStoreComment;
use Status;
use MediaWiki\WikiPage\Revision\RevisionStore;
use MediaWiki\Revision\RevisionRecord;
use Wikimedia\Content\SlotRecord;
use MediaWiki\Content\ContentHandler;
/**
* 示例 MediaWiki 扩展钩子类
*/
class ContentComparisonExtensionHooks implements MultiContentSaveHook {
/**
* 在内容保存后触发,用于比较编辑前后内容。
*
* @param RenderedRevision $renderedRevision 当前保存的修订版本信息
* @param UserIdentity $user 执行保存操作的用户
* @param CommentStoreComment $summary 编辑摘要
* @param int $flags 保存标志
* @param Status $hookStatus 钩子状态对象
* @return bool
*/
public function onMultiContentSave(
RenderedRevision $renderedRevision,
UserIdentity $user,
CommentStoreComment $summary,
$flags,
Status $hookStatus
): bool {
// 获取当前修订版本对象
$currentRevision = $renderedRevision->getRevision();
$pageTitle = $currentRevision->getPageAsLinkTarget()->getText(); // 获取页面标题字符串
// --- 获取编辑后的新内容 ---
$newContentObject = $currentRevision->getContent(SlotRecord::MAIN, RevisionRecord::RAW);
$newContentText = $newContentObject ? ContentHandler::getContentText($newContentObject) : '';
// --- 获取编辑前的旧内容 ---
$oldContentText = ''; // 默认旧内容为空
$parentId = $currentRevision->getParentId();
// 检查是否存在父版本 (即不是首次创建页面)
if ($parentId !== 0 && $parentId !== null) {
// 通过父版本ID加载前一个修订版本
$previousRevision = RevisionStore::getRevisionById($parentId);
if ($previousRevision) {
// 从前一个修订版本中提取内容
$oldContentObject = $previousRevision->getContent(SlotRecord::MAIN, RevisionRecord::RAW);
$oldContentText = $oldContentObject ? ContentHandler::getContentText($oldContentObject) : '';
} else {
// 无法加载到前一个修订版本 (可能ID无效或已删除)
wfDebugLog('ContentComparisonExtension', "Warning: Could not load previous revision with ID $parentId for page $pageTitle.");
}
} else {
// 这是页面的首次创建,没有旧内容
wfDebugLog('ContentComparisonExtension', "Page '$pageTitle' was created. No old content to compare.");
}
// --- 进行内容比较或进一步处理 ---
if ($oldContentText !== $newContentText) {
// 内容发生了变化
wfDebugLog('ContentComparisonExtension', "Page '$pageTitle' content changed.");
// 可以在此处执行差异分析、记录日志、发送通知等操作
// 例如:
// $diff = new \MediaWiki\Diff\TextDiffer();
// $changes = $diff->getDiff($oldContentText, $newContentText);
// ...
} else {
// 内容没有变化 (可能只是保存了空编辑或元数据编辑)
wfDebugLog('ContentComparisonExtension', "Page '$pageTitle' content unchanged.");
}
return true; // 总是返回 true,除非你想阻止保存操作
}
}在 extension.json 中注册钩子:
{
"name": "ContentComparisonExtension",
"version": "1.0.0",
"AutoloadClasses": {
"ContentComparisonExtensionHooks": "ContentComparisonExtensionHooks.php"
},
"Hooks": {
"MultiContentSave": [
"ContentComparisonExtensionHooks::onMultiContentSave"
]
},
"manifest_version": 2
}错误处理与空值检查:
性能考虑:
内容格式:
钩子返回值:
通过本教程,我们详细学习了如何在MediaWiki扩展的MultiContentSave钩子中,有效地获取页面编辑前后的内容。关键在于利用RenderedRevision对象获取当前修订版本,并通过其getParentId()方法和RevisionStore服务来检索并访问前一个修订版本的内容。掌握这些技术,开发者可以构建出功能强大、能够深入分析和处理页面内容变化的MediaWiki扩展。在实际开发中,务必注意错误处理、性能优化以及内容格式的兼容性。
以上就是MediaWiki扩展中获取页面编辑前后内容的教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号