fix(admin): replicate reference comment settings page 1:1
- Rewrite post_list/comment schema (PHP + JS) with the reference theme's field set, order, defaults and dependencies; smilie, comment location and quick-reply fields excluded - Map PostDisplay::get_comment_display_settings() to the new keys without legacy fallback: close_comments, comment_paginate_type (ajax_lists), user_edit_comment master switch, WP comment_order for sorting - Wire comment_box_hide visibility gate (signin / vip / vip_2 / auth) - Drop dead comment settings (order/per_page/depth/avatar/hot threshold/ empty text/city), the dead post_close_comments field, and city readers now fully owned by the IP-geo extension - Add comment settings reference contract test
This commit is contained in:
@@ -2,102 +2,80 @@ export const commentSchema = {
|
||||
key: 'post_list.comment',
|
||||
title: '评论设置',
|
||||
icon: 'fa fas fa-comment-dots',
|
||||
description: '配置评论区的排序、分页、权限、工具栏与互动方式。',
|
||||
description: '配置评论模块的显隐条件、翻页模式、输入工具栏与互动方式。',
|
||||
defaults: {
|
||||
comment_order: 'asc',
|
||||
comment_per_page: 20,
|
||||
comment_pagination_type: 'numbered',
|
||||
close_comments: false,
|
||||
comment_box_hide: '',
|
||||
comment_paginate_type: 'default',
|
||||
comment_paging_ajax_ias_s: true,
|
||||
comment_paging_ajax_ias_max: 3,
|
||||
comment_nested_depth: 3,
|
||||
comment_avatar_size: 48,
|
||||
comment_close_comments: false,
|
||||
comment_edit_window: 10,
|
||||
comment_code: true,
|
||||
comment_img: true,
|
||||
comment_upload_img: false,
|
||||
comment_link: false,
|
||||
comment_like_s: true,
|
||||
comment_hot_threshold: 10,
|
||||
comment_city_s: true,
|
||||
comment_city_type: 'province_city',
|
||||
comment_user_url_s: false,
|
||||
comment_author_tag: true,
|
||||
user_edit_comment: true,
|
||||
comment_like_s: true,
|
||||
comment_user_url_s: false,
|
||||
comment_corderby: true,
|
||||
comment_empty_text: '暂无评论,来做第一个评论的人吧~',
|
||||
comment_title: '评论',
|
||||
comment_submit_text: '提交评论',
|
||||
comment_text: '欢迎您留下宝贵的见解!',
|
||||
},
|
||||
groups: [
|
||||
{
|
||||
key: 'display',
|
||||
title: '评论展示',
|
||||
icon: 'fa fas fa-comment',
|
||||
key: 'comment',
|
||||
title: '',
|
||||
fields: [
|
||||
{ key: 'comment_order', label: '评论排序', type: 'radio', default: 'asc', options: [
|
||||
{ label: '正序 (旧→新)', value: 'asc' },
|
||||
{ label: '倒序 (新→旧)', value: 'desc' },
|
||||
]},
|
||||
{ key: 'comment_per_page', label: '每页评论数', type: 'number', default: 20, min: 5, max: 100 },
|
||||
{ key: 'comment_pagination_type', label: '分页方式', type: 'radio', default: 'numbered', options: [
|
||||
{ label: '翻页', value: 'numbered' },
|
||||
{ label: '加载更多', value: 'load_more' },
|
||||
{ label: '无限滚动', value: 'infinite' },
|
||||
]},
|
||||
{ key: 'comment_paging_ajax_ias_s', label: '评论自动加载', type: 'switch', default: true, help: '评论无限滚动时自动触发加载' },
|
||||
{ key: 'comment_paging_ajax_ias_max', label: '评论最大加载页数', type: 'number', default: 3, min: 0, max: 10, help: '0 = 不限' },
|
||||
{ key: 'comment_nested_depth', label: '回复嵌套深度', type: 'number', default: 3, min: 1, max: 10 },
|
||||
{ key: 'comment_avatar_size', label: '头像大小 (px)', type: 'number', default: 48, min: 24, max: 96 },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'permissions',
|
||||
title: '评论设置',
|
||||
icon: 'fa fas fa-lock',
|
||||
fields: [
|
||||
{ key: 'comment_close_comments', label: '关闭评论', type: 'switch', default: false },
|
||||
{ key: 'comment_edit_window', label: '作者自助编辑时限 (分钟)', type: 'number', default: 10, min: 0, max: 1440 },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'toolbar',
|
||||
title: '评论工具栏',
|
||||
icon: 'fa fas fa-wrench',
|
||||
fields: [
|
||||
{ key: 'comment_code', label: '代码插入', type: 'switch', default: true },
|
||||
{ key: 'comment_img', label: '图片按钮', type: 'switch', default: true },
|
||||
{ key: 'comment_link', label: '链接按钮', type: 'switch', default: false },
|
||||
{ key: 'comment_upload_img', label: '评论图片上传', type: 'switch', default: false },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'interaction',
|
||||
title: '互动功能',
|
||||
icon: 'fa fas fa-heart',
|
||||
fields: [
|
||||
{ key: 'comment_hot_threshold', label: '神评点赞阈值', type: 'number', default: 10, min: 1, max: 999, help: '点赞数达到该值后显示「神评」徽章', dependsOn: { key: 'comment_like_s', value: true } },
|
||||
{ key: 'comment_like_s', label: '评论点赞', type: 'switch', default: true },
|
||||
{ key: 'comment_user_url_s', label: '匿名者网址', type: 'switch', default: false, help: '用户未登录评论时,允许输入用户博客地址' },
|
||||
{ key: 'comment_city_s', label: '评论城市', type: 'switch', default: true },
|
||||
{ key: 'comment_city_type', label: '城市显示格式', type: 'radio', default: 'province_city', options: [
|
||||
{ label: '省份+城市', value: 'province_city' },
|
||||
{ label: '仅省份', value: 'province' },
|
||||
{ label: '国家+省份', value: 'country_province' },
|
||||
], dependsOn: { key: 'comment_city_s', value: true } },
|
||||
{ key: 'comment_author_tag', label: '作者标签', type: 'switch', default: true },
|
||||
{ key: 'comment_corderby', label: '评论排序切换', type: 'switch', default: true, help: '前台显示最新/最早/最热切换按钮' },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'text',
|
||||
title: '文案配置',
|
||||
icon: 'fa fas fa-font',
|
||||
fields: [
|
||||
{ key: 'comment_empty_text', label: '空评论提示', type: 'input', default: '暂无评论,来做第一个评论的人吧~' },
|
||||
{ key: 'comment_title', label: '评论区标题', type: 'input', default: '评论' },
|
||||
{ key: 'comment_submit_text', label: '提交按钮文案', type: 'input', default: '提交评论' },
|
||||
{ key: 'comment_text', label: '评论框提示', type: 'input', default: '欢迎您留下宝贵的见解!' },
|
||||
{
|
||||
key: 'comment_discussion_notice',
|
||||
label: '',
|
||||
type: 'content',
|
||||
ui_only: true,
|
||||
dependsOn: { key: 'close_comments', value: false },
|
||||
content: '<p style="margin:0;font-size:12px;color:var(--aksrt-color-muted);line-height:1.6;"><i class="fa fas fa-fw fa-info-circle"></i> WordPress默认关闭评论翻页功能,如需启用请按此进行设置:<br/>1. 进入WP讨论设置,勾选 <code>分页显示评论</code><br/>2. 设置默认显示 <code>最前</code>一页<br/>3. 设置在每个页面顶部显示 <code>旧的</code>评论<br/>4. 根据需要设置每一页显示数量<br/>5. 根据需要设置评论嵌套(推荐开启并设置为3层)<br/>6. wp默认开启免登陆评论,如需关闭则勾选<code>需要登录后才能发表评论</code><br/><a href="options-discussion.php">【去设置】</a></p>',
|
||||
},
|
||||
{ key: 'close_comments', label: '关闭文章评论功能', type: 'switch', default: false, description: '部分网站无需交互,或需备案审核,可在此关闭所有文章的评论功能。同时每一篇文章可单独关闭评论功能' },
|
||||
{
|
||||
key: 'comment_box_hide',
|
||||
label: '隐藏评论模块',
|
||||
type: 'radio',
|
||||
default: '',
|
||||
dependsOn: { key: 'close_comments', value: false },
|
||||
options: [
|
||||
{ label: '不隐藏', value: '' },
|
||||
{ label: '登录后显示', value: 'signin' },
|
||||
{ label: '所有会员显示', value: 'vip' },
|
||||
{ label: '二级会员显示', value: 'vip_2' },
|
||||
{ label: '认证用户显示', value: 'auth' },
|
||||
],
|
||||
description: '当用户满足条件时,文章评论功能及模块才会显示',
|
||||
},
|
||||
{
|
||||
key: 'comment_paginate_type',
|
||||
label: '评论列表翻页模式',
|
||||
type: 'radio',
|
||||
default: 'default',
|
||||
dependsOn: { key: 'close_comments', value: false },
|
||||
options: [
|
||||
{ label: 'AJAX追加列表翻页', value: 'ajax_lists' },
|
||||
{ label: '数字翻页按钮', value: 'default' },
|
||||
],
|
||||
},
|
||||
{ key: 'comment_paging_ajax_ias_s', label: 'AJAX翻页自动加载', type: 'switch', default: true, dependsOn: { key: 'comment_paginate_type', value: 'ajax_lists' }, description: '页面滚动到列表尽头时,自动加载下一页' },
|
||||
{ key: 'comment_paging_ajax_ias_max', label: '自动加载页数', type: 'number', default: 3, min: 0, max: 10, unit: '页', dependsOn: { all: [{ key: 'comment_paginate_type', value: 'ajax_lists' }, { key: 'comment_paging_ajax_ias_s', value: true }] }, description: 'AJAX翻页自动加载最多加载几页(为0则不限制,直到加载全部评论)' },
|
||||
{ key: 'comment_code', label: '允许插入代码', type: 'switch', default: true, dependsOn: { key: 'close_comments', value: false }, help: '为了防止恶意评论,建议在后台-设置-讨论:开启“用户必须登录后才能发表评论”' },
|
||||
{ key: 'comment_img', label: '允许插入图片', type: 'switch', default: true, dependsOn: { key: 'close_comments', value: false } },
|
||||
{ key: 'comment_upload_img', label: '允许上传图片', type: 'switch', default: false, dependsOn: { all: [{ key: 'close_comments', value: false }, { key: 'comment_img', value: true }] } },
|
||||
{ key: 'comment_link', label: '允许插入链接', type: 'switch', default: false },
|
||||
{ key: 'comment_author_tag', label: '显示“作者”标签', type: 'switch', default: true, dependsOn: { key: 'close_comments', value: false } },
|
||||
{ key: 'user_edit_comment', label: '允许用户编辑评论', type: 'switch', default: true, dependsOn: { key: 'close_comments', value: false } },
|
||||
{ key: 'comment_like_s', label: '评论点赞功能', type: 'switch', default: true, dependsOn: { key: 'close_comments', value: false } },
|
||||
{ key: 'comment_user_url_s', label: '匿名评论允许输入链接', type: 'switch', default: false, dependsOn: { key: 'close_comments', value: false }, description: '用户未登录评论时,允许输入用户博客地址' },
|
||||
{ key: 'comment_corderby', label: '评论排序功能', type: 'switch', default: true, dependsOn: { all: [{ key: 'close_comments', value: false }, { key: 'comment_like_s', value: true }] }, description: '显示“最新、最热”排序按钮' },
|
||||
{ key: 'comment_title', label: '自定义评论标题', type: 'textarea', default: '评论', rows: 1, dependsOn: { key: 'close_comments', value: false } },
|
||||
{ key: 'comment_submit_text', label: '自定义评论提交按钮文案', type: 'textarea', default: '提交评论', rows: 1, dependsOn: { key: 'close_comments', value: false } },
|
||||
{ key: 'comment_text', label: '自定义评论框占位符文案', type: 'input', default: '欢迎您留下宝贵的见解!', dependsOn: { key: 'close_comments', value: false } },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -63,6 +63,32 @@ add_filter('comments_template_query_args', static function ($args) {
|
||||
: $args;
|
||||
});
|
||||
|
||||
if (!function_exists('aksrt_comment_box_visible')) :
|
||||
/**
|
||||
* Whether the comment module may render for the current visitor.
|
||||
*
|
||||
* Mirrors the reference theme's comment_box_hide conditions.
|
||||
*/
|
||||
function aksrt_comment_box_visible(): bool {
|
||||
$settings = class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::get_comment_display_settings()
|
||||
: [];
|
||||
$hide = sanitize_key((string) ($settings['box_hide'] ?? ''));
|
||||
switch ($hide) {
|
||||
case 'signin':
|
||||
return is_user_logged_in();
|
||||
case 'vip':
|
||||
return function_exists('aksrt_is_vip') && aksrt_is_vip();
|
||||
case 'vip_2':
|
||||
return function_exists('aksrt_is_vip2') && aksrt_is_vip2();
|
||||
case 'auth':
|
||||
return function_exists('aksrt_current_user_is_verified') && aksrt_current_user_is_verified();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_comments_build_context')) :
|
||||
/**
|
||||
* Resolve comments runtime context once.
|
||||
@@ -116,6 +142,7 @@ if (!function_exists('aksrt_comments_build_context')) :
|
||||
'title_text' => (string) ($settings['title'] ?? __('评论', 'aksrt')),
|
||||
'corderby_enabled' => !empty($settings['corderby']),
|
||||
'close_comments' => !empty($settings['close_comments']),
|
||||
'box_hidden' => !aksrt_comment_box_visible(),
|
||||
'oauth_providers' => class_exists('\AKSRT\Auth\OAuth')
|
||||
? \AKSRT\Auth\OAuth::get_instance()->get_auth_providers_data()
|
||||
: [],
|
||||
@@ -646,7 +673,7 @@ if (!function_exists('aksrt_comments_render')) :
|
||||
}
|
||||
|
||||
$ctx = aksrt_comments_build_context();
|
||||
if (!empty($ctx['close_comments'])) {
|
||||
if (!empty($ctx['close_comments']) || !empty($ctx['box_hidden'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,26 @@ if (!function_exists('aksrt_get_user_identity_signals')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_current_user_is_verified')) {
|
||||
/**
|
||||
* Whether the current user carries a verification (认证) signal.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function aksrt_current_user_is_verified(): bool {
|
||||
$user_id = get_current_user_id();
|
||||
if ($user_id <= 0 || !function_exists('aksrt_get_user_identity_signals')) {
|
||||
return false;
|
||||
}
|
||||
foreach (aksrt_get_user_identity_signals($user_id) as $signal) {
|
||||
if ((string) ($signal['type'] ?? '') === 'verify') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_render_user_identity_chips')) {
|
||||
/**
|
||||
* Render compact identity chips (verify / level / badges).
|
||||
@@ -537,7 +557,8 @@ if (!function_exists('aksrt_get_worn_medal_icon')) {
|
||||
|
||||
if (!function_exists('aksrt_is_blog_comment_hot')) {
|
||||
/**
|
||||
* "神评" for ordinary post comments when likes cross threshold.
|
||||
* "神评" for ordinary post comments when likes cross the fixed threshold
|
||||
* (参考主题固定 10 赞,主题不再提供该阈值配置).
|
||||
*/
|
||||
function aksrt_is_blog_comment_hot($comment): bool {
|
||||
$comment_id = $comment instanceof WP_Comment ? (int) $comment->comment_ID : (int) $comment;
|
||||
@@ -548,16 +569,6 @@ if (!function_exists('aksrt_is_blog_comment_hot')) {
|
||||
return true;
|
||||
}
|
||||
$threshold = 10;
|
||||
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_comment_display_settings')) {
|
||||
$display = \AKSRT\Settings\Settings::get_comment_display_settings();
|
||||
if (isset($display['hot_threshold'])) {
|
||||
$threshold = max(1, (int) $display['hot_threshold']);
|
||||
}
|
||||
}
|
||||
$all = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
|
||||
if (isset($all['comment_hot_threshold'])) {
|
||||
$threshold = max(1, (int) $all['comment_hot_threshold']);
|
||||
}
|
||||
$likes = function_exists('aksrt_get_comment_likes') ? aksrt_get_comment_likes($comment_id) : (int) get_comment_meta($comment_id, 'aksrt_comment_likes', true);
|
||||
if ($likes < $threshold) {
|
||||
return false;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Gates:
|
||||
* master: ip_geo_enabled
|
||||
* surface: ip_geo_display ∈ {comment, user_home, user_center, post}
|
||||
* comments: comment_city_s (+ comment_city_type) via comments/geo.php
|
||||
* comments: display + format fully owned by this extension via comments/geo.php
|
||||
*
|
||||
* Meta:
|
||||
* comment → aksrt_comment_addr {country,province,city}
|
||||
|
||||
@@ -40,15 +40,14 @@ if (!function_exists('aksrt_comment_action_permissions')) :
|
||||
return false;
|
||||
};
|
||||
|
||||
$edit_window = 10;
|
||||
// 允许用户编辑评论:参考主题 user_edit_comment 总开关(关闭后本人亦不可编辑)。
|
||||
$user_edit = true;
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
$display = \AKSRT\Settings\Settings::get_comment_display_settings();
|
||||
$edit_window = (int) ($display['edit_window'] ?? 10);
|
||||
$user_edit = !isset($display['user_edit']) || !empty($display['user_edit']);
|
||||
}
|
||||
$within_window = $edit_window > 0
|
||||
&& (time() - strtotime((string) $comment->comment_date_gmt)) < ($edit_window * MINUTE_IN_SECONDS);
|
||||
|
||||
$can_edit_own = $is_owner && $within_window && $can('comment_edit');
|
||||
$can_edit_own = $is_owner && $user_edit && $can('comment_edit');
|
||||
$can_edit_others = (!$is_owner) && (
|
||||
($is_post_author && $can('comment_edit_my_post'))
|
||||
|| $can('comment_edit_other')
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Comment city / IP geo helpers.
|
||||
*
|
||||
* Meta: aksrt_comment_addr {country,province,city}
|
||||
* Gates: ip_geo_enabled + ip_geo_display has comment + comment_city_s
|
||||
* Gates: ip_geo_enabled + ip_geo_display has comment(扩展&增强 / IP归属地统一控制)
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -12,27 +12,14 @@ defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_comment_city_enabled')) :
|
||||
function aksrt_comment_city_enabled(): bool {
|
||||
if (function_exists('aksrt_ip_geo_display_enabled') && !aksrt_ip_geo_display_enabled('comment')) {
|
||||
return false;
|
||||
}
|
||||
if (!class_exists('\AKSRT\Settings\Settings')) {
|
||||
return false;
|
||||
}
|
||||
$s = \AKSRT\Settings\Settings::get_comment_display_settings();
|
||||
return !empty($s['city_s']);
|
||||
// 评论区位置显示的开关与精度统一由「扩展&增强 / IP归属地」配置提供。
|
||||
return function_exists('aksrt_ip_geo_display_enabled') && aksrt_ip_geo_display_enabled('comment');
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_comment_city_type')) :
|
||||
function aksrt_comment_city_type(): string {
|
||||
if (!class_exists('\AKSRT\Settings\Settings')) {
|
||||
return function_exists('aksrt_ip_geo_format_key') ? aksrt_ip_geo_format_key() : 'province_city';
|
||||
}
|
||||
$s = \AKSRT\Settings\Settings::get_comment_display_settings();
|
||||
$type = sanitize_key((string) ($s['city_type'] ?? 'province_city'));
|
||||
return in_array($type, ['province_city', 'province', 'country_province'], true)
|
||||
? $type
|
||||
: 'province_city';
|
||||
return function_exists('aksrt_ip_geo_format_key') ? aksrt_ip_geo_format_key() : 'province_city';
|
||||
}
|
||||
endif;
|
||||
|
||||
|
||||
@@ -136,7 +136,6 @@ class SchemaPostList {
|
||||
['key' => 'post_default_likes_min', 'label' => '默认点赞最小值', 'type' => 'number', 'default' => 5, 'min' => 0, 'max' => 9999],
|
||||
['key' => 'post_default_likes_max', 'label' => '默认点赞最大值', 'type' => 'number', 'default' => 15, 'min' => 1, 'max' => 9999],
|
||||
['key' => 'post_views_s', 'label' => '浏览统计', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'post_close_comments', 'label' => '关闭评论', 'type' => 'switch', 'default' => false],
|
||||
]],
|
||||
],
|
||||
],
|
||||
@@ -199,53 +198,36 @@ class SchemaPostList {
|
||||
'comment' => [
|
||||
'key' => 'comment',
|
||||
'title' => '评论设置',
|
||||
'version' => '1.0.0',
|
||||
'version' => '2.0.0',
|
||||
'option_key' => 'aksrt_settings',
|
||||
'groups' => [
|
||||
['key' => 'display', 'title' => '评论展示', 'fields' => [
|
||||
['key' => 'comment_order', 'label' => '评论排序', 'type' => 'radio', 'default' => 'asc', 'options' => [
|
||||
['label' => '正序', 'value' => 'asc'],
|
||||
['label' => '倒序', 'value' => 'desc'],
|
||||
['key' => 'comment', 'title' => '评论设置', 'fields' => [
|
||||
['key' => 'close_comments', 'label' => '关闭文章评论功能', 'type' => 'switcher', 'default' => false, 'description' => '部分网站无需交互,或需备案审核,可在此关闭所有文章的评论功能。同时每一篇文章可单独关闭评论功能'],
|
||||
['key' => 'comment_box_hide', 'label' => '隐藏评论模块', 'type' => 'radio', 'default' => '', 'dependsOn' => ['key' => 'close_comments', 'value' => false], 'options' => [
|
||||
['label' => '不隐藏', 'value' => ''],
|
||||
['label' => '登录后显示', 'value' => 'signin'],
|
||||
['label' => '所有会员显示', 'value' => 'vip'],
|
||||
['label' => '二级会员显示', 'value' => 'vip_2'],
|
||||
['label' => '认证用户显示', 'value' => 'auth'],
|
||||
], 'description' => '当用户满足条件时,文章评论功能及模块才会显示'],
|
||||
['key' => 'comment_paginate_type', 'label' => '评论列表翻页模式', 'type' => 'radio', 'default' => 'default', 'dependsOn' => ['key' => 'close_comments', 'value' => false], 'options' => [
|
||||
['label' => 'AJAX追加列表翻页', 'value' => 'ajax_lists'],
|
||||
['label' => '数字翻页按钮', 'value' => 'default'],
|
||||
]],
|
||||
['key' => 'comment_per_page', 'label' => '每页评论数', 'type' => 'number', 'default' => 20, 'min' => 5, 'max' => 100],
|
||||
['key' => 'comment_pagination_type', 'label' => '分页方式', 'type' => 'radio', 'default' => 'numbered', 'options' => [
|
||||
['label' => '翻页', 'value' => 'numbered'],
|
||||
['label' => '加载更多', 'value' => 'load_more'],
|
||||
['label' => '无限滚动', 'value' => 'infinite'],
|
||||
]],
|
||||
['key' => 'comment_paging_ajax_ias_s', 'label' => '评论自动加载', 'type' => 'switch', 'default' => true, 'description' => '评论无限滚动时自动触发加载'],
|
||||
['key' => 'comment_paging_ajax_ias_max', 'label' => '评论最大加载页数', 'type' => 'number', 'default' => 3, 'min' => 0, 'max' => 10, 'description' => '0=不限'],
|
||||
['key' => 'comment_nested_depth', 'label' => '回复嵌套深度', 'type' => 'number', 'default' => 3, 'min' => 1, 'max' => 10],
|
||||
['key' => 'comment_avatar_size', 'label' => '头像大小', 'type' => 'number', 'default' => 48, 'min' => 24, 'max' => 96],
|
||||
]],
|
||||
['key' => 'permissions', 'title' => '评论权限', 'fields' => [
|
||||
['key' => 'comment_close_comments', 'label' => '关闭评论', 'type' => 'switch', 'default' => false],
|
||||
['key' => 'comment_edit_window', 'label' => '作者自助编辑时限(分钟)', 'type' => 'number', 'default' => 10, 'min' => 0, 'max' => 1440],
|
||||
]],
|
||||
['key' => 'toolbar', 'title' => '评论工具栏', 'fields' => [
|
||||
['key' => 'comment_code', 'label' => '代码插入', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'comment_img', 'label' => '图片按钮', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'comment_upload_img', 'label' => '评论图片上传', 'type' => 'switch', 'default' => false],
|
||||
['key' => 'comment_link', 'label' => '链接按钮', 'type' => 'switch', 'default' => false],
|
||||
]],
|
||||
['key' => 'interaction', 'title' => '互动功能', 'fields' => [
|
||||
['key' => 'comment_hot_threshold', 'label' => '神评点赞阈值', 'type' => 'number', 'default' => 10, 'min' => 1, 'max' => 999],
|
||||
['key' => 'comment_like_s', 'label' => '评论点赞', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'comment_user_url_s', 'label' => '匿名者网址', 'type' => 'switch', 'default' => false, 'description' => '用户未登录评论时,允许输入用户博客地址'],
|
||||
['key' => 'comment_city_s', 'label' => '评论城市', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'comment_city_type', 'label' => '城市显示格式', 'type' => 'radio', 'default' => 'province_city', 'options' => [
|
||||
['label' => '省份+城市', 'value' => 'province_city'],
|
||||
['label' => '仅省份', 'value' => 'province'],
|
||||
['label' => '国家+省份', 'value' => 'country_province'],
|
||||
]],
|
||||
['key' => 'comment_author_tag', 'label' => '作者标签', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'comment_corderby', 'label' => '评论排序切换', 'type' => 'switch', 'default' => true, 'description' => '前台显示最新/最早/最热切换按钮'],
|
||||
]],
|
||||
['key' => 'text', 'title' => '文案配置', 'fields' => [
|
||||
['key' => 'comment_empty_text', 'label' => '空评论提示', 'type' => 'input', 'default' => '暂无评论,来做第一个评论的人吧~'],
|
||||
['key' => 'comment_title', 'label' => '评论区标题', 'type' => 'input', 'default' => '评论'],
|
||||
['key' => 'comment_submit_text', 'label' => '提交按钮文案', 'type' => 'input', 'default' => '提交评论'],
|
||||
['key' => 'comment_text', 'label' => '评论框提示', 'type' => 'input', 'default' => '说点什么吧...'],
|
||||
['key' => 'comment_paging_ajax_ias_s', 'label' => 'AJAX翻页自动加载', 'type' => 'switcher', 'default' => true, 'dependsOn' => ['key' => 'comment_paginate_type', 'value' => 'ajax_lists'], 'description' => '页面滚动到列表尽头时,自动加载下一页'],
|
||||
['key' => 'comment_paging_ajax_ias_max', 'label' => '自动加载页数', 'type' => 'number', 'default' => 3, 'min' => 0, 'max' => 10, 'unit' => '页', 'dependsOn' => ['all' => [['key' => 'comment_paginate_type', 'value' => 'ajax_lists'], ['key' => 'comment_paging_ajax_ias_s', 'value' => true]]], 'description' => 'AJAX翻页自动加载最多加载几页(为0则不限制,直到加载全部评论)'],
|
||||
['key' => 'comment_code', 'label' => '允许插入代码', 'type' => 'switcher', 'default' => true, 'dependsOn' => ['key' => 'close_comments', 'value' => false], 'help' => '为了防止恶意评论,建议在后台-设置-讨论:开启“用户必须登录后才能发表评论”'],
|
||||
['key' => 'comment_img', 'label' => '允许插入图片', 'type' => 'switcher', 'default' => true, 'dependsOn' => ['key' => 'close_comments', 'value' => false]],
|
||||
['key' => 'comment_upload_img', 'label' => '允许上传图片', 'type' => 'switcher', 'default' => false, 'dependsOn' => ['all' => [['key' => 'close_comments', 'value' => false], ['key' => 'comment_img', 'value' => true]]]],
|
||||
['key' => 'comment_link', 'label' => '允许插入链接', 'type' => 'switcher', 'default' => false],
|
||||
['key' => 'comment_author_tag', 'label' => '显示“作者”标签', 'type' => 'switcher', 'default' => true, 'dependsOn' => ['key' => 'close_comments', 'value' => false]],
|
||||
['key' => 'user_edit_comment', 'label' => '允许用户编辑评论', 'type' => 'switcher', 'default' => true, 'dependsOn' => ['key' => 'close_comments', 'value' => false]],
|
||||
['key' => 'comment_like_s', 'label' => '评论点赞功能', 'type' => 'switcher', 'default' => true, 'dependsOn' => ['key' => 'close_comments', 'value' => false]],
|
||||
['key' => 'comment_user_url_s', 'label' => '匿名评论允许输入链接', 'type' => 'switcher', 'default' => false, 'dependsOn' => ['key' => 'close_comments', 'value' => false], 'description' => '用户未登录评论时,允许输入用户博客地址'],
|
||||
['key' => 'comment_corderby', 'label' => '评论排序功能', 'type' => 'switcher', 'default' => true, 'dependsOn' => ['all' => [['key' => 'close_comments', 'value' => false], ['key' => 'comment_like_s', 'value' => true]]], 'description' => '显示“最新、最热”排序按钮'],
|
||||
['key' => 'comment_title', 'label' => '自定义评论标题', 'type' => 'textarea', 'default' => '评论', 'rows' => 1, 'dependsOn' => ['key' => 'close_comments', 'value' => false]],
|
||||
['key' => 'comment_submit_text', 'label' => '自定义评论提交按钮文案', 'type' => 'textarea', 'default' => '提交评论', 'rows' => 1, 'dependsOn' => ['key' => 'close_comments', 'value' => false]],
|
||||
['key' => 'comment_text', 'label' => '自定义评论框占位符文案', 'type' => 'input', 'default' => '欢迎您留下宝贵的见解!', 'dependsOn' => ['key' => 'close_comments', 'value' => false]],
|
||||
]],
|
||||
],
|
||||
],
|
||||
|
||||
@@ -163,7 +163,7 @@ class CommentActions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission: can edit? (author within configured window, or moderator)
|
||||
* Permission: can edit? (author with 允许用户编辑评论 on, or moderator)
|
||||
*/
|
||||
public function check_edit_permission(\WP_REST_Request $request): bool {
|
||||
if (!is_user_logged_in()) return false;
|
||||
|
||||
@@ -339,12 +339,13 @@ class PostDisplay {
|
||||
|
||||
public static function get_comment_display_settings(): array {
|
||||
$settings = Settings::get_all();
|
||||
$order = sanitize_key((string) ($settings['comment_order'] ?? 'desc'));
|
||||
|
||||
// 评论排序由 WP 讨论设置决定(与参考主题一致:主题不再提供排序配置)。
|
||||
$order = sanitize_key((string) get_option('comment_order', 'desc'));
|
||||
if (!in_array($order, ['asc', 'desc'], true)) {
|
||||
$order = 'desc';
|
||||
}
|
||||
|
||||
$empty_text = trim((string) ($settings['comment_empty_text'] ?? ''));
|
||||
$submit_text = trim((string) ($settings['comment_submit_text'] ?? ''));
|
||||
$box_placeholder = trim((string) ($settings['comment_text'] ?? ''));
|
||||
$title = trim((string) ($settings['comment_title'] ?? ''));
|
||||
@@ -354,11 +355,8 @@ class PostDisplay {
|
||||
'pagination_mode' => self::get_comment_pagination_mode(),
|
||||
'paging_ajax_ias' => !isset($settings['comment_paging_ajax_ias_s']) || !empty($settings['comment_paging_ajax_ias_s']),
|
||||
'paging_ajax_ias_max'=> max(0, min(10, (int) ($settings['comment_paging_ajax_ias_max'] ?? 3))),
|
||||
'per_page' => max(5, min(100, (int) ($settings['comment_per_page'] ?? 20))),
|
||||
'nested_depth' => max(1, min(10, (int) ($settings['comment_nested_depth'] ?? 3))),
|
||||
'require_login' => Settings::comment_requires_registration(),
|
||||
'avatar_size' => max(24, min(96, (int) ($settings['comment_avatar_size'] ?? 48))),
|
||||
'empty_text' => $empty_text !== '' ? $empty_text : __('暂无评论,来做第一个评论的人吧~', 'aksrt'),
|
||||
'box_hide' => sanitize_key((string) ($settings['comment_box_hide'] ?? '')),
|
||||
'toolbar' => [
|
||||
'code' => !isset($settings['comment_code']) || !empty($settings['comment_code']),
|
||||
'image' => !isset($settings['comment_img']) || !empty($settings['comment_img']),
|
||||
@@ -372,34 +370,15 @@ class PostDisplay {
|
||||
'like_enabled' => !isset($settings['comment_like_s']) || !empty($settings['comment_like_s']),
|
||||
'author_tag' => !isset($settings['comment_author_tag']) || !empty($settings['comment_author_tag']),
|
||||
'corderby' => !isset($settings['comment_corderby']) || !empty($settings['comment_corderby']),
|
||||
'edit_window' => max(0, min(1440, (int) ($settings['comment_edit_window'] ?? 10))),
|
||||
'user_edit' => !isset($settings['user_edit_comment']) || !empty($settings['user_edit_comment']),
|
||||
'submit_text' => $submit_text !== '' ? $submit_text : __('提交评论', 'aksrt'),
|
||||
'box_placeholder' => $box_placeholder !== '' ? $box_placeholder : __('说点什么吧...', 'aksrt'),
|
||||
'title' => $title !== '' ? $title : __('评论', 'aksrt'),
|
||||
// Extended legacy-parity settings.
|
||||
'close_comments' => !empty($settings['comment_close_comments']),
|
||||
'hot_threshold' => max(1, min(999, (int) ($settings['comment_hot_threshold'] ?? 10))),
|
||||
'close_comments' => !empty($settings['close_comments']),
|
||||
'user_url' => !empty($settings['comment_user_url_s']),
|
||||
'city_s' => !isset($settings['comment_city_s']) || !empty($settings['comment_city_s']),
|
||||
'city_type' => self::normalize_comment_city_type((string) ($settings['comment_city_type'] ?? 'province_city')),
|
||||
];
|
||||
}
|
||||
|
||||
private static function normalize_comment_city_type(string $type): string {
|
||||
$type = sanitize_key($type);
|
||||
// Map legacy legacy pro/city labels.
|
||||
if ($type === 'pro') {
|
||||
return 'province';
|
||||
}
|
||||
if ($type === 'city') {
|
||||
return 'province_city';
|
||||
}
|
||||
return in_array($type, ['province_city', 'province', 'country_province'], true)
|
||||
? $type
|
||||
: 'province_city';
|
||||
}
|
||||
|
||||
|
||||
public static function apply_list_orderby($query): void {
|
||||
if (is_admin() || !($query instanceof \WP_Query) || !$query->is_main_query()) {
|
||||
return;
|
||||
@@ -467,11 +446,9 @@ class PostDisplay {
|
||||
}
|
||||
|
||||
public static function get_comment_pagination_mode(): string {
|
||||
$mode = (string) Settings::get_value('comment_pagination_type', 'numbered');
|
||||
if ($mode === 'page') {
|
||||
$mode = 'numbered';
|
||||
}
|
||||
return in_array($mode, ['numbered', 'load_more', 'infinite'], true) ? $mode : 'numbered';
|
||||
// 与参考主题一致:ajax_lists = AJAX 追加列表翻页,其余为数字翻页按钮。
|
||||
$mode = (string) Settings::get_value('comment_paginate_type', 'default');
|
||||
return $mode === 'ajax_lists' ? 'ajax_lists' : 'numbered';
|
||||
}
|
||||
|
||||
private static function sanitize_custom_filter_defs($raw): array {
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* 「评论设置」后台设置页契约(对齐参考主题 1:1):
|
||||
* 1) PHP schema(SchemaPostList.php comment section)字段键、顺序、默认值与
|
||||
* JS schema(assets/admin/src/schema/sections/post-list/comment.js)一致;
|
||||
* 2) 参考主题字段全集存在:close_comments / comment_box_hide /
|
||||
* comment_paginate_type / comment_paging_ajax_ias_s /
|
||||
* comment_paging_ajax_ias_max / comment_code / comment_img /
|
||||
* comment_upload_img / comment_link / comment_author_tag /
|
||||
* user_edit_comment / comment_like_s / comment_user_url_s /
|
||||
* comment_corderby / comment_title / comment_submit_text / comment_text;
|
||||
* 3) 插入表情(comment_smilie)、评论地理位置(comment_city_s/comment_city_type,
|
||||
* 由扩展&增强/IP归属地实现)不在本页;
|
||||
* 4) 快捷回复按评论区硬切换契约保持移除(comment_quick_* 不存在);
|
||||
* 5) 旧 AKSRT 私有字段(comment_order / comment_per_page / comment_pagination_type /
|
||||
* comment_nested_depth / comment_avatar_size / comment_close_comments /
|
||||
* comment_edit_window / comment_hot_threshold / comment_empty_text /
|
||||
* post_close_comments)已彻底移除,无双路兼容;
|
||||
* 6) 运行时(PostDisplay::get_comment_display_settings)只读取新键。
|
||||
*/
|
||||
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const test = require('node:test');
|
||||
|
||||
const root = path.resolve(__dirname, '..', '..');
|
||||
const php = fs.readFileSync(path.join(root, 'src/Admin/Schema/SchemaPostList.php'), 'utf8');
|
||||
const js = fs.readFileSync(path.join(root, 'assets/admin/src/schema/sections/post-list/comment.js'), 'utf8');
|
||||
const runtime = fs.readFileSync(path.join(root, 'src/Settings/PostDisplay.php'), 'utf8');
|
||||
const commentsHelper = fs.readFileSync(path.join(root, 'inc/helpers/aksrt-comments.php'), 'utf8');
|
||||
const geoHelper = fs.readFileSync(path.join(root, 'inc/helpers/comments/geo.php'), 'utf8');
|
||||
const actionsHelper = fs.readFileSync(path.join(root, 'inc/helpers/comments/actions.php'), 'utf8');
|
||||
|
||||
const REFERENCE_KEYS = [
|
||||
'close_comments',
|
||||
'comment_box_hide',
|
||||
'comment_paginate_type',
|
||||
'comment_paging_ajax_ias_s',
|
||||
'comment_paging_ajax_ias_max',
|
||||
'comment_code',
|
||||
'comment_img',
|
||||
'comment_upload_img',
|
||||
'comment_link',
|
||||
'comment_author_tag',
|
||||
'user_edit_comment',
|
||||
'comment_like_s',
|
||||
'comment_user_url_s',
|
||||
'comment_corderby',
|
||||
'comment_title',
|
||||
'comment_submit_text',
|
||||
'comment_text',
|
||||
];
|
||||
|
||||
// 参考主题明确不做 / 本项目不做 / 其他地方实现的字段。
|
||||
const EXCLUDED_KEYS = [
|
||||
'comment_smilie',
|
||||
'comment_city_s',
|
||||
'comment_city_type',
|
||||
'comment_quick_s',
|
||||
'comment_quick_often',
|
||||
];
|
||||
|
||||
// 旧 AKSRT 私有字段(含已并入 WP 讨论设置与死字段 post_close_comments)。
|
||||
const LEGACY_KEYS = [
|
||||
'comment_order',
|
||||
'comment_per_page',
|
||||
'comment_pagination_type',
|
||||
'comment_nested_depth',
|
||||
'comment_avatar_size',
|
||||
'comment_close_comments',
|
||||
'comment_edit_window',
|
||||
'comment_hot_threshold',
|
||||
'comment_empty_text',
|
||||
'post_close_comments',
|
||||
];
|
||||
|
||||
/** Extract the PHP 'comment' => [ ... ] section body (balanced brackets). */
|
||||
function phpCommentSection(src) {
|
||||
const start = src.indexOf("'comment' => [");
|
||||
assert.notEqual(start, -1, 'PHP schema has a comment section');
|
||||
const open = src.indexOf('[', start);
|
||||
let depth = 0;
|
||||
for (let i = open; i < src.length; i++) {
|
||||
const ch = src[i];
|
||||
if (ch === "'" || ch === '"') {
|
||||
const quote = ch;
|
||||
i++;
|
||||
while (i < src.length) {
|
||||
if (src[i] === '\\') { i += 2; continue; }
|
||||
if (src[i] === quote) break;
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (ch === '[') depth++;
|
||||
else if (ch === ']') {
|
||||
depth--;
|
||||
if (depth === 0) return src.slice(open, i + 1);
|
||||
}
|
||||
}
|
||||
throw new Error('unbalanced comment section');
|
||||
}
|
||||
|
||||
const commentPhp = phpCommentSection(php);
|
||||
|
||||
test('PHP comment section 字段键与参考主题一致且顺序相同', () => {
|
||||
// 字段定义均为 ['key' => '...', 'label' => ...] 开头;dependsOn 内的
|
||||
// ['key' => '...', 'value' => ...] 不是字段定义,须排除。
|
||||
const found = [];
|
||||
const re = /'key'\s*=>\s*'([a-z0-9_]+)',\s*'label'/g;
|
||||
let m;
|
||||
while ((m = re.exec(commentPhp)) !== null) found.push(m[1]);
|
||||
assert.deepEqual(found, REFERENCE_KEYS);
|
||||
});
|
||||
|
||||
test('PHP comment section 不含表情/地理位置/快捷回复字段', () => {
|
||||
for (const key of EXCLUDED_KEYS) {
|
||||
assert.doesNotMatch(commentPhp, new RegExp(`'${key}'`), `comment section 不应包含 ${key}`);
|
||||
}
|
||||
});
|
||||
|
||||
test('PHP comment section 默认值对齐参考主题', () => {
|
||||
assert.match(commentPhp, /'close_comments',\s*'label'\s*=>\s*'关闭文章评论功能',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*false/);
|
||||
assert.match(commentPhp, /'comment_box_hide',\s*'label'\s*=>\s*'隐藏评论模块',\s*'type'\s*=>\s*'radio',\s*'default'\s*=>\s*''/);
|
||||
assert.match(commentPhp, /'comment_paginate_type',\s*'label'\s*=>\s*'评论列表翻页模式',\s*'type'\s*=>\s*'radio',\s*'default'\s*=>\s*'default'/);
|
||||
assert.match(commentPhp, /'comment_paging_ajax_ias_s',\s*'label'\s*=>\s*'AJAX翻页自动加载',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
assert.match(commentPhp, /'comment_paging_ajax_ias_max',\s*'label'\s*=>\s*'自动加载页数',\s*'type'\s*=>\s*'number',\s*'default'\s*=>\s*3/);
|
||||
assert.match(commentPhp, /'comment_code',\s*'label'\s*=>\s*'允许插入代码',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
assert.match(commentPhp, /'comment_img',\s*'label'\s*=>\s*'允许插入图片',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
assert.match(commentPhp, /'comment_upload_img',\s*'label'\s*=>\s*'允许上传图片',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*false/);
|
||||
assert.match(commentPhp, /'comment_link',\s*'label'\s*=>\s*'允许插入链接',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*false/);
|
||||
assert.match(commentPhp, /'comment_author_tag',\s*'label'\s*=>\s*'显示“作者”标签',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
assert.match(commentPhp, /'user_edit_comment',\s*'label'\s*=>\s*'允许用户编辑评论',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
assert.match(commentPhp, /'comment_like_s',\s*'label'\s*=>\s*'评论点赞功能',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
assert.match(commentPhp, /'comment_user_url_s',\s*'label'\s*=>\s*'匿名评论允许输入链接',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*false/);
|
||||
assert.match(commentPhp, /'comment_corderby',\s*'label'\s*=>\s*'评论排序功能',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
|
||||
assert.match(commentPhp, /'comment_title',\s*'label'\s*=>\s*'自定义评论标题',\s*'type'\s*=>\s*'textarea',\s*'default'\s*=>\s*'评论'/);
|
||||
assert.match(commentPhp, /'comment_submit_text',\s*'label'\s*=>\s*'自定义评论提交按钮文案',\s*'type'\s*=>\s*'textarea',\s*'default'\s*=>\s*'提交评论'/);
|
||||
assert.match(commentPhp, /'comment_text',\s*'label'\s*=>\s*'自定义评论框占位符文案',\s*'type'\s*=>\s*'input',\s*'default'\s*=>\s*'欢迎您留下宝贵的见解!'/);
|
||||
});
|
||||
|
||||
test('PHP comment section 选项与依赖对齐参考主题', () => {
|
||||
// 隐藏评论模块选项。
|
||||
for (const option of ['不隐藏', '登录后显示', '所有会员显示', '二级会员显示', '认证用户显示']) {
|
||||
assert.ok(commentPhp.includes(`'${option}'`), `comment_box_hide 缺少选项 ${option}`);
|
||||
}
|
||||
// 翻页模式选项。
|
||||
for (const option of ['AJAX追加列表翻页', '数字翻页按钮']) {
|
||||
assert.ok(commentPhp.includes(`'${option}'`), `comment_paginate_type 缺少选项 ${option}`);
|
||||
}
|
||||
assert.match(commentPhp, /'comment_box_hide'[\s\S]*?'dependsOn'\s*=>\s*\['key'\s*=>\s*'close_comments',\s*'value'\s*=>\s*false\]/);
|
||||
assert.match(commentPhp, /'comment_paginate_type'[\s\S]*?'dependsOn'\s*=>\s*\['key'\s*=>\s*'close_comments',\s*'value'\s*=>\s*false\]/);
|
||||
assert.match(commentPhp, /'comment_paging_ajax_ias_s'[\s\S]*?'dependsOn'\s*=>\s*\['key'\s*=>\s*'comment_paginate_type',\s*'value'\s*=>\s*'ajax_lists'\]/);
|
||||
assert.match(commentPhp, /'comment_paging_ajax_ias_max'[\s\S]*?'dependsOn'\s*=>\s*\['all'/);
|
||||
assert.match(commentPhp, /'comment_upload_img'[\s\S]*?'dependsOn'\s*=>\s*\['all'/);
|
||||
assert.match(commentPhp, /'comment_corderby'[\s\S]*?'dependsOn'\s*=>\s*\['all'/);
|
||||
// 允许插入链接在参考主题中没有依赖(其后紧跟 comment_author_tag)。
|
||||
const linkIdx = commentPhp.indexOf("'comment_link'");
|
||||
const authorTagIdx = commentPhp.indexOf("'comment_author_tag'");
|
||||
assert.ok(linkIdx !== -1 && authorTagIdx > linkIdx, 'comment_link / comment_author_tag 顺序应符合参考主题');
|
||||
const linkSlice = commentPhp.slice(linkIdx, authorTagIdx);
|
||||
assert.ok(!linkSlice.includes('dependsOn'), 'comment_link 不应有 dependsOn');
|
||||
});
|
||||
|
||||
test('JS schema 与 PHP 字段键一致(ui_only 提示行除外)', () => {
|
||||
// 字段定义为 { key: '...', label: ... };dependsOn 内的 { key, value } 须排除。
|
||||
const keys = [];
|
||||
const re = /key:\s*'([a-z0-9_]+)',\s*label:/g;
|
||||
let m;
|
||||
while ((m = re.exec(js)) !== null) keys.push(m[1]);
|
||||
const persisted = keys.filter((k) => REFERENCE_KEYS.includes(k));
|
||||
assert.deepEqual(persisted, REFERENCE_KEYS);
|
||||
for (const legacy of LEGACY_KEYS) {
|
||||
assert.ok(!keys.includes(legacy), `JS schema 残留旧字段: ${legacy}`);
|
||||
}
|
||||
for (const excluded of EXCLUDED_KEYS) {
|
||||
assert.ok(!keys.includes(excluded), `JS schema 不应包含 ${excluded}`);
|
||||
}
|
||||
// WP 讨论设置指引行承载参考主题 submessage 与【去设置】链接。
|
||||
assert.match(js, /ui_only:\s*true/);
|
||||
assert.match(js, /options-discussion\.php/);
|
||||
assert.match(js, /分页显示评论/);
|
||||
});
|
||||
|
||||
test('JS schema 默认值与选项对齐参考主题', () => {
|
||||
assert.match(js, /close_comments:\s*false/);
|
||||
assert.match(js, /comment_box_hide:\s*''/);
|
||||
assert.match(js, /comment_paginate_type:\s*'default'/);
|
||||
assert.match(js, /comment_paging_ajax_ias_s:\s*true/);
|
||||
assert.match(js, /comment_paging_ajax_ias_max:\s*3/);
|
||||
assert.match(js, /user_edit_comment:\s*true/);
|
||||
assert.match(js, /comment_text:\s*'欢迎您留下宝贵的见解!'/);
|
||||
for (const option of ['AJAX追加列表翻页', '数字翻页按钮', '登录后显示', '所有会员显示', '二级会员显示', '认证用户显示']) {
|
||||
assert.ok(js.includes(option), `JS schema 缺少选项 ${option}`);
|
||||
}
|
||||
assert.match(js, /dependsOn:\s*\{\s*key:\s*'close_comments',\s*value:\s*false\s*\}/);
|
||||
assert.match(js, /dependsOn:\s*\{\s*key:\s*'comment_paginate_type',\s*value:\s*'ajax_lists'\s*\}/);
|
||||
});
|
||||
|
||||
test('旧字段在 schema 与运行时中均已移除(无双路)', () => {
|
||||
for (const legacy of LEGACY_KEYS) {
|
||||
assert.ok(!php.includes(legacy), `PHP schema 残留旧字段: ${legacy}`);
|
||||
// 运行时按主题设置读取的形态 $settings['<legacy>'] 必须消失
|
||||
// (comment_order 允许以 WP 讨论选项 get_option('comment_order') 形态存在)。
|
||||
for (const source of [['PostDisplay', runtime], ['aksrt-comments.php', commentsHelper], ['comments/geo.php', geoHelper], ['comments/actions.php', actionsHelper]]) {
|
||||
assert.ok(!source[1].includes(`$settings['${legacy}']`), `${source[0]} 残留旧字段读取: ${legacy}`);
|
||||
}
|
||||
}
|
||||
// 运行时只读取新键。
|
||||
assert.match(runtime, /\$settings\['close_comments'\]/);
|
||||
assert.match(runtime, /\$settings\['user_edit_comment'\]/);
|
||||
assert.match(runtime, /\$settings\['comment_box_hide'\]/);
|
||||
assert.match(runtime, /Settings::get_value\('comment_paginate_type'/);
|
||||
assert.match(runtime, /return \$mode === 'ajax_lists' \? 'ajax_lists' : 'numbered';/);
|
||||
// 排序回退到 WP 讨论设置(参考主题行为)。
|
||||
assert.match(runtime, /get_option\('comment_order', 'desc'\)/);
|
||||
// 评论区位置显示交由扩展 IP 归属地控制。
|
||||
assert.match(geoHelper, /aksrt_ip_geo_display_enabled\('comment'\)/);
|
||||
assert.match(geoHelper, /aksrt_ip_geo_format_key/);
|
||||
// 编辑权限使用 user_edit 总开关。
|
||||
assert.match(actionsHelper, /\$display\['user_edit'\]/);
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated_at": "2026-09-24T04:13:34+00:00",
|
||||
"generated_at": "2026-09-24T05:35:38+00:00",
|
||||
"errors": [],
|
||||
"warnings": [
|
||||
"customPage tools-update section 'tools/update' not in PHP schema (ok if pure operational page)",
|
||||
@@ -8,9 +8,6 @@
|
||||
"enum incomplete parse for 'avatar_external' (php subset of js): php=[] js=[,gravatar,weavatar,cravatar,geekzu,loli,sep,v2ex]",
|
||||
"enum incomplete parse for 'backup_frequency' (php subset of js): php=[daily] js=[daily,weekly,monthly]",
|
||||
"enum incomplete parse for 'bind_reminder' (php subset of js): php=[email] js=[email,phone,email_phone,close]",
|
||||
"enum incomplete parse for 'comment_city_type' (php subset of js): php=[province_city] js=[province_city,province,country_province]",
|
||||
"enum incomplete parse for 'comment_order' (php subset of js): php=[asc] js=[asc,desc]",
|
||||
"enum incomplete parse for 'comment_pagination_type' (php subset of js): php=[numbered] js=[numbered,load_more,infinite]",
|
||||
"enum incomplete parse for 'content_audit_on_failure' (php subset of js): php=[allow] js=[allow,block]",
|
||||
"enum incomplete parse for 'content_audit_provider' (php subset of js): php=[baidu] js=[baidu,null]",
|
||||
"enum incomplete parse for 'epay_device' (php subset of js): php=[auto] js=[auto,pc,mobile]",
|
||||
@@ -237,7 +234,7 @@
|
||||
"entry": true,
|
||||
"missing_chunks": [],
|
||||
"chunks": [
|
||||
"SchemaPage.C2bnpARq.js",
|
||||
"SchemaPage.CPZNRYWC.js",
|
||||
"vendor-vue.BYzo-2I-.js",
|
||||
"FaIcon.B3OOcphx.js",
|
||||
"FaIconPicker.DHrC0Y72.js",
|
||||
@@ -252,8 +249,8 @@
|
||||
"vendor-draggable.YNevSrwY.js",
|
||||
"PageHeader.jmNZVzHG.js",
|
||||
"FooterTabbarSettings.CwSsjNlJ.js",
|
||||
"PostPageSettings.DZzG8fRg.js",
|
||||
"CommentSettings.sUF8U6J1.js",
|
||||
"PostPageSettings.DxiP1RzY.js",
|
||||
"CommentSettings.C6xJZ_dU.js",
|
||||
"PermissionsCapabilities.BeLUij9c.js",
|
||||
"CmsCredits.CTDJTkG-.js",
|
||||
"ThemeInfoPage.CbJKzVFa.js",
|
||||
|
||||
Reference in New Issue
Block a user