Files
wordpress-theme-aksrt/inc/helpers/comments/item.php
T
kate522 9375b1c30c refactor(assets): vendor 资产迁入标准目录并全仓去除 zibll 标识
- assets/vendor 全量迁移: fontawesome5→assets/fontawesome5, css→assets/css,
  js→assets/js/runtime(避开 14 个同名自有文件), img 合并去重→assets/img,
  fonts→assets/fonts; 删除 assets/vendor
- libs 五个与 widgets/third-party 字节相同的库不重复入库, loader paths 改指向
- 运行时切换: _win.uri=assets 根, loader baseUrl=/js/runtime, enlighter 注入
  路径同步; PHP 7 个引用文件切换并改名 $zibll_*→$runtime_*
- 去品牌: Qinver 头注释/品牌 console.log/演示链接清除, 默认文案中性化
- 功能标识符改名: zib__→aksrt__, zib_ajax→aksrt_ajax, window.zib→
  window.aksrtLegacy, zibllblock/*→aksrtblock/*, .zib-widget→.aksrt-panel,
  .zib-slider→.aksrt-slider, zib_menu_options meta 键等
- 自有 CSS 改名: legacy-utilities/compat-vars/footer shell
- admin SPA 重建; 契约测试同步(路径/断言/文件更名)
- 例外保留: tests/visual 对照环境与 fixtures 前缀(外部 Zibll 产品引用)

验证: php -l 133 个改动文件通过; runtime 86 个 JS node --check 通过;
契约测试 68/70(2 个失败经 stash 对照确认为存量问题)
2026-08-22 16:16:30 +08:00

311 lines
13 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Comment list item renderer — legacy DOM contract (1:1).
*
* Mirrors legacy / legacy / legacy
* from the legacy comments-list module.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_get_comment_like_html')) :
/**
* Header like control (legacy: legacy).
*
* @param WP_Comment $comment Comment.
* @param bool $enabled Like enabled.
* @return string
*/
function aksrt_get_comment_like_html($comment, bool $enabled = true): string {
if (!$enabled) {
return '';
}
$comment_id = $comment instanceof WP_Comment ? (int) $comment->comment_ID : (int) $comment;
if ($comment_id <= 0) {
return '';
}
$like_count = function_exists('aksrt_get_comment_likes') ? (int) aksrt_get_comment_likes($comment_id) : 0;
$is_liked = function_exists('aksrt_is_comment_liked') && aksrt_is_comment_liked($comment_id);
$classes = 'action action-comment-like muted-2-color flex0 ml10' . ($is_liked ? ' actived' : '');
return sprintf(
'<a href="javascript:;" data-comment-action="like" data-action="comment_like" class="%1$s" data-pid="%2$d" data-active="%3$s" aria-pressed="%4$s"><i class="fa fa-thumbs-up mr3" aria-hidden="true"></i><count>%5$s</count></a>',
esc_attr($classes),
$comment_id,
$is_liked ? '1' : '0',
$is_liked ? 'true' : 'false',
esc_html((string) $like_count)
);
}
endif;
if (!function_exists('aksrt_get_comment_avatar_box')) :
/**
* Comment avatar box (legacy: legacy).
*
* @param WP_Comment $comment Comment.
* @param string $class Classes for the avatar wrapper.
* @param bool $link Wrap in a link when a target URL exists.
* @return string
*/
function aksrt_get_comment_avatar_box(WP_Comment $comment, string $class = 'avatar-img comt-avatar', bool $link = true): string {
$user_id = (int) $comment->user_id;
$size = 45;
$avatar = $user_id > 0
? get_avatar($user_id, $size, '', '', ['class' => 'avatar'])
: get_avatar($comment->comment_author_email, $size, '', '', ['class' => 'avatar']);
$html = '<span class="' . esc_attr($class) . '">' . $avatar . '</span>';
if (!$link) {
return $html;
}
if ($user_id > 0) {
$url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user_id) : get_author_posts_url($user_id);
return '<a href="' . esc_url($url) . '">' . $html . '</a>';
}
if (!empty($comment->comment_author_url)) {
return '<a rel="nofollow" href="' . esc_url($comment->comment_author_url) . '">' . $html . '</a>';
}
return $html;
}
endif;
if (!function_exists('aksrt_get_comments_user_name_html')) :
/**
* Name row (legacy: legacy) — topping + author + badges.
*
* @param WP_Comment $comment Comment.
* @param array<string,mixed> $settings Display settings.
* @return string
*/
function aksrt_get_comments_user_name_html(WP_Comment $comment, array $settings = []): string {
$user_id = (int) $comment->user_id;
$show_author_tag = !isset($settings['author_tag']) || !empty($settings['author_tag']);
$is_pinned = function_exists('aksrt_is_comment_pinned') && aksrt_is_comment_pinned($comment);
$is_post_author = $user_id > 0 && $user_id === (int) get_post_field('post_author', $comment->comment_post_ID);
$topping = '';
if ($is_pinned) {
$topping = '<badge class="badge-topping jb-blue mr6 flex0" title="' . esc_attr__('置顶评论', 'aksrt') . '" data-toggle="tooltip"><i class="fa fa-thumbtack" aria-hidden="true"></i></badge>';
}
$user_name = '';
if ($user_id > 0) {
$user = get_userdata($user_id);
if ($user instanceof WP_User) {
$url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user_id) : get_author_posts_url($user_id);
$user_name = '<a class="text-ellipsis font-bold" href="' . esc_url($url) . '">' . esc_html($user->display_name) . '</a>';
if (function_exists('aksrt_render_user_identity_chips')) {
$user_name .= aksrt_render_user_identity_chips($user_id, 'comment');
}
}
} elseif (!empty($comment->comment_author_url)) {
$user_name = '<a class="text-ellipsis font-bold" rel="nofollow" href="' . esc_url($comment->comment_author_url) . '">' . esc_html($comment->comment_author) . '</a>';
}
$user_name = $user_name !== '' ? $user_name : '<b class="mr6 text-ellipsis">' . esc_html($comment->comment_author) . '</b>';
$badge = '';
if ($show_author_tag && $is_post_author) {
$badge .= '<span class="badg c-green badg-sm flex0 ml3">' . esc_html__('作者', 'aksrt') . '</span>';
}
return '<name class="flex ac flex1">' . $topping . $user_name . $badge . '</name>';
}
endif;
if (!function_exists('aksrt_get_comment_header_html')) :
/**
* Comment header (legacy: legacy).
*
* @param WP_Comment $comment Comment.
* @param array<string,mixed> $settings Settings.
* @return string
*/
function aksrt_get_comment_header_html(WP_Comment $comment, array $settings = []): string {
$like_enabled = !isset($settings['like_enabled']) || !empty($settings['like_enabled']);
$avatar = aksrt_get_comment_avatar_box($comment, 'avatar-img comt-avatar');
$name = aksrt_get_comments_user_name_html($comment, $settings);
$like = aksrt_get_comment_like_html($comment, $like_enabled);
$html = '<div class="author-box flex ac">';
$html .= $avatar;
$html .= $name;
$html .= $like;
$html .= '</div>';
return '<div class="comment-header mb10">' . $html . '</div>';
}
endif;
if (!function_exists('aksrt_get_comments_action_dropdown_html')) :
/**
* More-actions menu (legacy: legacy) — pin / edit / approve / delete.
*
* @param WP_Comment $comment Comment.
* @param int $depth Depth.
* @return string
*/
function aksrt_get_comments_action_dropdown_html(WP_Comment $comment, int $depth = 0): string {
$perms = function_exists('aksrt_comment_action_permissions')
? aksrt_comment_action_permissions($comment)
: ['can_edit' => false, 'can_delete' => false, 'can_moderate' => false, 'can_pin' => false];
$is_pinned = function_exists('aksrt_is_comment_pinned') && aksrt_is_comment_pinned($comment);
$is_pending = '0' === (string) $comment->comment_approved;
$lists = '';
if (!empty($perms['can_pin']) && (int) $comment->comment_parent === 0) {
$label = $is_pinned ? __('取消置顶', 'aksrt') : __('设置置顶', 'aksrt');
// 不带 legacy 的 wp-ajax-submit 类:vendor main.min.js 会全局代理该类并向
// admin-ajax 发空 action 请求(400 "0"),置顶走 data-comment-action REST。
$lists .= '<li><a class="comment-topping" data-comment-action="pin" data-pinned="' . ($is_pinned ? '1' : '0') . '" href="javascript:;"><i class="fa fa-thumbtack mr10 fa-fw" aria-hidden="true"></i>' . esc_html($label) . '</a></li>';
}
if (!empty($perms['can_edit'])) {
$lists .= '<li><a class="comment-edit-link" data-commentid="' . (int) $comment->comment_ID . '" data-postid="' . (int) $comment->comment_post_ID . '" href="javascript:;"><i class="fa fa-edit mr10 fa-fw" aria-hidden="true"></i>' . esc_html__('编辑', 'aksrt') . '</a></li>';
}
if (!empty($perms['can_moderate'])) {
$text = $is_pending ? __('批准', 'aksrt') : __('驳回', 'aksrt');
$class = $is_pending ? 'approve' : 'unapprove';
$action = $is_pending ? 'approve' : 'hold';
$lists .= '<li><a class="comment-approve-link ' . $class . '" data-comment-action="' . $action . '" data-commentid="' . (int) $comment->comment_ID . '" data-postid="' . (int) $comment->comment_post_ID . '" href="javascript:;"><i class="fa fa-check mr10 fa-fw" aria-hidden="true"></i><text>' . esc_html($text) . '</text></a></li>';
}
if (!empty($perms['can_delete'])) {
$lists .= '<li><a class="comment-trash-link c-red" data-comment-action="delete" data-commentid="' . (int) $comment->comment_ID . '" data-postid="' . (int) $comment->comment_post_ID . '" href="javascript:;"><i class="fa fa-trash-o mr10 fa-fw" aria-hidden="true"></i>' . esc_html__('删除', 'aksrt') . '</a></li>';
}
if ($lists === '') {
return '';
}
$icon_a = '<a href="javascript:;" class="muted-color padding-6" data-toggle="dropdown"><i class="fa fa-ellipsis-h" aria-hidden="true"></i></a>';
return '<span class="dropdown drop-fixed-sm padding-6">' . $icon_a . '<ul class="dropdown-menu">' . $lists . '</ul></span>';
}
endif;
if (!function_exists('aksrt_get_comment_footer_html')) :
/**
* comt-meta row (legacy: legacy).
*
* @param WP_Comment $comment Comment.
* @param array $args wp_list_comments args.
* @param int $depth Depth.
* @param array<string,mixed> $settings Settings.
* @return string
*/
function aksrt_get_comment_footer_html(WP_Comment $comment, array $args, int $depth, array $settings = []): string {
$is_pending = '0' === (string) $comment->comment_approved;
$badg_approve = '';
if ($is_pending) {
$badg_approve = '<span class="badg c-red badg-sm">' . esc_html__('待审核', 'aksrt') . '</span>';
}
$badg_approve = '<span class="badge-approve">' . $badg_approve . '</span>';
$absolute = date_i18n(__('Y年m月d日 H:i:s', 'aksrt'), strtotime((string) $comment->comment_date));
$ago = function_exists('aksrt_time_ago')
? aksrt_time_ago((string) $comment->comment_date)
: human_time_diff(strtotime((string) $comment->comment_date), current_time('timestamp')) . __('前', 'aksrt');
$time_html = '<span class="comt-author" title="' . esc_attr($absolute) . '">' . esc_html($ago) . '</span>';
$city_html = function_exists('aksrt_get_comment_city_badge_html')
? aksrt_get_comment_city_badge_html($comment)
: '';
$parent_html = '';
if ((int) $comment->comment_parent > 0) {
$parent_author = get_comment_author((int) $comment->comment_parent);
$parent_html = '<span>@<a rel="nofollow" class="url" href="javascript:;" data-scroll-to="#comment-' . (int) $comment->comment_parent . '">' . esc_html($parent_author) . '</a></span>';
}
$reply_html = '';
if (!$is_pending && $depth > 0) {
$max_depth = (int) ($args['max_depth'] ?? get_option('thread_comments_depth', 5));
$link = get_comment_reply_link(
[
'add_below' => 'div-comment',
'reply_text' => __('回复', 'aksrt'),
'login_text' => __('回复', 'aksrt'),
'depth' => $depth,
'max_depth' => $max_depth,
],
$comment
);
if ($link) {
// 去掉 WP 内联 onclick(addComment.moveForm),回复由 comment-move-form.js 事件委托处理。
$link = preg_replace('/ onclick="[^"]*"/i', '', $link);
if (strpos($link, 'data-commentid') === false) {
$link = str_replace(
'comment-reply-link',
'comment-reply-link" data-commentid="' . (int) $comment->comment_ID . '" data-postid="' . (int) $comment->comment_post_ID,
$link
);
}
$reply_html = '<span class="reply-link">' . $link . '</span>';
}
}
$actions = aksrt_get_comments_action_dropdown_html($comment, $depth);
$info = $time_html . $city_html . $parent_html . $badg_approve . $reply_html;
return '<div class="comt-meta muted-2-color">' . $info . $actions . '</div>';
}
endif;
if (!function_exists('aksrt_get_comments_list_html')) :
/**
* Single comment item HTML (legacy: legacy).
*
* @param WP_Comment $comment Comment.
* @param array $args Args.
* @param int $depth Depth.
* @param array $settings Settings.
* @return string
*/
function aksrt_get_comments_list_html(WP_Comment $comment, array $args = [], int $depth = 0, array $settings = []): string {
$comment_id = (int) $comment->comment_ID;
$con = function_exists('aksrt_render_comment_content')
? aksrt_render_comment_content((string) get_comment_text($comment))
: wp_kses_post((string) get_comment_text($comment));
$header = aksrt_get_comment_header_html($comment, $settings);
$footer = aksrt_get_comment_footer_html($comment, $args, $depth, $settings);
$html = '<li ' . comment_class('', $comment, null, false) . ' id="comment-' . esc_attr((string) $comment_id) . '">';
$html .= '<ul class="list-inline">';
$html .= '<li class="comt-main" id="div-comment-' . esc_attr((string) $comment_id) . '">';
$html .= $header;
$html .= '<div class="comment-footer">';
$html .= '<div class="mb10 comment-content" id="comment-content-' . esc_attr((string) $comment_id) . '">' . $con . '</div>';
$html .= $footer;
$html .= '</div>';
$html .= '</li>';
$html .= '</ul>';
return $html;
}
endif;
if (!function_exists('aksrt_comment_callback')) :
/**
* Canonical wp_list_comments callback (legacy: legacy).
*
* The closing </li> is emitted by the walker after children.
*
* @param WP_Comment $comment Comment.
* @param array $args Args.
* @param int $depth Depth.
*/
function aksrt_comment_callback($comment, $args, $depth) {
$GLOBALS['comment'] = $comment;
$settings = get_query_var('aksrt_comment_settings', []);
$settings = is_array($settings) ? $settings : [];
if (empty($settings) && class_exists('\AKSRT\Settings\Settings')) {
$settings = \AKSRT\Settings\Settings::get_comment_display_settings();
}
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- composed helpers escape.
echo aksrt_get_comments_list_html($comment, is_array($args) ? $args : [], (int) $depth, $settings);
}
endif;