Files
wordpress-theme-aksrt/inc/classes/admin/class-aksrt-admin-forum-controller.php
T

412 lines
15 KiB
PHP

<?php
/**
* Forum REST controller.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
class AKSRT_Admin_Forum_Controller extends AKSRT_Admin_Controller_Base {
use AKSRT_Admin_Forum_Controller_Part_1;
use AKSRT_Admin_Forum_Controller_Part_2;
private static $instance = null;
private $admin;
public static function get_instance(): self {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
public function set_admin(AKSRT_Admin $admin): void {
$this->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<id>\d+)', [
'methods' => 'POST',
'callback' => [$this, 'update_board'],
'permission_callback' => [$this, 'check_permission'],
]);
register_rest_route(self::API_NAMESPACE, '/forum/boards/(?P<id>\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<id>\d+)', [
'methods' => 'GET',
'callback' => [$this, 'get_topic_detail'],
'permission_callback' => [$this, 'check_permission'],
]);
register_rest_route(self::API_NAMESPACE, '/forum/topics/(?P<id>\d+)/moderate', [
'methods' => 'POST',
'callback' => [$this, 'moderate_topic'],
'permission_callback' => [$this, 'check_logged_in_permission'],
]);
register_rest_route(self::API_NAMESPACE, '/forum/topics/(?P<id>\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<id>[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<id>\d+)/favorite', [
'methods' => 'POST',
'callback' => [$this, 'toggle_favorite'],
'permission_callback' => [$this, 'check_logged_in_permission'],
]);
register_rest_route(self::API_NAMESPACE, '/forum/topics/(?P<id>\d+)/score', [
'methods' => 'POST',
'callback' => [$this, 'score_topic'],
'permission_callback' => [$this, 'check_logged_in_permission'],
]);
register_rest_route(self::API_NAMESPACE, '/forum/topics/(?P<id>\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<id>\d+)', [
'methods' => 'GET',
'callback' => [$this, 'get_plate'],
'permission_callback' => [$this, 'check_permission'],
]);
register_rest_route(self::API_NAMESPACE, '/forum/plates/(?P<id>\d+)', [
'methods' => 'POST',
'callback' => [$this, 'update_plate'],
'permission_callback' => [$this, 'check_permission'],
]);
register_rest_route(self::API_NAMESPACE, '/forum/plates/(?P<id>\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<id>\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<id>\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<id>\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);
}
}