- 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
619 lines
24 KiB
PHP
619 lines
24 KiB
PHP
<?php
|
|
/**
|
|
* @package AKSRT
|
|
*/
|
|
|
|
namespace AKSRT\Core;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
class CommentActions {
|
|
|
|
private static $instance = null;
|
|
|
|
private function __construct() {}
|
|
|
|
public static function get_instance(): self {
|
|
if (null === self::$instance) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
public function init(): void {
|
|
add_action('rest_api_init', [$this, 'register_routes']);
|
|
}
|
|
|
|
public function register_routes(): void {
|
|
register_rest_route('aksrt/v1', '/comment/list', [
|
|
'methods' => \WP_REST_Server::READABLE,
|
|
'callback' => [$this, 'list_comments'],
|
|
'permission_callback' => '__return_true',
|
|
'args' => [
|
|
'post_id' => ['required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint'],
|
|
'page' => ['required' => false, 'type' => 'integer', 'default' => 1, 'sanitize_callback' => 'absint'],
|
|
'order' => ['required' => false, 'type' => 'string', 'default' => 'newest', 'sanitize_callback' => 'sanitize_key'],
|
|
'author_only' => ['required' => false, 'type' => 'boolean', 'default' => false],
|
|
],
|
|
]);
|
|
|
|
register_rest_route('aksrt/v1', '/comment/submit', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'submit_comment'],
|
|
'permission_callback' => '__return_true',
|
|
]);
|
|
|
|
register_rest_route('aksrt/v1', '/comment/edit', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'edit_comment'],
|
|
'permission_callback' => [$this, 'check_edit_permission'],
|
|
'args' => [
|
|
'comment_id' => ['required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint'],
|
|
'content' => ['required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_textarea_field'],
|
|
],
|
|
]);
|
|
|
|
register_rest_route('aksrt/v1', '/comment/delete', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'delete_comment'],
|
|
'permission_callback' => [$this, 'check_delete_permission'],
|
|
'args' => [
|
|
'comment_id' => ['required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint'],
|
|
],
|
|
]);
|
|
|
|
register_rest_route('aksrt/v1', '/comment/moderate', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'moderate_comment'],
|
|
'permission_callback' => [$this, 'check_moderate_permission'],
|
|
'args' => [
|
|
'comment_id' => ['required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint'],
|
|
'status' => ['required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field'],
|
|
],
|
|
]);
|
|
|
|
register_rest_route('aksrt/v1', '/comment/pin', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'pin_comment'],
|
|
'permission_callback' => [$this, 'check_pin_permission'],
|
|
'args' => [
|
|
'comment_id' => ['required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint'],
|
|
'pinned' => ['required' => false, 'type' => 'boolean'],
|
|
],
|
|
]);
|
|
|
|
register_rest_route('aksrt/v1', '/comment/like', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'like_comment'],
|
|
// Guests may like; abuse is bounded by per-visitor toggle state.
|
|
'permission_callback' => '__return_true',
|
|
'args' => [
|
|
'comment_id' => ['required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint'],
|
|
'active' => ['required' => false, 'type' => 'boolean'],
|
|
],
|
|
]);
|
|
|
|
register_rest_route('aksrt/v1', '/comment/get', [
|
|
'methods' => \WP_REST_Server::READABLE,
|
|
'callback' => [$this, 'get_comment'],
|
|
'permission_callback' => [$this, 'check_get_permission'],
|
|
'args' => [
|
|
'comment_id' => ['required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint'],
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Permission: can load raw content for edit?
|
|
*/
|
|
public function check_get_permission(\WP_REST_Request $request): bool {
|
|
$comment_id = (int) $request->get_param('comment_id');
|
|
if ($comment_id <= 0 || !is_user_logged_in()) {
|
|
return false;
|
|
}
|
|
$perms = $this->permissions($comment_id);
|
|
return !empty($perms['can_edit']);
|
|
}
|
|
|
|
/**
|
|
* Return raw comment content for moveForm edit.
|
|
*/
|
|
public function get_comment(\WP_REST_Request $request): \WP_REST_Response {
|
|
$comment_id = (int) $request->get_param('comment_id');
|
|
$comment = get_comment($comment_id);
|
|
if (!$comment) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'comment_not_found',
|
|
'message' => __('评论不存在。', 'aksrt'),
|
|
], 404);
|
|
}
|
|
return new \WP_REST_Response([
|
|
'success' => true,
|
|
'content' => (string) $comment->comment_content,
|
|
'data' => [
|
|
'content' => (string) $comment->comment_content,
|
|
'comment_id' => $comment_id,
|
|
'parent' => (int) $comment->comment_parent,
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Resolve the per-comment action contract (single source of truth).
|
|
*
|
|
* @param int $comment_id Comment ID.
|
|
* @return array{can_edit:bool,can_delete:bool,can_moderate:bool,can_pin:bool}
|
|
*/
|
|
private function permissions(int $comment_id): array {
|
|
if (function_exists('aksrt_comment_action_permissions')) {
|
|
return aksrt_comment_action_permissions($comment_id);
|
|
}
|
|
|
|
// Defensive fallback if the helper is unavailable.
|
|
$comment = get_comment($comment_id);
|
|
$is_mod = current_user_can('moderate_comments');
|
|
$is_owner = $comment && is_user_logged_in() && (int) $comment->user_id === get_current_user_id();
|
|
return [
|
|
'can_edit' => $is_mod || $is_owner,
|
|
'can_delete' => $is_mod || $is_owner,
|
|
'can_moderate' => $is_mod,
|
|
'can_pin' => $is_mod,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
return $this->permissions((int) $request->get_param('comment_id'))['can_edit'];
|
|
}
|
|
|
|
/**
|
|
* Permission: can delete? (author, or moderator)
|
|
*/
|
|
public function check_delete_permission(\WP_REST_Request $request): bool {
|
|
if (!is_user_logged_in()) return false;
|
|
return $this->permissions((int) $request->get_param('comment_id'))['can_delete'];
|
|
}
|
|
|
|
/**
|
|
* Permission: can pin? (moderator, top-level only)
|
|
*/
|
|
public function check_pin_permission(\WP_REST_Request $request): bool {
|
|
if (!is_user_logged_in()) return false;
|
|
return $this->permissions((int) $request->get_param('comment_id'))['can_pin'];
|
|
}
|
|
|
|
|
|
/**
|
|
* Fragment list for order / author / page without full HTML scrape.
|
|
*/
|
|
public function list_comments(\WP_REST_Request $request): \WP_REST_Response {
|
|
$post_id = (int) $request->get_param('post_id');
|
|
$post = get_post($post_id);
|
|
if (!$post) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'post_not_found',
|
|
'message' => __('文章不存在。', 'aksrt'),
|
|
], 404);
|
|
}
|
|
|
|
if (!function_exists('aksrt_comments_render_list_fragment')) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'fragment_unavailable',
|
|
'message' => __('评论片段渲染不可用。', 'aksrt'),
|
|
], 500);
|
|
}
|
|
|
|
$order = sanitize_key((string) ($request->get_param('order') ?: 'newest'));
|
|
$author_only = (bool) $request->get_param('author_only');
|
|
$page = max(1, (int) ($request->get_param('page') ?: 1));
|
|
|
|
$fragment = aksrt_comments_render_list_fragment($post_id, [
|
|
'order' => $order,
|
|
'author_only' => $author_only,
|
|
'page' => $page,
|
|
]);
|
|
|
|
return new \WP_REST_Response([
|
|
'success' => true,
|
|
'data' => $fragment,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* AJAX submit with HTML item for local insert.
|
|
* Runs through native WP comment pipeline (preprocess_comment / moderation).
|
|
*/
|
|
public function submit_comment(\WP_REST_Request $request): \WP_REST_Response {
|
|
$params = $request->get_json_params();
|
|
if (!is_array($params) || empty($params)) {
|
|
$params = $request->get_params();
|
|
}
|
|
if (!is_array($params)) {
|
|
$params = [];
|
|
}
|
|
|
|
$edit_id = absint($params['edit_comment_ID'] ?? $params['edit_comment_id'] ?? 0);
|
|
if ($edit_id > 0) {
|
|
$request->set_param('comment_id', $edit_id);
|
|
$request->set_param('content', (string) ($params['comment'] ?? $params['content'] ?? ''));
|
|
return $this->edit_comment($request);
|
|
}
|
|
|
|
$post_id = absint($params['comment_post_ID'] ?? $params['post_id'] ?? 0);
|
|
$content = isset($params['comment']) ? (string) $params['comment'] : '';
|
|
$parent = absint($params['comment_parent'] ?? 0);
|
|
|
|
if ($post_id <= 0 || trim(wp_strip_all_tags($content)) === '') {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'invalid_payload',
|
|
'message' => __('请输入评论内容。', 'aksrt'),
|
|
], 400);
|
|
}
|
|
|
|
$post = get_post($post_id);
|
|
if (!$post || !comments_open($post_id)) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'comments_closed',
|
|
'message' => __('评论已关闭。', 'aksrt'),
|
|
], 403);
|
|
}
|
|
|
|
$user_id = get_current_user_id();
|
|
if (!function_exists('aksrt_user_can') || !aksrt_user_can('comment_add', $user_id, $post_id)) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'comment_forbidden',
|
|
'message' => __('当前账号没有发表评论的权限。', 'aksrt'),
|
|
], $user_id > 0 ? 403 : 401);
|
|
}
|
|
|
|
$nonce = (string) ($params['_aksrt_comment_nonce'] ?? $params['_wpnonce'] ?? '');
|
|
if ($nonce !== '' && !wp_verify_nonce($nonce, 'aksrt_comment_nonce') && !wp_verify_nonce($nonce, 'wp_rest')) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'invalid_nonce',
|
|
'message' => __('安全校验失败,请刷新后重试。', 'aksrt'),
|
|
], 403);
|
|
}
|
|
|
|
$captcha_result = aksrt_require_captcha('comment', $params);
|
|
if ($captcha_result !== true) {
|
|
$captcha_error = is_wp_error($captcha_result) ? $captcha_result : null;
|
|
$captcha_data = $captcha_error ? $captcha_error->get_error_data() : null;
|
|
$captcha_status = is_array($captcha_data) ? (int) ($captcha_data['status'] ?? 400) : 400;
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => $captcha_error ? ($captcha_error->get_error_code() ?: 'captcha_failed') : 'captcha_failed',
|
|
'message' => $captcha_error
|
|
? ($captcha_error->get_error_message() ?: __('人机验证失败', 'aksrt'))
|
|
: __('人机验证失败', 'aksrt'),
|
|
], $captcha_status > 0 ? $captcha_status : 400);
|
|
}
|
|
|
|
$user = wp_get_current_user();
|
|
$commentdata = [
|
|
'comment_post_ID' => $post_id,
|
|
'comment_content' => $content,
|
|
'comment_parent' => $parent,
|
|
'comment_type' => '',
|
|
// Prefer real client IP behind CDN/proxy (REMOTE_ADDR alone is often edge IP).
|
|
'comment_author_IP' => function_exists('aksrt_get_client_ip')
|
|
? (string) aksrt_get_client_ip()
|
|
: (isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash((string) $_SERVER['REMOTE_ADDR'])) : ''),
|
|
'comment_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash((string) $_SERVER['HTTP_USER_AGENT'])) : '',
|
|
'comment_date' => current_time('mysql'),
|
|
'comment_date_gmt' => current_time('mysql', true),
|
|
];
|
|
|
|
if ($user && $user->ID > 0) {
|
|
$commentdata['user_id'] = (int) $user->ID;
|
|
$commentdata['comment_author'] = $user->display_name ?: $user->user_login;
|
|
$commentdata['comment_author_email'] = $user->user_email;
|
|
$commentdata['comment_author_url'] = $user->user_url;
|
|
} else {
|
|
$commentdata['user_id'] = 0;
|
|
$commentdata['comment_author'] = sanitize_text_field((string) ($params['author'] ?? ''));
|
|
$commentdata['comment_author_email'] = sanitize_email((string) ($params['email'] ?? ''));
|
|
$commentdata['comment_author_url'] = esc_url_raw((string) ($params['url'] ?? ''));
|
|
if ($commentdata['comment_author'] === '' || $commentdata['comment_author_email'] === '') {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'guest_fields_required',
|
|
'message' => __('请填写昵称和邮箱。', 'aksrt'),
|
|
], 400);
|
|
}
|
|
}
|
|
|
|
foreach (['author', 'email', 'url', 'comment', 'comment_post_ID', 'comment_parent', '_aksrt_comment_nonce'] as $k) {
|
|
if (isset($params[$k])) {
|
|
$_POST[$k] = $params[$k];
|
|
}
|
|
}
|
|
|
|
$comment_id = null;
|
|
if (class_exists('\AKSRT\Auth\Moderation')) {
|
|
\AKSRT\Auth\Moderation::get_instance()->begin_captcha_verified_comment_request();
|
|
}
|
|
try {
|
|
$comment_id = wp_new_comment(wp_slash($commentdata), true);
|
|
} finally {
|
|
if (class_exists('\AKSRT\Auth\Moderation')) {
|
|
\AKSRT\Auth\Moderation::get_instance()->end_captcha_verified_comment_request();
|
|
}
|
|
}
|
|
if (is_wp_error($comment_id)) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => $comment_id->get_error_code() ?: 'submit_failed',
|
|
'message' => $comment_id->get_error_message() ?: __('评论提交失败。', 'aksrt'),
|
|
], 400);
|
|
}
|
|
|
|
$comment = get_comment((int) $comment_id);
|
|
if (!$comment) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'submit_failed',
|
|
'message' => __('评论提交失败。', 'aksrt'),
|
|
], 500);
|
|
}
|
|
|
|
$settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_comment_display_settings() : [];
|
|
$html = function_exists('aksrt_comments_render_single_html')
|
|
? aksrt_comments_render_single_html($comment, $settings)
|
|
: '';
|
|
|
|
$needs_moderation = '0' === (string) $comment->comment_approved;
|
|
$wait_time = 0;
|
|
|
|
return new \WP_REST_Response([
|
|
'success' => true,
|
|
'code' => 'submitted',
|
|
'message' => $needs_moderation ? __('评论已提交,等待管理员审核', 'aksrt') : __('评论发布成功', 'aksrt'),
|
|
'html' => $html,
|
|
'is_reply'=> $parent > 0,
|
|
'parent_id' => $parent,
|
|
'needs_moderation' => $needs_moderation,
|
|
'wait_time' => $wait_time,
|
|
'data' => [
|
|
'comment_id' => (int) $comment_id,
|
|
'approved' => (string) $comment->comment_approved,
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Edit comment content
|
|
*/
|
|
public function edit_comment(\WP_REST_Request $request): \WP_REST_Response {
|
|
$comment_id = $request->get_param('comment_id');
|
|
$content = $request->get_param('content');
|
|
|
|
$comment = get_comment($comment_id);
|
|
if (!$comment) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'comment_not_found',
|
|
'message' => __('评论不存在。', 'aksrt'),
|
|
], 404);
|
|
}
|
|
|
|
// Sanitize with wp_kses (allow basic HTML)
|
|
$allowed_html = [
|
|
'a' => ['href' => [], 'title' => [], 'target' => []],
|
|
'code' => [],
|
|
'pre' => [],
|
|
'strong' => [],
|
|
'em' => [],
|
|
'br' => [],
|
|
'p' => [],
|
|
];
|
|
$clean_content = wp_kses($content, $allowed_html);
|
|
|
|
$updated = wp_update_comment([
|
|
'comment_ID' => $comment_id,
|
|
'comment_content' => $clean_content,
|
|
]);
|
|
|
|
if (is_wp_error($updated)) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'update_failed',
|
|
'message' => __('更新失败。', 'aksrt'),
|
|
], 500);
|
|
}
|
|
|
|
$rendered = function_exists('aksrt_render_comment_content')
|
|
? aksrt_render_comment_content($clean_content)
|
|
: wpautop($clean_content);
|
|
|
|
return new \WP_REST_Response([
|
|
'success' => true,
|
|
'code' => 'updated',
|
|
'message' => __('评论已更新。', 'aksrt'),
|
|
'data' => [
|
|
'content' => $rendered,
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Delete comment
|
|
*/
|
|
public function delete_comment(\WP_REST_Request $request): \WP_REST_Response {
|
|
$comment_id = $request->get_param('comment_id');
|
|
|
|
$comment = get_comment($comment_id);
|
|
if (!$comment) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'comment_not_found',
|
|
'message' => __('评论不存在。', 'aksrt'),
|
|
], 404);
|
|
}
|
|
|
|
$deleted = wp_delete_comment($comment_id, false); // soft delete
|
|
if (!$deleted) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'delete_failed',
|
|
'message' => __('删除失败。', 'aksrt'),
|
|
], 500);
|
|
}
|
|
|
|
return new \WP_REST_Response([
|
|
'success' => true,
|
|
'code' => 'deleted',
|
|
'message' => __('评论已删除。', 'aksrt'),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Moderate comment (approve / hold / spam)
|
|
*/
|
|
public function moderate_comment(\WP_REST_Request $request): \WP_REST_Response {
|
|
$comment_id = $request->get_param('comment_id');
|
|
$status = $request->get_param('status');
|
|
|
|
$allowed_statuses = ['approve', 'hold', 'spam'];
|
|
if (!in_array($status, $allowed_statuses, true)) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'invalid_status',
|
|
'message' => __('无效状态。', 'aksrt'),
|
|
], 400);
|
|
}
|
|
|
|
$comment = get_comment($comment_id);
|
|
if (!$comment) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'comment_not_found',
|
|
'message' => __('评论不存在。', 'aksrt'),
|
|
], 404);
|
|
}
|
|
|
|
$status_map = [
|
|
'approve' => 'approved',
|
|
'hold' => 'hold',
|
|
'spam' => 'spam',
|
|
];
|
|
|
|
$result = wp_set_comment_status($comment_id, $status_map[$status]);
|
|
if (is_wp_error($result)) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'moderate_failed',
|
|
'message' => __('操作失败。', 'aksrt'),
|
|
], 500);
|
|
}
|
|
|
|
return new \WP_REST_Response([
|
|
'success' => true,
|
|
'code' => 'moderated',
|
|
'message' => __('操作成功。', 'aksrt'),
|
|
'data' => [
|
|
'status' => $status_map[$status],
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Toggle a comment's pinned ("置顶") state. Top-level comments only.
|
|
*/
|
|
public function pin_comment(\WP_REST_Request $request): \WP_REST_Response {
|
|
$comment_id = (int) $request->get_param('comment_id');
|
|
$comment = get_comment($comment_id);
|
|
if (!$comment) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'comment_not_found',
|
|
'message' => __('评论不存在。', 'aksrt'),
|
|
], 404);
|
|
}
|
|
|
|
if ((int) $comment->comment_parent !== 0) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'cannot_pin_reply',
|
|
'message' => __('仅顶层评论可置顶。', 'aksrt'),
|
|
], 400);
|
|
}
|
|
|
|
$current = '1' === (string) get_comment_meta($comment_id, '_aksrt_comment_pinned', true);
|
|
$target = null !== $request->get_param('pinned')
|
|
? (bool) $request->get_param('pinned')
|
|
: !$current;
|
|
|
|
if ($target) {
|
|
update_comment_meta($comment_id, '_aksrt_comment_pinned', '1');
|
|
} else {
|
|
delete_comment_meta($comment_id, '_aksrt_comment_pinned');
|
|
}
|
|
|
|
return new \WP_REST_Response([
|
|
'success' => true,
|
|
'code' => 'pinned',
|
|
'message' => $target ? __('评论已置顶。', 'aksrt') : __('已取消置顶。', 'aksrt'),
|
|
'data' => [
|
|
'pinned' => $target,
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Toggle the current visitor's like on a comment.
|
|
*/
|
|
public function like_comment(\WP_REST_Request $request): \WP_REST_Response {
|
|
$comment_id = (int) $request->get_param('comment_id');
|
|
$comment = get_comment($comment_id);
|
|
if (!$comment || '1' !== (string) $comment->comment_approved) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'comment_unavailable',
|
|
'message' => __('评论不存在或未通过审核。', 'aksrt'),
|
|
], 404);
|
|
}
|
|
|
|
if (!function_exists('aksrt_is_comment_liked') || !function_exists('aksrt_set_comment_like_state') || !function_exists('aksrt_update_comment_counter')) {
|
|
return new \WP_REST_Response([
|
|
'success' => false,
|
|
'code' => 'like_unavailable',
|
|
'message' => __('点赞功能不可用。', 'aksrt'),
|
|
], 500);
|
|
}
|
|
|
|
$current = aksrt_is_comment_liked($comment_id);
|
|
$target = null !== $request->get_param('active')
|
|
? (bool) $request->get_param('active')
|
|
: !$current;
|
|
|
|
if ($target !== $current) {
|
|
aksrt_set_comment_like_state($comment_id, $target);
|
|
$count = aksrt_update_comment_counter($comment_id, 'aksrt_comment_likes', $target ? 1 : -1);
|
|
if (is_user_logged_in()) {
|
|
do_action('aksrt_comment_liked', $comment_id, get_current_user_id(), (bool) $target);
|
|
}
|
|
} else {
|
|
$count = aksrt_get_comment_likes($comment_id);
|
|
}
|
|
|
|
return new \WP_REST_Response([
|
|
'success' => true,
|
|
'code' => 'liked',
|
|
'data' => [
|
|
'active' => $target,
|
|
'count' => $count,
|
|
],
|
|
]);
|
|
}
|
|
}
|