在MediaWiki扩展中比较页面编辑前后内容的实践指南

心靈之曲
发布: 2025-10-09 10:53:53
原创
524人浏览过

在MediaWiki扩展中比较页面编辑前后内容的实践指南

本教程旨在指导开发者如何在MediaWiki扩展中,利用MultiContentSave钩子获取页面编辑前后的内容。文章详细介绍了如何从当前保存的修订版本中提取新内容,以及如何通过父修订ID获取并解析旧内容,并提供了完整的代码示例和注意事项,帮助开发者实现页面内容差异对比等功能。

MediaWiki扩展中获取页面编辑前后内容

在开发mediawiki扩展时,有时需要获取页面在保存编辑前后的内容,以便进行内容对比、审计、触发特定逻辑或集成外部服务。multicontentsave钩子是实现这一目标的关键入口点,它在页面内容被保存后触发,并提供了访问新修订版本信息的途径。

1. 理解 MultiContentSave 钩子

MultiContentSave钩子在多内容模型(MultiContent model)下保存内容时被调用。其签名如下:

public static function onMultiContentSave(
    RenderedRevision $renderedRevision,
    UserIdentity $user,
    CommentStoreComment $summary,
    $flags,
    Status $hookStatus
)
登录后复制

其中,$renderedRevision参数包含了新保存的修订版本的所有信息,是获取新内容的主要来源。

2. 获取编辑后的新内容

从$renderedRevision中获取编辑后的新内容相对直接。RenderedRevision对象封装了一个RevisionRecord,我们可以通过它来访问具体的页面内容。

use MediaWiki\Revision\RenderedRevision;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Revision\SlotRecord;
use MediaWiki\Content\ContentHandler;
use MediaWiki\Storage\RevisionStore;
use MediaWiki\User\UserIdentity;
use CommentStoreComment;
use Status;

class MyExtensionHooks {
    public static function onMultiContentSave(
        RenderedRevision $renderedRevision,
        UserIdentity $user,
        CommentStoreComment $summary,
        $flags,
        Status $hookStatus
    ) {
        $revision = $renderedRevision->getRevision();
        $title = $revision->getPageAsLinkTarget(); // 获取页面LinkTarget对象

        // 获取新内容
        // SlotRecord::MAIN 表示主内容槽
        // RevisionRecord::RAW 表示获取原始内容对象
        $new_content_object = $revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW);
        // 将内容对象转换为文本
        $new_content_text = ContentHandler::getContentText($new_content_object);

        // ... 后续处理 ...

        return true;
    }
}
登录后复制

这里,$revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW)会返回一个Content对象,然后使用ContentHandler::getContentText()将其转换为可读的文本格式。

稿定PPT
稿定PPT

海量PPT模版资源库

稿定PPT 146
查看详情 稿定PPT

3. 获取编辑前的旧内容

获取编辑前的旧内容需要通过当前修订版本的父修订ID来追溯。每个修订版本(除了页面的首次创建)都会有一个指向其前一个版本的父修订ID。

use MediaWiki\Revision\RenderedRevision;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Revision\SlotRecord;
use MediaWiki\Content\ContentHandler;
use MediaWiki\Storage\RevisionStore; // 引入RevisionStore
use MediaWiki\User\UserIdentity;
use CommentStoreComment;
use Status;

class MyExtensionHooks {
    public static function onMultiContentSave(
        RenderedRevision $renderedRevision,
        UserIdentity $user,
        CommentStoreComment $summary,
        $flags,
        Status $hookStatus
    ) {
        $revision = $renderedRevision->getRevision();
        $title = $revision->getPageAsLinkTarget();

        // 获取新内容
        $new_content_object = $revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW);
        $new_content_text = ContentHandler::getContentText($new_content_object);

        // 获取父修订ID
        $parent_id = $revision->getParentId();

        $old_content_text = null; // 初始化旧内容变量

        // 检查是否存在父修订(即不是页面首次创建)
        if ($parent_id !== null && $parent_id !== 0) {
            // 通过RevisionStore加载父修订版本
            // RevisionStore::singleton() 获取RevisionStore实例
            $previous_revision = RevisionStore::singleton()->getRevisionById($parent_id);

            // 检查是否成功加载到旧修订版本
            if ($previous_revision) {
                // 获取旧内容对象
                // 注意:旧版本的getContent方法可能需要Revision::RAW而不是RevisionRecord::RAW
                // 推荐使用SlotRecord::MAIN和RevisionRecord::RAW以保持一致性
                $old_content_object = $previous_revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW);
                if ($old_content_object) {
                    $old_content_text = ContentHandler::getContentText($old_content_object);
                }
            }
        }

        // 至此,您已拥有 $new_content_text 和 $old_content_text (如果存在旧版本)
        // 可以在这里进行内容对比或其他业务逻辑
        // 例如:
        // if ($old_content_text !== null) {
        //     $diff = self::compareContent($old_content_text, $new_content_text);
        //     // 处理差异
        // }

        return true;
    }

    // 示例:一个简单的内容比较函数
    // private static function compareContent(string $old, string $new): array {
    //     // 这里可以集成MediaWiki的DiffEngine或其他第三方库进行内容差异比较
    //     // 简单示例:
    //     return [
    //         'old_length' => strlen($old),
    //         'new_length' => strlen($new),
    //         'is_changed' => ($old !== $new)
    //     ];
    // }
}
登录后复制

4. 关键点与注意事项

  • getParentId() 返回值:
    • 如果页面是首次创建,getParentId()将返回0。
    • 如果父修订ID未定义或未知,将返回null。
    • 因此,在尝试加载旧修订之前,务必检查$parent_id是否不为null且不为0。
  • RevisionStore::getRevisionById():
    • 此方法用于根据ID加载RevisionRecord对象。
    • 如果找不到对应ID的修订版本,它将返回null,因此需要进行非空检查。
    • 为了获取RevisionStore的实例,通常使用RevisionStore::singleton()。
  • getContent() 参数:
    • 对于新旧修订,获取主内容槽的原始数据,应使用SlotRecord::MAIN和RevisionRecord::RAW。
  • ContentHandler::getContentText():
    • 这是一个非常实用的工具函数,可以将各种Content对象(如WikitextContent、JsonContent等)统一转换为其文本表示形式,便于进行字符串比较。
  • 性能考量:
    • 在每次保存时加载旧修订版本会增加数据库查询的开销。对于流量非常大的Wiki,如果此功能不是核心需求,应谨慎评估其性能影响。
  • 错误处理:
    • 始终对RevisionStore::getRevisionById()和$previous_revision->getContent()的返回值进行检查,以避免空指针引用错误。
  • 内容类型:
    • MediaWiki支持多种内容模型(例如维基文本、JSON、CSS等)。getContentText()会尝试返回内容的文本表示。如果需要处理特定类型的内容(例如解析JSON内容),则可能需要先检查$new_content_object->getModel()。

总结

通过MultiContentSave钩子,结合RenderedRevision、RevisionRecord和RevisionStore,开发者可以有效地获取MediaWiki页面编辑前后的内容。这为实现强大的扩展功能提供了基础,例如版本差异显示、内容审核工作流、自动化内容处理等。在实现过程中,务必关注代码的健壮性和性能,确保扩展在各种场景下都能稳定运行。

以上就是在MediaWiki扩展中比较页面编辑前后内容的实践指南的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号