412 lines
15 KiB
PHP
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);
|
|
}
|
|
|
|
}
|