refactor(badges): use modal REST routes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-05 00:16:39 +08:00
co-authored by Claude Fable 5
parent 34150f3358
commit 25ce1d8f43
2 changed files with 51 additions and 41 deletions
+49 -39
View File
@@ -30,11 +30,6 @@ class Badges {
public function init(): void {
add_action('rest_api_init', [$this, 'register_routes']);
add_action('aksrt_badge_granted', [$this, 'on_badge_granted_notify'], 10, 3);
// HTML modal for modal runtime (zibll user_medal_info_modal).
add_action('wp_ajax_aksrt_user_badge_info_modal', [$this, 'ajax_info_modal']);
add_action('wp_ajax_nopriv_aksrt_user_badge_info_modal', [$this, 'ajax_info_modal']);
add_action('wp_ajax_aksrt_single_badge_info_modal', [$this, 'ajax_single_info_modal']);
add_action('wp_ajax_nopriv_aksrt_single_badge_info_modal', [$this, 'ajax_single_info_modal']);
}
/**
@@ -71,39 +66,32 @@ class Badges {
}
/**
* AJAX: full badge list modal HTML.
* REST response for the badge list modal.
*/
public function ajax_info_modal(): void {
$user_id = max(0, (int) ($_REQUEST['id'] ?? $_REQUEST['user_id'] ?? 0)); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ($user_id <= 0) {
$user_id = get_current_user_id();
}
public function rest_modal_list(\WP_REST_Request $request) {
$user_id = absint($request->get_param('id'));
if ($user_id <= 0 || !get_userdata($user_id)) {
wp_send_json_error(['message' => __('用户不存在', 'aksrt')], 404);
return new \WP_Error('aksrt_badge_user_missing', __('用户不存在', 'aksrt'), ['status' => 404]);
}
$html = self::render_info_modal_html($user_id);
wp_send_json_success(['html' => $html]);
return new \WP_REST_Response(['html' => self::render_info_modal_html($user_id)], 200);
}
/**
* AJAX: single badge detail modal.
* REST response for a single badge modal.
*/
public function ajax_single_info_modal(): void {
$slug = sanitize_key((string) ($_REQUEST['name'] ?? $_REQUEST['slug'] ?? '')); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$user_id = max(0, (int) ($_REQUEST['user_id'] ?? $_REQUEST['id'] ?? 0)); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
public function rest_modal_single(\WP_REST_Request $request) {
$slug = sanitize_key((string) $request->get_param('slug'));
$user_id = absint($request->get_param('id'));
if ($slug === '') {
wp_send_json_error(['message' => __('徽章不存在', 'aksrt')], 404);
return new \WP_Error('aksrt_badge_missing', __('徽章不存在', 'aksrt'), ['status' => 404]);
}
$html = self::render_single_modal_html($slug, $user_id);
wp_send_json_success(['html' => $html]);
return new \WP_REST_Response(['html' => self::render_single_modal_html($slug, $user_id)], 200);
}
/**
* Badge list modal HTML (zibll zib_get_user_medal_info_modal parity).
* Badge list modal HTML.
*
* Head (avatar + owner + worn medal) + category-grouped medal card grid.
* Each card deep-links into the single badge modal via the modal runtime
* contract (data-aksrt-modal="remote" + data-aksrt-modal-url).
* Head (avatar + owner + worn medal) and category-grouped medal card grid.
*/
public static function render_info_modal_html(int $user_id): string {
$user = get_userdata($user_id);
@@ -162,7 +150,7 @@ class Badges {
// Footer: quick jump to my own badges while browsing someone else (zibll).
if (!$is_self && $current > 0) {
$my_url = add_query_arg(['action' => 'aksrt_user_badge_info_modal', 'id' => $current], admin_url('admin-ajax.php'));
$my_url = rest_url('aksrt/v1/users/' . $current . '/badges/modal');
$html .= '<div class="medal-modal__buts">';
$html .= '<a class="but c-blue" href="' . esc_url($my_url) . '" data-aksrt-modal="remote" data-aksrt-modal-url="' . esc_url($my_url) . '" data-aksrt-modal-class="full-sm" data-aksrt-modal-mobile-bottom="true"><i class="fas fa-medal" aria-hidden="true"></i> ' . esc_html__('查看我的徽章', 'aksrt') . '</a>';
$html .= '</div>';
@@ -199,10 +187,7 @@ class Badges {
}
$card .= '</div>';
$url = add_query_arg(
['action' => 'aksrt_single_badge_info_modal', 'name' => $slug, 'user_id' => $user_id],
admin_url('admin-ajax.php')
);
$url = rest_url('aksrt/v1/users/' . $user_id . '/badges/' . rawurlencode($slug) . '/modal');
return '<a class="medal-list" href="' . esc_url($url) . '" data-aksrt-modal="remote" data-aksrt-modal-url="' . esc_url($url) . '" data-aksrt-modal-class="modal-mini" data-aksrt-modal-mobile-bottom="true">' . $card . '</a>';
}
@@ -262,7 +247,7 @@ class Badges {
// Back to the full badge list modal.
if ($user_id > 0) {
$back_url = add_query_arg(['action' => 'aksrt_user_badge_info_modal', 'id' => $user_id], admin_url('admin-ajax.php'));
$back_url = rest_url('aksrt/v1/users/' . $user_id . '/badges/modal');
$html .= '<a class="medal-modal__back muted-2-color em09" href="' . esc_url($back_url) . '" data-aksrt-modal="remote" data-aksrt-modal-url="' . esc_url($back_url) . '" data-aksrt-modal-class="full-sm" data-aksrt-modal-mobile-bottom="true"><i class="fas fa-angle-left" aria-hidden="true"></i> ' . esc_html__('返回徽章列表', 'aksrt') . '</a>';
}
@@ -271,7 +256,7 @@ class Badges {
}
/**
* Remote-modal trigger for a user's badge list (zibll zib_get_user_medal_info_link).
* Declarative modal runtime trigger for a user's badge list.
*/
public static function get_info_link(int $user_id, string $class = '', ?string $text = null): string {
if ($user_id <= 0 || !self::enabled()) {
@@ -283,13 +268,7 @@ class Badges {
if (!function_exists('aksrt_get_modal_link')) {
return '';
}
$url = add_query_arg(
[
'action' => 'aksrt_user_badge_info_modal',
'id' => $user_id,
],
admin_url('admin-ajax.php')
);
$url = rest_url('aksrt/v1/users/' . $user_id . '/badges/modal');
return aksrt_get_modal_link([
'tag' => 'a',
'class' => trim('user-medal-info ' . $class),
@@ -315,6 +294,37 @@ class Badges {
],
]);
register_rest_route('aksrt/v1', '/users/(?P<id>\d+)/badges/modal', [
'methods' => 'GET',
'callback' => [$this, 'rest_modal_list'],
'permission_callback' => '__return_true',
'args' => [
'id' => [
'type' => 'integer',
'required' => true,
'sanitize_callback' => 'absint',
],
],
]);
register_rest_route('aksrt/v1', '/users/(?P<id>\d+)/badges/(?P<slug>[a-z0-9_-]+)/modal', [
'methods' => 'GET',
'callback' => [$this, 'rest_modal_single'],
'permission_callback' => '__return_true',
'args' => [
'id' => [
'type' => 'integer',
'required' => true,
'sanitize_callback' => 'absint',
],
'slug' => [
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_key',
],
],
]);
register_rest_route('aksrt/v1', '/users/me/badges/wear', [
'methods' => 'POST',
'callback' => [$this, 'rest_wear'],