admin = $admin; } public function register_routes(): void { register_rest_route(self::API_NAMESPACE, '/forum/overview', [ 'methods' => 'GET', 'callback' => [$this, 'get_overview'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/boards', [ 'methods' => 'GET', 'callback' => [$this, 'get_boards'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/boards', [ 'methods' => 'POST', 'callback' => [$this, 'create_board'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/boards/(?P\d+)', [ 'methods' => 'POST', 'callback' => [$this, 'update_board'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/boards/(?P\d+)', [ 'methods' => 'DELETE', 'callback' => [$this, 'delete_board'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/boards/reorder', [ 'methods' => 'POST', 'callback' => [$this, 'reorder_boards'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/topics', [ 'methods' => 'GET', 'callback' => [$this, 'get_topics'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/topics/(?P\d+)', [ 'methods' => 'GET', 'callback' => [$this, 'get_topic_detail'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/topics/(?P\d+)/moderate', [ 'methods' => 'POST', 'callback' => [$this, 'moderate_topic'], 'permission_callback' => [$this, 'check_logged_in_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/topics/(?P\d+)/vote', [ 'methods' => 'POST', 'callback' => [$this, 'vote_topic'], 'permission_callback' => [$this, 'check_logged_in_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/update-topic', [ 'methods' => 'POST', 'callback' => [$this, 'update_topic_legacy'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/moderators', [ 'methods' => 'GET', 'callback' => [$this, 'get_moderators'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/moderators', [ 'methods' => 'POST', 'callback' => [$this, 'update_moderators'], 'permission_callback' => [$this, 'check_permission'], ]); // Change moderator role register_rest_route(self::API_NAMESPACE, '/forum/moderators/role', [ 'methods' => 'POST', 'callback' => [$this, 'change_moderator_role'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/moderator/apply', [ 'methods' => 'POST', 'callback' => [$this, 'apply_moderator'], 'permission_callback' => [$this, 'check_logged_in_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/moderator/applications', [ 'methods' => 'GET', 'callback' => [$this, 'get_moderator_applications'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/moderator/applications/(?P[A-Za-z0-9-]+)/review', [ 'methods' => 'POST', 'callback' => [$this, 'review_moderator_application'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/topics/(?P\d+)/favorite', [ 'methods' => 'POST', 'callback' => [$this, 'toggle_favorite'], 'permission_callback' => [$this, 'check_logged_in_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/topics/(?P\d+)/score', [ 'methods' => 'POST', 'callback' => [$this, 'score_topic'], 'permission_callback' => [$this, 'check_logged_in_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/topics/(?P\d+)/adopt', [ 'methods' => 'POST', 'callback' => [$this, 'adopt_answer'], 'permission_callback' => [$this, 'check_logged_in_permission'], ]); // §7.0 Plate CPT endpoints register_rest_route(self::API_NAMESPACE, '/forum/plates', [ 'methods' => 'GET', 'callback' => [$this, 'get_plates'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/plates', [ 'methods' => 'POST', 'callback' => [$this, 'create_plate'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/plates/(?P\d+)', [ 'methods' => 'GET', 'callback' => [$this, 'get_plate'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/plates/(?P\d+)', [ 'methods' => 'POST', 'callback' => [$this, 'update_plate'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/plates/(?P\d+)', [ 'methods' => 'DELETE', 'callback' => [$this, 'delete_plate'], 'permission_callback' => [$this, 'check_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/plates/reorder', [ 'methods' => 'POST', 'callback' => [$this, 'reorder_plates'], 'permission_callback' => [$this, 'check_permission'], ]); // §7.2 Follow plate register_rest_route(self::API_NAMESPACE, '/forum/plates/(?P\d+)/follow', [ 'methods' => 'POST', 'callback' => [$this, 'toggle_follow_plate'], 'permission_callback' => [$this, 'check_logged_in_permission'], ]); // §7.2 Plate categories (分区) register_rest_route(self::API_NAMESPACE, '/forum/plate-categories', [ 'methods' => 'GET', 'callback' => [$this, 'get_plate_categories'], 'permission_callback' => [$this, 'check_permission'], ]); // §7.2 Sorted plates register_rest_route(self::API_NAMESPACE, '/forum/plates/sorted', [ 'methods' => 'GET', 'callback' => [$this, 'get_sorted_plates'], 'permission_callback' => '__return_true', ]); // §7.2 Front-end plate CRUD (forum admin/moderator) register_rest_route(self::API_NAMESPACE, '/forum/front/plates', [ 'methods' => 'POST', 'callback' => [$this, 'frontend_create_plate'], 'permission_callback' => [$this, 'check_logged_in_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/front/plates/(?P\d+)', [ 'methods' => 'POST', 'callback' => [$this, 'frontend_update_plate'], 'permission_callback' => [$this, 'check_logged_in_permission'], ]); register_rest_route(self::API_NAMESPACE, '/forum/front/plates/(?P\d+)', [ 'methods' => 'DELETE', 'callback' => [$this, 'frontend_delete_plate'], 'permission_callback' => [$this, 'check_logged_in_permission'], ]); } public function get_overview(): WP_REST_Response { $forum = $this->get_forum_service(); if (!$forum) { return $this->success(['data' => ['stats' => [], 'boards' => [], 'recent_topics' => [], 'pending_applications' => []]]); } $pending_topics = $forum->get_topic_list([ 'limit' => 6, 'status' => 'pending', 'review_status' => AKSRT_Forum::REVIEW_PENDING, 'viewer_user_id' => get_current_user_id(), 'include_hidden' => true, ]); return $this->success([ 'data' => [ 'stats' => $forum->get_stats(), 'boards' => array_slice($forum->get_boards(), 0, 6), 'pending_topics' => $pending_topics['items'], 'pending_applications' => array_slice($forum->get_moderator_application_list(['status' => AKSRT_Forum::APPLICATION_PENDING]), 0, 6), ], ]); } public function get_boards(): WP_REST_Response { $forum = $this->get_forum_service(); $items = $forum ? $forum->get_boards() : []; return $this->success([ 'data' => [ 'items' => $items, 'total' => count($items), ], ]); } public function create_board(WP_REST_Request $request): WP_REST_Response { $forum = $this->get_forum_service(); if (!$forum) { return $this->error(__('论坛系统未启用', 'aksrt')); } $params = $this->get_json_params($request); $name = sanitize_text_field((string) ($params['name'] ?? '')); if ($name === '') { return $this->error(__('版块名称不能为空', 'aksrt')); } $term_id = $forum->create_board($params); if ($term_id <= 0) { return $this->error(__('创建版块失败', 'aksrt')); } return $this->success([ 'message' => __('版块已创建', 'aksrt'), 'data' => ['id' => $term_id], ], 201); } public function update_board(WP_REST_Request $request): WP_REST_Response { $forum = $this->get_forum_service(); if (!$forum) { return $this->error(__('论坛系统未启用', 'aksrt')); } $board_id = (int) $request->get_param('id'); if ($board_id <= 0) { return $this->error(__('参数无效', 'aksrt')); } $success = $forum->update_board($board_id, $this->get_json_params($request)); if (!$success) { return $this->error(__('版块更新失败', 'aksrt')); } return $this->success(['message' => __('版块已更新', 'aksrt')]); } public function delete_board(WP_REST_Request $request): WP_REST_Response { $forum = $this->get_forum_service(); if (!$forum) { return $this->error(__('论坛系统未启用', 'aksrt')); } $board_id = (int) $request->get_param('id'); if ($board_id <= 0) { return $this->error(__('参数无效', 'aksrt')); } $success = $forum->delete_board($board_id); if (!$success) { return $this->error(__('版块删除失败', 'aksrt')); } return $this->success(['message' => __('版块已删除', 'aksrt')]); } public function reorder_boards(WP_REST_Request $request): WP_REST_Response { $forum = $this->get_forum_service(); if (!$forum) { return $this->error(__('论坛系统未启用', 'aksrt')); } $params = $this->get_json_params($request); $order = $params['order'] ?? []; if (!is_array($order) || empty($order)) { return $this->error(__('排序参数无效', 'aksrt')); } $forum->reorder_boards($order); return $this->success(['message' => __('排序已更新', 'aksrt')]); } // ================================================================ // §7.0 Plate CPT handlers // ================================================================ public function get_plates(WP_REST_Request $request): WP_REST_Response { $forum = $this->get_forum_service(); if (!$forum) { return $this->success(['data' => ['items' => [], 'total' => 0]]); } $args = []; $parent = $request->get_param('parent'); if ($parent !== null) { $args['parent'] = (int) $parent; } $plate_cat = $request->get_param('plate_cat'); if ($plate_cat) { $args['plate_cat'] = (int) $plate_cat; } $items = $forum->get_plates($args); return $this->success([ 'data' => [ 'items' => $items, 'total' => count($items), ], ]); } public function get_plate(WP_REST_Request $request): WP_REST_Response { $forum = $this->get_forum_service(); if (!$forum) { return $this->error(__('论坛系统未启用', 'aksrt')); } $plate_id = (int) $request->get_param('id'); $plate = $forum->get_plate($plate_id); if (!$plate) { return $this->error(__('版块不存在', 'aksrt'), 404); } return $this->success(['data' => $plate]); } public function create_plate(WP_REST_Request $request): WP_REST_Response { $forum = $this->get_forum_service(); if (!$forum) { return $this->error(__('论坛系统未启用', 'aksrt')); } $params = $this->get_json_params($request); $name = sanitize_text_field((string) ($params['name'] ?? '')); if ($name === '') { return $this->error(__('版块名称不能为空', 'aksrt')); } $plate_id = $forum->create_plate($params); if ($plate_id <= 0) { return $this->error(__('创建版块失败', 'aksrt')); } return $this->success([ 'message' => __('版块已创建', 'aksrt'), 'data' => ['id' => $plate_id], ], 201); } }