
MultiContentSave 钩子是MediaWiki提供的一个重要扩展点,它在页面内容被保存(无论是新建、编辑还是回滚)之后但在事务提交之前触发。这个钩子提供了对当前正在保存的修订版本(RenderedRevision)的访问权限,是进行页面内容分析、日志记录或内容审核等操作的理想位置。
在钩子函数中,我们可以通过传入的参数获取到关于本次保存操作的各种信息,包括用户、编辑摘要以及最关键的——修订版本对象。
当 MultiContentSave 钩子触发时,$renderedRevision 参数包含了当前新保存的页面修订版本信息。从中获取新内容是相对直接的。
<?php
use MediaWiki\Revision\RenderedRevision;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Revision\SlotRecord;
use MediaWiki\User\UserIdentity;
use MediaWiki\Status\Status;
use CommentStoreComment;
use RevisionStore;
use ContentHandler;
class MyExtensionHooks {
public static function onMultiContentSave(
RenderedRevision $renderedRevision,
UserIdentity $user,
CommentStoreComment $summary,
$flags,
Status $hookStatus
) {
// 获取当前修订版本记录
$revision = $renderedRevision->getRevision();
// 获取页面标题对象,这是一个LinkTarget对象,而非字符串
$title = $revision->getPageAsLinkTarget();
// 获取新编辑后的主内容槽(SlotRecord::MAIN)的原始数据
// getNativeData() 返回内容对象的原生数据,通常是字符串形式的页面内容
$new_content = $revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW)->getNativeData();
// ... 后续处理 ...
return true;
}
}在上述代码中:
获取编辑前的页面内容需要稍微多一步操作,因为它涉及到查询历史版本。MediaWiki的修订版本系统通过父ID来链接历史版本。
<?php
// ... (use 语句与 MyExtensionHooks 类定义同上) ...
class MyExtensionHooks {
public static function onMultiContentSave(
RenderedRevision $renderedRevision,
UserIdentity $user,
CommentStoreComment $summary,
$flags,
Status $hookStatus
) {
$revision = $renderedRevision->getRevision();
$title = $revision->getPageAsLinkTarget();
$new_content = $revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW)->getNativeData();
// 获取当前修订版本的父版本ID
// 如果没有父版本(例如,页面是新建的),getParentId() 将返回 0
// 如果父版本未定义或未知,可能返回 null
$parent_id = $revision->getParentId();
$old_content_text = null; // 初始化旧内容为 null
// 只有当存在有效的父版本ID时,才尝试获取旧内容
if ( $parent_id > 0 ) {
// 通过父版本ID从RevisionStore加载旧的修订版本记录
// 如果找不到对应的修订版本,getRevisionById() 将返回 null
$previous_revision = RevisionStore::singleton()->getRevisionById( $parent_id );
if ( $previous_revision ) {
// 获取旧修订版本的主内容槽的原始内容对象
$old_content = $previous_revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW);
// 将内容对象转换为文本字符串
// ContentHandler::getContentText() 是一个安全且推荐的方法
$old_content_text = ContentHandler::getContentText( $old_content );
}
}
// 此时,$new_content 包含新编辑后的内容
// $old_content_text 包含编辑前的旧内容(如果存在)
// 可以在这里进行内容比较或其他逻辑
// 例如:
if ( $old_content_text !== null ) {
// 进行差异比较或分析
// error_log("页面 '{$title->getText()}' 内容变更:");
// error_log("旧内容长度: " . strlen($old_content_text));
// error_log("新内容长度: " . strlen($new_content));
} else {
// error_log("页面 '{$title->getText()}' 是新建的,没有旧内容。");
}
return true;
}
}在上述代码中:
将上述逻辑整合到一起,可以形成一个完整的钩子实现。
<?php
// 引入必要的类
use MediaWiki\Revision\RenderedRevision;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Revision\SlotRecord;
use MediaWiki\User\UserIdentity;
use MediaWiki\Status\Status;
use CommentStoreComment;
use RevisionStore; // 用于获取历史版本
use ContentHandler; // 用于将Content对象转换为文本
class MyExtensionHooks {
public static function onMultiContentSave(
RenderedRevision $renderedRevision,
UserIdentity $user,
CommentStoreComment $summary,
$flags,
Status $hookStatus
) {
$revision = $renderedRevision->getRevision();
$title = $revision->getPageAsLinkTarget(); // 获取页面标题对象
// 获取新编辑后的页面内容
$new_content = $revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW)->getNativeData();
$old_content_text = null; // 初始化旧内容变量
// 获取父版本ID
$parent_id = $revision->getParentId();
// 检查是否存在父版本(即页面是否不是新建的)
if ( $parent_id > 0 ) {
// 尝试加载父修订版本
$previous_revision = RevisionStore::singleton()->getRevisionById( $parent_id );
if ( $previous_revision ) {
// 成功获取到父修订版本,提取其主内容槽的文本
$old_content = $previous_revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW);
$old_content_text = ContentHandler::getContentText( $old_content );
} else {
// 理论上不应该发生,除非数据库异常或父ID无效
// error_log("警告: 无法找到ID为 {$parent_id} 的父修订版本。");
}
}
// 至此,您已拥有:
// $title: 页面标题对象
// $new_content: 新编辑后的页面内容字符串
// $old_content_text: 编辑前的页面内容字符串 (如果页面不是新建的且成功获取到)
// 您可以在这里实现您的核心逻辑,例如:
if ( $old_content_text !== null ) {
// 比较 $new_content 和 $old_content_text 的差异
// 例如,计算差异、记录变更日志、触发特定工作流等
// error_log("页面 '{$title->getText()}' 内容已从 '{$old_content_text}' 变为 '{$new_content}'");
} else {
// 页面是新建的,只有新内容
// error_log("页面 '{$title->getText()}' 已创建,内容为 '{$new_content}'");
}
// 钩子函数必须返回 true 以继续MediaWiki的正常保存流程
return true;
}
}注意事项:
通过在MediaWiki扩展的 MultiContentSave 钩子中结合 RenderedRevision、getParentId() 和 RevisionStore::getRevisionById(),开发者可以有效地获取并比较页面在编辑前后的内容。这种能力为构建各种高级功能奠定了基础,例如内容版本控制工具、自动审核系统、变更通知或自定义内容分析。理解并正确应用这些方法是开发强大MediaWiki扩展的关键。
以上就是在MediaWiki扩展中比较页面编辑前后内容变更的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号