Mediawiki CommentStreams最近评论 扩展

HW 发布于 1 小时前 6 次阅读 预计阅读时间: 5 分钟


Mediawiki的CommentStreams扩展在某个版本删除了最近评论的功能,之前建站用AI弄了个扩展,服务器要过期了,先在这里备份下代码,晚点存github

结构

RecentComments/
├── extension.json
├── i18n/
│ ├── en.json
│ └── zh.json
└── includes/
├── RecentComments.alias.php
└── SpecialRecentComments.php

代码

extension.json

{
	"manifest_version": 2,
	"name": "RecentComments",
	"version": "1.1.0",
	"author": "H_W(使用AI辅助)",
	"url": "https://lostmediawiki.cn/wiki/Special:最近评论",
	"descriptionmsg": "尝试修复CommentStreams在9.0.0版本移除所有评论的诡异操作",
	"license-name": "GPL-2.0-or-later",
	"type": "specialpage",
	"SpecialPages": {
		"RecentComments": "MediaWiki\\Extension\\RecentComments\\SpecialRecentComments"
	},
	"ExtensionMessagesFiles": {
		"RecentCommentsAlias": "i18n/RecentComments.alias.php"
	},
	"MessagesDirs": {
		"RecentComments": "i18n"
	},
	"AutoloadClasses": {
		"MediaWiki\\Extension\\RecentComments\\SpecialRecentComments": "includes/SpecialRecentComments.php"
	}
}

SpecialRecentComments.php

<?php

namespace MediaWiki\Extension\RecentComments;

use MediaWiki\MediaWikiServices;
use MediaWiki\SpecialPage\SpecialPage;
use MediaWiki\Extension\CommentStreams\ICommentStreamsStore;
use MediaWiki\Extension\CommentStreams\AbstractComment;
use MediaWiki\Extension\CommentStreams\Comment;   // 新增:用于获取评论标题
use MediaWiki\Title\Title;
use MediaWiki\Parser\ParserOptions;
use MediaWiki\Html\Html;

class SpecialRecentComments extends SpecialPage {

	public function __construct() {
		parent::__construct( 'RecentComments' );
	}

	public function execute( $subPage ) {
		$this->setHeaders();
		$out = $this->getOutput();
		$request = $this->getRequest();

		$out->setPageTitleMsg( $this->msg( 'recentcomments-title' ) );

		$limit = 20;
		$offset = max( 0, (int)$request->getInt( 'offset', 0 ) );

		$services = MediaWikiServices::getInstance();
		/** @var ICommentStreamsStore $store */
		$store = $services->get( 'CommentStreamsStore' );

		$result = $store->getCommentPages( $limit, $offset );

		$comments = [];
		foreach ( $result as $row ) {
			$pageId = (int)$row->page_id;
			$comment = $store->getComment( $pageId ) ?? $store->getReply( $pageId );
			if ( $comment instanceof AbstractComment ) {
				$comments[] = $comment;
			}
		}

		if ( empty( $comments ) ) {
			$out->addWikiMsg( 'recentcomments-no-comments' );
			return;
		}

		// === 卡片样式(你原来的设置 + 小优化)===
		$out->addHTML( '<style>
			.recent-comment-card {
				background-color: var(--background-color-neutral-subtle, #f8f9fa);
				border: 1px solid var(--color-subtle, #54595d);
				border-radius: 5px;
				padding: 5px;
				margin-bottom: 24px;
				box-shadow: 0 1px 3px rgba(0,0,0,0.08);
			}
			.recent-comment-card .header-title {
				font-size: 1.5em;
				font-weight: 600;
			}
			.recent-comment-card .meta{
			    height:4.5em;
			}
			.recent-comment-card .meta .sp-avatar-wrapper img{
			    width:3em !important;
			    height:3em !important;
			}
			.recent-comment-card .meta a[title*="用户"]{
				font-size: 1.2em;
			}
			.recent-comment-card hr {
				border: none;
				border-top: 1px solid var(--color-subtle, #54595d);
			}
			.recent-comment-card .page-title {
				font-size: 1.1em;
				color: var(--color-emphasized, #101418);
				margin-bottom: 12px;
			}
		</style>' );

		$parserFactory = $services->getParserFactory();
		$parserOptions = ParserOptions::newFromContext( $this->getContext() );
		$linkRenderer = $this->getLinkRenderer();

		foreach ( $comments as $comment ) {
			$associatedTitle = $comment->getAssociatedPage();
			
			if ( !$associatedTitle || !$associatedTitle->exists() ) {
				continue;
			}
			
			$pageLink = $associatedTitle 
				? $linkRenderer->makeKnownLink( $associatedTitle, $associatedTitle->getPrefixedText() )
				: '(未知页面)';

			$author = $comment->getAuthor();
			$authorLink = $author 
				? $linkRenderer->makeKnownLink( Title::makeTitle( NS_USER, $author->getName() ), $author->getName() )
				: '(匿名)';

			//$time = $comment->getCreated()->format( 'Y-m-d H:i' );
			
			$created = $comment->getCreated();
            // 固定中文日期:2026年3月25日 12:45
            $dateStr = $created->format('Y年n月j日 H:i');
            // 计算时间差(秒)
            $diff = time() - $created->getTimestamp();
            // 极简4档判断(秒/分/时/天)
            if ($diff < 60) {
                $relative = $diff . '秒前';
            } elseif ($diff < 3600) {
                $relative = intval($diff / 60) . '分钟前';
            } elseif ($diff < 86400) {
                $relative = intval($diff / 3600) . '小时前';
            } else {
                $relative = intval($diff / 86400) . '天前';
            }
            // 最终拼接
            $time = $dateStr . '(' . $relative . ')';

			// === 新增:获取评论标题(主评论才有)===
			$commentTitle = $comment instanceof Comment 
				? $comment->getTitle() 
				: '回复';

			// 评论固定链接(用于点击标题跳转)
			$permalink = '';
			if ( $associatedTitle ) {
				$anchor = 'cs-comment-' . $comment->getId();
				$permalink = $associatedTitle->getFullURL() . '#' . $anchor;
			}

			$wikitext = $store->getWikitext( $comment );
			$parser = $parserFactory->create();
			//$parseResult = $parser->parse( $wikitext, $associatedTitle ?? $this->getTitle(), $parserOptions );
			$parseResult = $parser->parse( $wikitext, $associatedTitle ?? $this->getPageTitle(), $parserOptions );
			$transformed = $parseResult->runOutputPipeline( $parserOptions, [ 'unwrap' => true ] );
			$contentHtml = $transformed->getContentHolderText();

			// 输出卡片
			$out->addHTML( '<div class="recent-comment-card">' );
			
			// 1. 评论标题(可点击跳转)
			$headerContent = $permalink 
				? Html::element( 'a', [ 'href' => $permalink ], htmlspecialchars( $commentTitle ) )
				: htmlspecialchars( $commentTitle );
			$out->addHTML( '<div class="header-title">' . $headerContent . '</div> <div class="page-title">' . $pageLink . '</div>' );
			
			$out->addHTML( '<hr>' );
			
			// 2. 用户 + 时间
			$out->addHTML( '<div class="meta">' . $authorLink . ' · ' . htmlspecialchars( $time ) . '</div>' );
			
			// 4. 评论正文
			$out->addHTML( '<div>' . $contentHtml . '</div>' );
			
			$out->addHTML( '</div>' );
		}

		// 分页(保持不变)
		$prevOffset = $offset - $limit;
		$nextOffset = $offset + $limit;
		$hasPrev = $offset > 0;
		$hasNext = count( $comments ) >= $limit;

		if ( $hasPrev || $hasNext ) {
			$out->addHTML( '<div style="margin-top:2em;text-align:center;">' );
			if ( $hasPrev ) {
				$url = $this->getPageTitle()->getLocalURL( [ 'offset' => $prevOffset ] );
				$out->addHTML( Html::element( 'a', [ 'href' => $url ], $this->msg( 'recentcomments-prev', $limit )->text() ) . ' &nbsp;|&nbsp; ' );
			}
			if ( $hasNext ) {
				$url = $this->getPageTitle()->getLocalURL( [ 'offset' => $nextOffset ] );
				$out->addHTML( Html::element( 'a', [ 'href' => $url ], $this->msg( 'recentcomments-next', $limit )->text() ) );
			}
			$out->addHTML( '</div>' );
		}
	}
}

RecentComments.alias.php

<?php

$specialPageAliases = [];

/** English */
$specialPageAliases['en'] = [
	'RecentComments' => [ 'RecentComments' ]
];

/** Chinese (Simplified) */
$specialPageAliases['zh'] = [
	'RecentComments' => [ '最近评论' ]
];
$specialPageAliases['zh-hans'] = [
	'RecentComments' => [ '最近评论' ]
];

zh.json

{
	"recentcomments-desc": "提供一个显示 CommentStreams 全站最近评论的特殊页面。",
	"recentcomments-title": "最近评论",
	"recentcomments-no-comments": "暂无评论。",
	"recentcomments-prev": "上一页($1 条)",
	"recentcomments-next": "下一页($1 条)",
	"recentcomments-page": "所在页面",
	"recentcomments-author": "发布者",
	"recentcomments-time": "发布时间",
	"recentcomments-permalink": "固定链接",
	"recentcomments-content": "评论内容"
}

en.json

{
	"recentcomments-desc": "提供一个显示 CommentStreams 全站最近评论的特殊页面。",
	"recentcomments-title": "最近评论",
	"recentcomments-no-comments": "暂无评论。",
	"recentcomments-prev": "上一页($1 条)",
	"recentcomments-next": "下一页($1 条)",
	"recentcomments-page": "所在页面",
	"recentcomments-author": "发布者",
	"recentcomments-time": "发布时间",
	"recentcomments-permalink": "固定链接",
	"recentcomments-content": "评论内容"
}
此作者没有提供个人介绍。
最后更新于 2026-06-02