Files
wordpress-theme-aksrt/inc/helpers/aksrt-comments.php
T
kate522 ab70a5eae9 refactor(admin): consolidate duplicate configuration
Remove duplicate comment, captcha, filing, and website-security configuration paths.

Move front submission verification to the captcha scene matrix and retire obsolete admin routes and components.
2026-08-13 02:26:17 +08:00

725 lines
28 KiB
PHP

<?php
/**
* Unified comments composition (Zibll-style closed surface).
*
* comments.php stays a thin mount point. Policy + sections live here.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_comments_template_query_args')) :
/**
* Apply order / author-only filters to the comments template query.
*
* @param array<string,mixed> $args Comment query args.
* @return array<string,mixed>
*/
function aksrt_comments_template_query_args(array $args): array {
$order = isset($_GET['aksrt_comment_order'])
? sanitize_key((string) wp_unslash($_GET['aksrt_comment_order']))
: '';
if ($order === '') {
$settings = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_comment_display_settings()
: [];
$order = (($settings['order'] ?? 'desc') === 'asc') ? 'oldest' : 'newest';
}
if (!in_array($order, ['newest', 'oldest', 'hottest'], true)) {
$order = 'newest';
}
if ($order === 'oldest') {
$args['order'] = 'ASC';
$args['orderby'] = 'comment_date_gmt';
} else {
// newest + hottest: base DESC; hottest reorders via comments_clauses.
$args['order'] = 'DESC';
$args['orderby'] = 'comment_date_gmt';
}
if (isset($_GET['aksrt_author_only']) && (int) wp_unslash($_GET['aksrt_author_only']) === 1) {
$post_id = (int) get_queried_object_id();
if ($post_id <= 0 && !empty($args['post_id'])) {
$post_id = (int) $args['post_id'];
}
$author_id = $post_id > 0 ? (int) get_post_field('post_author', $post_id) : 0;
if ($author_id > 0) {
$args['user_id'] = $author_id;
}
}
return $args;
}
endif;
add_filter('comments_template_query_args', static function ($args) {
if (!is_array($args)) {
$args = [];
}
return function_exists('aksrt_comments_template_query_args')
? aksrt_comments_template_query_args($args)
: $args;
});
if (!function_exists('aksrt_comments_build_context')) :
/**
* Resolve comments runtime context once.
*
* @return array<string,mixed>
*/
function aksrt_comments_build_context(): array {
$settings = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_comment_display_settings()
: [
'order' => 'desc',
'nested_depth' => 3,
'require_login' => false,
'avatar_size' => 48,
'empty_text' => __('暂无评论,来做第一个评论的人吧~', 'aksrt'),
];
$default_order = (($settings['order'] ?? 'desc') === 'asc') ? 'oldest' : 'newest';
$order = isset($_GET['aksrt_comment_order'])
? sanitize_key((string) wp_unslash($_GET['aksrt_comment_order']))
: $default_order;
if (!in_array($order, ['newest', 'oldest', 'hottest'], true)) {
$order = 'newest';
}
$avatar_size = max(24, (int) ($settings['avatar_size'] ?? 48));
$toolbar = is_array($settings['toolbar'] ?? null)
? $settings['toolbar']
: ['smilie' => true, 'code' => true, 'image' => true];
$phrases = is_array($settings['quick_phrases'] ?? null) ? $settings['quick_phrases'] : [];
return [
'settings' => $settings,
'comment_count' => (int) get_comments_number(),
'is_logged_in' => is_user_logged_in(),
'current_user' => wp_get_current_user(),
'require_login' => !empty($settings['require_login']),
'order' => $order,
'reverse_comments' => $order === 'newest',
'is_hottest' => $order === 'hottest',
'author_only' => isset($_GET['aksrt_author_only']) && (int) $_GET['aksrt_author_only'] === 1,
'post_author_id' => (int) get_the_author_meta('ID'),
'avatar_size' => $avatar_size,
'max_depth' => max(1, (int) ($settings['nested_depth'] ?? 3)),
'empty_text' => (string) ($settings['empty_text'] ?? __('暂无评论,来做第一个评论的人吧~', 'aksrt')),
'toolbar' => $toolbar,
'upload_enabled' => !empty($toolbar['upload_img']),
'box_placeholder' => (string) ($settings['box_placeholder'] ?? __('说点什么吧...', 'aksrt')),
'submit_text' => (string) ($settings['submit_text'] ?? __('提交评论', 'aksrt')),
'title_text' => (string) ($settings['title'] ?? __('评论', 'aksrt')),
'corderby_enabled' => !empty($settings['corderby']),
'close_comments' => !empty($settings['close_comments']),
'quick_s' => !isset($settings['quick_s']) || !empty($settings['quick_s']),
'quick_phrases' => $phrases,
'oauth_providers' => class_exists('\AKSRT\Auth\OAuth')
? \AKSRT\Auth\OAuth::get_instance()->get_auth_providers_data()
: [],
];
}
endif;
if (!function_exists('aksrt_comments_apply_hottest_order')) :
/**
* Apply hottest-order SQL once for the current comments query.
*/
function aksrt_comments_apply_hottest_order(): void {
static $applied = false;
if ($applied) {
return;
}
$applied = true;
add_filter('comments_clauses', static function ($clauses) {
global $wpdb;
$clauses['join'] .= " LEFT JOIN {$wpdb->commentmeta} AS aksrt_cm ON ({$wpdb->comments}.comment_ID = aksrt_cm.comment_id AND aksrt_cm.meta_key = 'aksrt_comment_likes')";
$clauses['orderby'] = 'CAST(aksrt_cm.meta_value AS UNSIGNED) DESC, ' . $clauses['orderby'];
return $clauses;
});
}
endif;
if (!function_exists('aksrt_comments_normalize_order')) :
/**
* Normalize comment order key.
*/
function aksrt_comments_normalize_order(string $order = ''): string {
$order = sanitize_key($order);
if (!in_array($order, ['newest', 'oldest', 'hottest'], true)) {
$settings = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_comment_display_settings()
: [];
$order = (($settings['order'] ?? 'desc') === 'asc') ? 'oldest' : 'newest';
}
if (!in_array($order, ['newest', 'oldest', 'hottest'], true)) {
$order = 'newest';
}
return $order;
}
endif;
if (!function_exists('aksrt_comments_query_for_post')) :
/**
* Shared comment query for first paint / fragment / load-more.
*
* @return array{comments:array<int,\WP_Comment>,total:int,max_pages:int,page:int,order:string,author_only:bool,settings:array}
*/
function aksrt_comments_query_for_post(int $post_id, array $args = []): array {
$settings = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_comment_display_settings()
: [];
$order = aksrt_comments_normalize_order((string) ($args['order'] ?? ''));
$author_only = !empty($args['author_only']);
$page = max(1, (int) ($args['page'] ?? 1));
$per_page = max(1, (int) ($args['per_page'] ?? get_option('comments_per_page', 10)));
$include_unapproved_for_user = (int) ($args['include_unapproved_user'] ?? 0);
$query_args = [
'post_id' => $post_id,
'status' => 'approve',
'number' => $per_page,
'offset' => ($page - 1) * $per_page,
'orderby' => 'comment_date_gmt',
'order' => $order === 'oldest' ? 'ASC' : 'DESC',
'hierarchical' => 'threaded',
];
if ($author_only) {
$author_id = (int) get_post_field('post_author', $post_id);
if ($author_id > 0) {
$query_args['user_id'] = $author_id;
$query_args['hierarchical'] = false;
}
}
if ($include_unapproved_for_user > 0) {
// WP_Comment_Query does not support mixed status easily; keep approve only for list fragment.
}
// Hottest uses meta_value_num when meta exists; fall back to date.
$hottest_filter = null;
if ($order === 'hottest') {
$query_args['orderby'] = 'meta_value_num';
$query_args['meta_key'] = 'aksrt_comment_likes';
$query_args['order'] = 'DESC';
// Ensure comments without like meta still appear.
$query_args['meta_query'] = [
'relation' => 'OR',
[
'key' => 'aksrt_comment_likes',
'compare' => 'EXISTS',
],
[
'key' => 'aksrt_comment_likes',
'compare' => 'NOT EXISTS',
],
];
// Prefer clauses filter for stable hottest ordering.
$hottest_filter = static function ($clauses) {
global $wpdb;
if (strpos($clauses['join'], 'aksrt_cm_hot') === false) {
$clauses['join'] .= " LEFT JOIN {$wpdb->commentmeta} AS aksrt_cm_hot ON ({$wpdb->comments}.comment_ID = aksrt_cm_hot.comment_id AND aksrt_cm_hot.meta_key = 'aksrt_comment_likes')";
}
$clauses['orderby'] = 'CAST(COALESCE(aksrt_cm_hot.meta_value, 0) AS UNSIGNED) DESC, ' . $wpdb->comments . '.comment_date_gmt DESC';
return $clauses;
};
add_filter('comments_clauses', $hottest_filter, 20);
// Prefer date orderby with clauses override.
$query_args['orderby'] = 'comment_date_gmt';
unset($query_args['meta_key'], $query_args['meta_query']);
}
$comment_query = new WP_Comment_Query($query_args);
$comments = is_array($comment_query->comments) ? $comment_query->comments : [];
if ($hottest_filter) {
remove_filter('comments_clauses', $hottest_filter, 20);
}
// Pin reorder for page 1 when not author-only.
if ($page === 1 && !$author_only && function_exists('aksrt_reorder_pinned_comments')) {
$comments = aksrt_reorder_pinned_comments($comments, $post_id);
}
$count_args = [
'post_id' => $post_id,
'status' => 'approve',
'count' => true,
];
if ($author_only) {
$author_id = (int) get_post_field('post_author', $post_id);
if ($author_id > 0) {
$count_args['user_id'] = $author_id;
}
}
$total = (int) get_comments($count_args);
$max_pages = (int) max(1, (int) ceil($total / $per_page));
return [
'comments' => $comments,
'total' => $total,
'max_pages' => $max_pages,
'page' => $page,
'order' => $order,
'author_only' => $author_only,
'settings' => $settings,
'per_page' => $per_page,
];
}
endif;
if (!function_exists('aksrt_comments_render_items_html')) :
/**
* Render comment list items HTML via canonical callback.
*
* @param array<int,\WP_Comment> $comments
* @param array<string,mixed> $settings
* @param string $order
*/
function aksrt_comments_render_items_html(array $comments, array $settings = [], string $order = 'newest'): string {
if (empty($comments) || !function_exists('aksrt_comment_callback')) {
return '';
}
set_query_var('aksrt_comment_settings', $settings);
set_query_var('aksrt_comment_order', aksrt_comments_normalize_order($order));
$avatar = max(24, (int) ($settings['avatar_size'] ?? 48));
$depth = max(1, (int) ($settings['nested_depth'] ?? 3));
$reverse = $order === 'newest';
ob_start();
wp_list_comments([
'callback' => 'aksrt_comment_callback',
'style' => 'ol',
'avatar_size' => $avatar,
'max_depth' => $depth,
'reverse_top_level' => $reverse,
'reverse_children' => $reverse,
], $comments);
return (string) ob_get_clean();
}
endif;
if (!function_exists('aksrt_comments_render_single_html')) :
/**
* Render one comment item HTML.
*/
function aksrt_comments_render_single_html(\WP_Comment $comment, array $settings = []): string {
$html = aksrt_comments_render_items_html([$comment], $settings, 'newest');
return $html;
}
endif;
if (!function_exists('aksrt_comments_render_list_fragment')) :
/**
* Fragment payload for order/author/page AJAX.
*
* @return array{html:string,filter_html:string,pagination_html:string,count_text:string,total:int,max_pages:int,page:int,order:string,author_only:bool,empty:bool}
*/
function aksrt_comments_render_list_fragment(int $post_id, array $args = []): array {
$result = aksrt_comments_query_for_post($post_id, $args);
$settings = $result['settings'];
$order = $result['order'];
$author_only = !empty($result['author_only']);
$page = (int) $result['page'];
$max_pages = (int) $result['max_pages'];
$total = (int) $result['total'];
// Fake globals needed by pagination helpers when not on singular loop.
$GLOBALS['post'] = get_post($post_id);
setup_postdata($GLOBALS['post']);
set_query_var('cpage', $page);
set_query_var('aksrt_comment_order', $order);
set_query_var('aksrt_comment_settings', $settings);
$items_html = aksrt_comments_render_items_html($result['comments'], $settings, $order);
$ctx = [
'order' => $order,
'author_only' => $author_only,
'post_author_id' => (int) get_post_field('post_author', $post_id),
'corderby_enabled' => !empty($settings['corderby']),
'comment_count' => $total,
'empty_text' => (string) ($settings['empty_text'] ?? __('暂无评论,来做第一个评论的人吧~', 'aksrt')),
];
ob_start();
if (function_exists('aksrt_comments_render_filter') && !empty($ctx['corderby_enabled'])) {
aksrt_comments_render_filter($ctx);
}
$filter_html = (string) ob_get_clean();
ob_start();
if ($items_html === '' && function_exists('aksrt_comments_render_empty')) {
aksrt_comments_render_empty($ctx);
} else {
echo '<div id="postcomments"><ol class="commentlist list-unstyled" id="comment-list">';
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- rendered comment markup.
echo $items_html;
echo '</ol></div>';
}
$list_html = (string) ob_get_clean();
ob_start();
if (function_exists('aksrt_render_comment_pagination') && $max_pages > 1) {
// Temporarily override page counts via filter.
$pages_filter = static function () use ($max_pages) {
return $max_pages;
};
add_filter('get_comment_pages_count', $pages_filter);
aksrt_render_comment_pagination();
remove_filter('get_comment_pages_count', $pages_filter);
}
$pagination_html = (string) ob_get_clean();
wp_reset_postdata();
return [
'html' => $list_html,
'items_html' => $items_html,
'filter_html' => $filter_html,
'pagination_html' => $pagination_html,
'count_text' => sprintf(__('共 %d 条', 'aksrt'), $total),
'total' => $total,
'max_pages' => $max_pages,
'page' => $page,
'order' => $order,
'author_only' => $author_only,
'empty' => $items_html === '',
];
}
endif;
if (!function_exists('aksrt_comments_render_signarea')) :
/**
* Login-required gate.
*
* @param array<string,mixed> $ctx Comments context.
*/
function aksrt_comments_render_signarea(array $ctx): void {
$oauth_providers = is_array($ctx['oauth_providers'] ?? null) ? $ctx['oauth_providers'] : [];
?>
<div class="comment-signarea text-center box-body radius8">
<i class="fas fa-lock" aria-hidden="true"></i>
<span><?php esc_html_e('登录后参与评论', 'aksrt'); ?></span>
<div class="comment-login-prompt__btns">
<a class="signin-loader but hollow" href="<?php echo esc_url(function_exists('aksrt_get_login_url') ? aksrt_get_login_url(get_permalink()) : wp_login_url(get_permalink())); ?>"><?php esc_html_e('登录', 'aksrt'); ?></a>
<?php if (get_option('users_can_register')) : ?>
<a class="signup-loader but b-theme" href="<?php echo esc_url(function_exists('aksrt_get_register_url') ? aksrt_get_register_url() : wp_registration_url()); ?>"><?php esc_html_e('注册', 'aksrt'); ?></a>
<?php endif; ?>
</div>
<?php if (!empty($oauth_providers)) : ?>
<div class="comment-signarea__oauth">
<?php foreach ($oauth_providers as $provider) :
$provider_name = (string) ($provider['name'] ?? '');
$label = (string) ($provider['label'] ?? $provider_name);
$url = (string) ($provider['url'] ?? '#');
$icon = $provider['icon'] ?? '';
?>
<a href="<?php echo esc_url($url); ?>" class="social-login-item but hollow <?php echo esc_attr($provider_name); ?>" data-provider="<?php echo esc_attr($provider_name); ?>" title="<?php echo esc_attr($label); ?>">
<?php echo $icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<span><?php echo esc_html($label); ?></span>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<?php
}
endif;
if (!function_exists('aksrt_comments_render_form')) :
/**
* Comment respond form.
*
* @param array<string,mixed> $ctx Comments context.
*/
function aksrt_comments_render_form(array $ctx): void {
$is_logged_in = !empty($ctx['is_logged_in']);
$current_user = $ctx['current_user'] ?? null;
$avatar_size = max(40, (int) $ctx['avatar_size']);
$require_name_email = (bool) get_option('require_name_email');
$comment_author = isset($_COOKIE['comment_author_' . COOKIEHASH])
? sanitize_text_field(wp_unslash((string) $_COOKIE['comment_author_' . COOKIEHASH]))
: '';
$comment_email = isset($_COOKIE['comment_author_email_' . COOKIEHASH])
? sanitize_text_field(wp_unslash((string) $_COOKIE['comment_author_email_' . COOKIEHASH]))
: '';
$placeholder = (string) $ctx['box_placeholder'];
$post_id = (int) get_the_ID();
$can_comment = function_exists('aksrt_user_can')
? aksrt_user_can('comment_add', get_current_user_id(), $post_id)
: $is_logged_in;
if (!$can_comment) {
if (!$is_logged_in) {
aksrt_comments_render_signarea($ctx);
} else {
echo '<p class="comments-permission-denied muted-2-color">' . esc_html__('当前账号没有发表评论的权限。', 'aksrt') . '</p>';
}
return;
}
if (function_exists('aksrt_get_comment_virtual_input_html')) {
echo aksrt_get_comment_virtual_input_html($placeholder, '#respond'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
?>
<div id="respond" class="comment-respond mobile-fixed">
<div class="fixed-body"></div>
<form id="commentform" class="comment-form" method="post" action="<?php echo esc_url(site_url('/wp-comments-post.php')); ?>">
<div class="flex ac">
<div class="comt-title text-center flex0 mr10">
<?php if ($is_logged_in && $current_user instanceof WP_User) : ?>
<div class="comt-avatar mb10">
<?php echo get_avatar($current_user->ID, $avatar_size, '', '', ['class' => 'avatar-img comt-avatar']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<p class="text-ellipsis muted-2-color"><?php echo esc_html($current_user->display_name); ?></p>
<?php else : ?>
<div class="comt-avatar mb10">
<?php echo get_avatar(0, $avatar_size, '', '', ['class' => 'avatar-img comt-avatar']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<p data-toggle-class="open" data-target="#comment-user-info" title="<?php esc_attr_e('填写用户信息', 'aksrt'); ?>">
<?php echo $comment_author !== '' ? esc_html($comment_author) : esc_html__('昵称', 'aksrt'); ?>
</p>
<?php endif; ?>
</div>
<div class="comt-box grow1">
<div class="action-text mb10 em09 muted-2-color" id="comment-reply-info" style="display:none;"></div>
<textarea placeholder="<?php echo esc_attr($placeholder); ?>" autoheight="true" maxheight="188" class="form-control grin comt-textarea" name="comment" id="comment" cols="100%" rows="4" tabindex="1" required></textarea>
<?php if (function_exists('aksrt_is_captcha_enabled_for') && function_exists('aksrt_render_captcha') && aksrt_is_captcha_enabled_for('comment')) : ?>
<div class="comment-form__captcha" style="width:230px;margin-top:8px;"><?php aksrt_render_captcha('comment'); ?></div>
<?php endif; ?>
<div class="comt-ctrl relative">
<div class="comt-tips">
<?php comment_id_fields(); ?>
<?php wp_nonce_field('aksrt_comment_nonce', '_aksrt_comment_nonce'); ?>
<input type="hidden" name="comment_post_ID" value="<?php echo esc_attr((string) get_the_ID()); ?>">
<?php do_action('comment_form', get_the_ID()); ?>
</div>
<div class="comt-tips-right pull-right">
<a class="but c-red" id="cancel-comment-reply-link" href="javascript:;" style="display:none;"><?php esc_html_e('取消', 'aksrt'); ?></a>
<button class="but c-blue pw-1em input-expand-submit comment-send comment-form__submit" name="submit" id="submit" type="submit" tabindex="5"><?php echo esc_html((string) $ctx['submit_text']); ?></button>
</div>
<div class="comt-tips-left">
<?php if (!$is_logged_in) :
$req_mark = $require_name_email ? '(' . __('必填', 'aksrt') . ')' : '';
?>
<span class="dropup relative" id="comment-user-info"<?php echo $require_name_email ? ' require_name_email="true"' : ''; ?>>
<a class="but mr6" data-toggle-class="open" data-target="#comment-user-info" href="javascript:;"><i class="fa fa-fw fa-user" aria-hidden="true"></i><span class="hide-sm"><?php esc_html_e('昵称', 'aksrt'); ?></span></a>
<div class="dropdown-menu box-body" style="width:250px;">
<div class="mb20">
<p><?php esc_html_e('请填写用户信息:', 'aksrt'); ?></p>
<ul>
<li class="line-form mb10">
<input type="text" name="author" class="line-form-input" tabindex="1" value="<?php echo esc_attr($comment_author); ?>" placeholder="" <?php echo $require_name_email ? 'required' : ''; ?> />
<div class="scale-placeholder"><?php echo esc_html__('昵称', 'aksrt') . esc_html($req_mark); ?></div>
</li>
<li class="line-form">
<input type="email" name="email" class="line-form-input" tabindex="2" value="<?php echo esc_attr($comment_email); ?>" placeholder="" <?php echo $require_name_email ? 'required' : ''; ?> />
<div class="scale-placeholder"><?php echo esc_html__('邮箱', 'aksrt') . esc_html($req_mark); ?></div>
</li>
</ul>
</div>
<?php
$oauth = is_array($ctx['oauth_providers'] ?? null) ? $ctx['oauth_providers'] : [];
if (!empty($oauth)) :
?>
<div class="comment-signarea__oauth flex ac" style="flex-wrap:wrap;gap:6px;">
<?php foreach ($oauth as $provider) :
$label = (string) ($provider['label'] ?? $provider['name'] ?? '');
$url = (string) ($provider['url'] ?? '#');
?>
<a href="<?php echo esc_url($url); ?>" class="but hollow social-login-item"><?php echo esc_html($label); ?></a>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</span>
<?php endif; ?>
<?php if (function_exists('aksrt_render_comment_expand_toolbar')) { aksrt_render_comment_expand_toolbar($ctx); } ?>
</div>
</div>
</div>
</div>
</form>
</div>
<?php
}
endif;
if (!function_exists('aksrt_comments_render_filter')) :
/**
* Newest/hottest + author-only filter.
*
* @param array<string,mixed> $ctx Comments context.
*/
function aksrt_comments_render_filter(array $ctx): void {
if (empty($ctx['corderby_enabled'])) {
return;
}
$order = (string) $ctx['order'];
$author_only = !empty($ctx['author_only']);
$post_author_id = (int) $ctx['post_author_id'];
?>
<div class="comment-filter tab-nav-theme flex ac jsb" win-ajax-replace="comment-order-btn">
<ul class="list-inline comment-order-box comment-filter__tabs">
<li class="<?php echo $order === 'newest' ? 'active' : ''; ?>">
<a href="javascript:;" class="comment-orderby" data-order="newest" rel="nofollow"><?php esc_html_e('最新', 'aksrt'); ?></a>
</li>
<li class="<?php echo $order === 'hottest' ? 'active' : ''; ?>">
<a href="javascript:;" class="comment-orderby" data-order="hottest" rel="nofollow"><?php esc_html_e('最热', 'aksrt'); ?></a>
</li>
</ul>
<?php if ($post_author_id > 0) : ?>
<a href="javascript:;" class="but comment-orderby btn-only-author p2-10 comment-author-filter<?php echo $author_only ? ' active' : ''; ?>" data-author-only="<?php echo $author_only ? '0' : '1'; ?>" rel="nofollow">
<?php echo $author_only ? esc_html__('查看全部', 'aksrt') : esc_html__('只看作者', 'aksrt'); ?>
</a>
<?php endif; ?>
</div>
<?php
}
endif;
if (!function_exists('aksrt_comments_render_list')) :
/**
* Comment list + pagination.
*
* @param array<string,mixed> $ctx Comments context.
*/
function aksrt_comments_render_list(array $ctx): void {
?>
<div id="postcomments">
<ol class="commentlist list-unstyled" id="comment-list">
<?php
wp_list_comments([
'style' => 'ol',
'short_ping' => true,
'avatar_size' => (int) $ctx['avatar_size'],
'max_depth' => (int) $ctx['max_depth'],
'callback' => 'aksrt_comment_callback',
'reverse_top_level' => !empty($ctx['reverse_comments']),
'reverse_children' => !empty($ctx['reverse_comments']),
]);
?>
</ol>
</div>
<?php
if (function_exists('aksrt_render_comment_pagination')) {
aksrt_render_comment_pagination();
}
}
endif;
if (!function_exists('aksrt_comments_render_empty')) :
/**
* Empty state.
*
* @param array<string,mixed> $ctx Comments context.
*/
function aksrt_comments_render_empty(array $ctx): void {
$closed = !comments_open();
$text = (string) ($ctx['empty_text'] ?? __('暂无评论内容', 'aksrt'));
if ($closed) {
$text = __('评论已关闭', 'aksrt');
} elseif (!empty($ctx['author_only'])) {
$text = __('暂无作者评论', 'aksrt');
}
$hint = $closed
? __('本文评论已关闭,仅可浏览历史留言', 'aksrt')
: (!empty($ctx['author_only'])
? __('切换到「查看全部」可浏览其他评论', 'aksrt')
: __('成为第一个评论者吧', 'aksrt'));
if (function_exists('aksrt_get_null')) {
echo aksrt_get_null($text, 40, 'null.svg', 'comment comment-null comments-empty', 220); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<p class="comments-empty__hint muted-3-color em09 text-center" style="margin-top:-20px;">' . esc_html($hint) . '</p>';
return;
}
?>
<div class="comments-empty post_ajax_loader">
<div class="comments-empty__icon">
<i class="far fa-comment-dots"></i>
</div>
<p class="comments-empty__text"><?php echo esc_html($text); ?></p>
<p class="comments-empty__hint"><?php echo esc_html($hint); ?></p>
</div>
<?php
}
endif;
if (!function_exists('aksrt_comments_render')) :
/**
* Compose the full comments surface.
*/
function aksrt_comments_render(): void {
if (post_password_required()) {
return;
}
$ctx = aksrt_comments_build_context();
if (!empty($ctx['close_comments'])) {
return;
}
if (!empty($ctx['is_hottest'])) {
aksrt_comments_apply_hottest_order();
}
set_query_var('aksrt_comment_order', (string) $ctx['order']);
set_query_var('aksrt_comment_settings', $ctx['settings']);
$avatar_size = max(45, (int) $ctx['avatar_size']);
$count = (int) $ctx['comment_count'];
$count_label = $count > 0
? sprintf(__('共%s条', 'aksrt'), (string) $count)
: __('抢沙发', 'aksrt');
?>
<div class="theme-box" id="comments" style="<?php echo esc_attr('--aksrt-comment-avatar:' . $avatar_size . 'px;--aksrt-comment-avatar-form:' . $avatar_size . 'px;--aksrt-comment-indent:86px;'); ?>">
<div class="box-body notop">
<div class="title-theme">
<?php echo esc_html((string) $ctx['title_text']); ?>
<small class="comments-count"><?php echo esc_html($count_label); ?></small>
</div>
</div>
<div class="no_webshot main-bg theme-box box-body radius8 main-shadow">
<?php if (comments_open()) : ?>
<?php if (!empty($ctx['require_login']) && empty($ctx['is_logged_in'])) : ?>
<?php aksrt_comments_render_signarea($ctx); ?>
<?php else : ?>
<?php aksrt_comments_render_form($ctx); ?>
<?php endif; ?>
<?php endif; ?>
<?php
$show_filter = !empty($ctx['corderby_enabled']) && ($count > 0 || !empty($ctx['author_only']) || have_comments());
if ($show_filter) {
aksrt_comments_render_filter($ctx);
}
?>
<?php if (have_comments()) : ?>
<?php aksrt_comments_render_list($ctx); ?>
<?php elseif (!post_password_required()) : ?>
<?php aksrt_comments_render_empty($ctx); ?>
<div class="pagenav hide"><div class="next-page ajax-next"><a href="#"></a></div></div>
<?php endif; ?>
<?php if (!comments_open() && $count && post_type_supports(get_post_type(), 'comments')) : ?>
<p class="comments-closed separator text-muted em12"><?php esc_html_e('评论已关闭。', 'aksrt'); ?></p>
<?php endif; ?>
</div>
</div>
<?php
}
endif;