Wire paid plate follow (admin meta + points/balance purchase + AJAX), re-check plate gate on topics, post list sales column, and order type subtabs; update gap matrix and admin IA map.
175 lines
6.0 KiB
PHP
175 lines
6.0 KiB
PHP
<?php
|
|
defined('ABSPATH') || exit;
|
|
|
|
trait AKSRT_Forum_Board_Service_Part_3 {
|
|
|
|
|
|
/**
|
|
* Check if a user is a plate_cat moderator (分区版主).
|
|
*/
|
|
public function is_cat_moderator(int $user_id, int $cat_id): bool {
|
|
if ($user_id <= 0) {
|
|
return false;
|
|
}
|
|
if ($this->forum->is_forum_admin($user_id)) {
|
|
return true;
|
|
}
|
|
$moderator_ids = get_term_meta($cat_id, '_aksrt_cat_moderator', true);
|
|
if (!is_array($moderator_ids)) {
|
|
return false;
|
|
}
|
|
return in_array($user_id, array_map('intval', $moderator_ids), true);
|
|
}
|
|
|
|
/**
|
|
* Get plates sorted by a specified dimension (§7.2 多维排序).
|
|
*/
|
|
public function get_sorted_plates(string $orderby = 'menu_order', string $order = 'ASC', int $limit = 50): array {
|
|
$allowed = [
|
|
'name' => 'title',
|
|
'date' => 'date',
|
|
'modified' => 'modified',
|
|
'menu_order' => 'menu_order',
|
|
'last_post' => '_aksrt_last_post',
|
|
'last_reply' => '_aksrt_last_reply',
|
|
'posts_count' => '_aksrt_posts_count',
|
|
'reply_count' => '_aksrt_reply_count',
|
|
'today_reply_count' => '_aksrt_today_reply_count',
|
|
'views' => '_aksrt_views',
|
|
'follow_count' => '_aksrt_follow_count',
|
|
'rand' => 'rand',
|
|
];
|
|
|
|
$query_args = [
|
|
'post_type' => 'aksrt_forum_plate',
|
|
'post_status' => 'publish',
|
|
'posts_per_page' => $limit,
|
|
'order' => strtoupper($order) === 'ASC' ? 'ASC' : 'DESC',
|
|
];
|
|
|
|
if (isset($allowed[$orderby])) {
|
|
$meta_key = $allowed[$orderby];
|
|
if (str_starts_with($meta_key, '_aksrt_')) {
|
|
$query_args['orderby'] = 'meta_value_num';
|
|
$query_args['meta_key'] = $meta_key;
|
|
} else {
|
|
$query_args['orderby'] = $meta_key;
|
|
}
|
|
} else {
|
|
$query_args['orderby'] = 'menu_order';
|
|
}
|
|
|
|
$posts = get_posts($query_args);
|
|
$plates = [];
|
|
foreach ($posts as $post) {
|
|
$plates[] = $this->build_plate_payload($post);
|
|
}
|
|
return $plates;
|
|
}
|
|
|
|
public function maybe_migrate_boards(): void {
|
|
if (get_option('aksrt_forum_boards_migrated')) {
|
|
return;
|
|
}
|
|
|
|
$old_boards = get_option('aksrt_forum_boards', []);
|
|
if (!is_array($old_boards) || empty($old_boards)) {
|
|
update_option('aksrt_forum_boards_migrated', time());
|
|
return;
|
|
}
|
|
|
|
foreach ($old_boards as $board) {
|
|
$name = sanitize_text_field((string) ($board['name'] ?? ''));
|
|
if ($name === '') {
|
|
continue;
|
|
}
|
|
|
|
$existing = get_terms([
|
|
'taxonomy' => 'aksrt_forum_board',
|
|
'name' => $name,
|
|
'hide_empty' => false,
|
|
'fields' => 'ids',
|
|
]);
|
|
|
|
if (!is_wp_error($existing) && !empty($existing)) {
|
|
$term_id = (int) $existing[0];
|
|
} else {
|
|
$result = wp_insert_term($name, 'aksrt_forum_board', [
|
|
'description' => sanitize_textarea_field((string) ($board['description'] ?? '')),
|
|
]);
|
|
if (is_wp_error($result)) {
|
|
continue;
|
|
}
|
|
$term_id = (int) $result['term_id'];
|
|
}
|
|
|
|
$icon = sanitize_text_field((string) ($board['icon'] ?? ''));
|
|
if ($icon !== '') {
|
|
update_term_meta($term_id, '_aksrt_icon', $icon);
|
|
}
|
|
|
|
update_term_meta($term_id, '_aksrt_sort_order', (int) ($board['sort_order'] ?? $term_id));
|
|
|
|
if (!empty($board['moderators']) && is_array($board['moderators'])) {
|
|
update_term_meta($term_id, '_aksrt_moderators', array_map('intval', $board['moderators']));
|
|
}
|
|
}
|
|
|
|
update_option('aksrt_forum_boards_migrated', time());
|
|
}
|
|
|
|
public function ajax_follow_plate(): void {
|
|
check_ajax_referer('aksrt_forum_action', '_nonce');
|
|
|
|
$user_id = get_current_user_id();
|
|
if ($user_id <= 0) {
|
|
wp_send_json_error(['message' => __('请先登录', 'aksrt')]);
|
|
}
|
|
|
|
$plate_id = (int) ($_POST['plate_id'] ?? 0);
|
|
if ($plate_id <= 0) {
|
|
wp_send_json_error(['message' => __('版块不存在', 'aksrt')]);
|
|
}
|
|
|
|
$result = $this->toggle_follow_plate($user_id, $plate_id);
|
|
if (!empty($result['require_pay'])) {
|
|
wp_send_json_error([
|
|
'code' => 'require_pay',
|
|
'message' => (string) ($result['message'] ?? __('需要付费关注', 'aksrt')),
|
|
'require_pay' => true,
|
|
'pay' => $result['pay'] ?? [],
|
|
'followed' => false,
|
|
'follow_count' => (int) ($result['follow_count'] ?? 0),
|
|
]);
|
|
}
|
|
if (isset($result['success']) && $result['success'] === false) {
|
|
wp_send_json_error([
|
|
'message' => (string) ($result['message'] ?? __('操作失败', 'aksrt')),
|
|
]);
|
|
}
|
|
wp_send_json_success($result);
|
|
}
|
|
|
|
public function ajax_purchase_plate_follow(): void {
|
|
check_ajax_referer('aksrt_forum_action', '_nonce');
|
|
|
|
$user_id = get_current_user_id();
|
|
if ($user_id <= 0) {
|
|
wp_send_json_error(['message' => __('请先登录', 'aksrt')]);
|
|
}
|
|
|
|
$plate_id = (int) ($_POST['plate_id'] ?? 0);
|
|
if ($plate_id <= 0) {
|
|
wp_send_json_error(['message' => __('版块不存在', 'aksrt')]);
|
|
}
|
|
|
|
$result = $this->purchase_plate_follow($user_id, $plate_id);
|
|
if (empty($result['success'])) {
|
|
wp_send_json_error([
|
|
'message' => (string) ($result['message'] ?? __('支付失败', 'aksrt')),
|
|
]);
|
|
}
|
|
wp_send_json_success($result);
|
|
}
|
|
}
|