refactor: flatten src/AKSRT → src (drop theme-identifier dir)
Move all domain folders from src/AKSRT/{Domain} to src/{Domain}; remap
Composer PSR-4 "AKSRT\\": "src/"; update audit script + README + ADR
paths; remove dead tools/build-psr4-map.php (scanned deleted inc/classes).
This commit is contained in:
@@ -0,0 +1,747 @@
|
||||
<?php
|
||||
/**
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
namespace AKSRT\Admin;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class UserController extends ControllerBase {
|
||||
use UserControllerReportOperations;
|
||||
use UserControllerInviteOperations;
|
||||
use UserControllerVerifyIntegrations;
|
||||
use UserControllerIdentitySettings;
|
||||
use UserControllerAuthPhoneOperations;
|
||||
use UserControllerRestrictionOperations;
|
||||
use UserControllerFollowOperations;
|
||||
use UserControllerProfileMediaOperations;
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
public static function get_instance(): self {
|
||||
if (null === self::$instance) self::$instance = new self();
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function register_routes(): void {
|
||||
// Auth settings (login/registration)
|
||||
register_rest_route(self::API_NAMESPACE, '/settings/auth', [
|
||||
'methods' => ['GET', 'POST'],
|
||||
'callback' => [$this, 'rest_handle_auth_settings'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// OAuth settings
|
||||
register_rest_route(self::API_NAMESPACE, '/settings/oauth', [
|
||||
'methods' => ['GET', 'POST'],
|
||||
'callback' => [$this, 'rest_handle_oauth'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// OAuth proxy settings
|
||||
register_rest_route(self::API_NAMESPACE, '/settings/oauth-proxy', [
|
||||
'methods' => ['GET', 'POST'],
|
||||
'callback' => [$this, 'rest_handle_oauth_proxy'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// User profile media uploads (logged-in users).
|
||||
register_rest_route(self::API_NAMESPACE, '/user/background', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'rest_upload_user_background'],
|
||||
'permission_callback' => function () { return is_user_logged_in(); },
|
||||
]);
|
||||
register_rest_route(self::API_NAMESPACE, '/user/avatar', [
|
||||
[
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'rest_upload_user_avatar'],
|
||||
'permission_callback' => function () { return is_user_logged_in(); },
|
||||
],
|
||||
[
|
||||
'methods' => 'DELETE',
|
||||
'callback' => [$this, 'rest_delete_user_avatar'],
|
||||
'permission_callback' => function () { return is_user_logged_in(); },
|
||||
],
|
||||
]);
|
||||
|
||||
// Comment inline image upload (logged-in users)
|
||||
register_rest_route(self::API_NAMESPACE, '/comment/upload-image', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'rest_upload_comment_image'],
|
||||
'permission_callback' => function () { return is_user_logged_in(); },
|
||||
]);
|
||||
|
||||
// Notification settings
|
||||
register_rest_route(self::API_NAMESPACE, '/settings/notifications', [
|
||||
'methods' => ['GET', 'POST'],
|
||||
'callback' => [$this, 'rest_handle_notification_settings'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Keep message-center aliases on this controller so existing admin pages
|
||||
// remain compatible while notifications runtime lives in Message controller.
|
||||
register_rest_route(self::API_NAMESPACE, '/notifications/overview', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'rest_get_notification_overview'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
register_rest_route(self::API_NAMESPACE, '/notifications/mark-read', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'rest_mark_notification_read'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
register_rest_route(self::API_NAMESPACE, '/notifications/(?P<id>\d+)', [
|
||||
'methods' => 'DELETE',
|
||||
'callback' => [$this, 'rest_delete_notification_item'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
register_rest_route(self::API_NAMESPACE, '/notifications/cleanup', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'rest_run_notification_cleanup'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Mail templates (email content templates)
|
||||
register_rest_route(self::API_NAMESPACE, '/settings/mail-templates', [
|
||||
'methods' => ['GET', 'POST'],
|
||||
'callback' => [$this, 'handle_mail_templates'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Credits settings (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/credits/settings', [
|
||||
'methods' => ['GET', 'POST'],
|
||||
'callback' => [$this, 'rest_handle_credit_settings'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Credits — current user balance (frontend)
|
||||
register_rest_route(self::API_NAMESPACE, '/credits/me', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'rest_get_credits_me'],
|
||||
'permission_callback' => function () { return is_user_logged_in(); },
|
||||
]);
|
||||
|
||||
// Credits — user list (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/credits/users', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'rest_list_credit_users'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Credits — adjust user balance (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/credits/users/(?P<id>\d+)/adjust', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'rest_adjust_user_credits'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Credits — transaction log (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/credits/log', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'rest_get_credits_log'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Report ticket list (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/report/list', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_report_list'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
register_rest_route(self::API_NAMESPACE, '/users/reports', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_report_list'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
register_rest_route(self::API_NAMESPACE, '/users/reports/(?P<id>\d+)', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_report_detail'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
register_rest_route(self::API_NAMESPACE, '/users/reports/(?P<id>\d+)/process', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'process_report'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Report status update (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/report/update-status', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'update_report_status'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Report counts (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/report/counts', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_report_counts'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Report submit (logged-in users, front-end)
|
||||
register_rest_route(self::API_NAMESPACE, '/report/submit', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'submit_report'],
|
||||
'permission_callback' => function () { return is_user_logged_in(); },
|
||||
]);
|
||||
|
||||
// Follow toggle (logged-in users)
|
||||
register_rest_route(self::API_NAMESPACE, '/follow/toggle', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'follow_toggle'],
|
||||
'permission_callback' => function () { return is_user_logged_in(); },
|
||||
]);
|
||||
|
||||
// Follow status check (logged-in users)
|
||||
register_rest_route(self::API_NAMESPACE, '/follow/status', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'follow_status'],
|
||||
'permission_callback' => function () { return is_user_logged_in(); },
|
||||
]);
|
||||
|
||||
// Follow counts (public)
|
||||
register_rest_route(self::API_NAMESPACE, '/follow/counts', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'follow_counts'],
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
|
||||
// Invite codes management (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/invite/codes', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_invite_codes'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
register_rest_route(self::API_NAMESPACE, '/invite/codes', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'generate_invite_codes'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
register_rest_route(self::API_NAMESPACE, '/invite/codes/(?P<id>\d+)/disable', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'disable_invite_code'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
register_rest_route(self::API_NAMESPACE, '/invite/codes/bulk', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'bulk_update_invite_codes'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
register_rest_route(self::API_NAMESPACE, '/invite/stats', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_invite_stats'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// ── Modal Auth (弹窗登录/注册) ──
|
||||
|
||||
// Modal login
|
||||
register_rest_route(self::API_NAMESPACE, '/auth/modal-login', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'modal_login'],
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
|
||||
// Modal register
|
||||
register_rest_route(self::API_NAMESPACE, '/auth/modal-register', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'modal_register'],
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
|
||||
// Current user info (for AJAX refresh)
|
||||
register_rest_route(self::API_NAMESPACE, '/auth/me', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_current_user_info'],
|
||||
'permission_callback' => function () { return is_user_logged_in(); },
|
||||
]);
|
||||
|
||||
// Identity verification provider settings (admin only)
|
||||
register_rest_route(self::API_NAMESPACE, '/identity/settings', [
|
||||
[
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_identity_settings'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
],
|
||||
[
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'update_identity_settings'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
],
|
||||
]);
|
||||
register_rest_route(self::API_NAMESPACE, '/identity/settings/test', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'test_identity_settings'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// SMS provider status
|
||||
register_rest_route(self::API_NAMESPACE, '/sms/status', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_sms_status'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// SMS test send (admin only)
|
||||
register_rest_route(self::API_NAMESPACE, '/sms/test', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'test_sms_send'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// WeChat notification status
|
||||
register_rest_route(self::API_NAMESPACE, '/wechat/status', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_wechat_status'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// WeChat settings update
|
||||
register_rest_route(self::API_NAMESPACE, '/wechat/settings', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'update_wechat_settings'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// SMS auth: send verification code (public, rate-limited)
|
||||
register_rest_route(self::API_NAMESPACE, '/auth/send-sms-code', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'auth_send_sms_code'],
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
|
||||
// SMS auth: register by phone (public)
|
||||
register_rest_route(self::API_NAMESPACE, '/auth/phone-register', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'auth_phone_register'],
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
|
||||
// SMS auth: login by phone + password (public)
|
||||
register_rest_route(self::API_NAMESPACE, '/auth/phone-login', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'auth_phone_login'],
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
|
||||
// SMS auth: login by phone + SMS code (public)
|
||||
register_rest_route(self::API_NAMESPACE, '/auth/phone-code-login', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'auth_phone_code_login'],
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
|
||||
// SMS auth: bind phone to current user (logged-in)
|
||||
register_rest_route(self::API_NAMESPACE, '/auth/bind-phone', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'auth_bind_phone'],
|
||||
'permission_callback' => function () { return is_user_logged_in(); },
|
||||
]);
|
||||
|
||||
// ── User Restrictions / Ban ──
|
||||
|
||||
// List restrictions for a user (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/users/(?P<user_id>\d+)/restrictions', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_user_restrictions'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Add restriction (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/users/(?P<user_id>\d+)/restrict', [
|
||||
'methods' => 'POST',
|
||||
'callback' => [$this, 'add_user_restriction'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Remove restriction (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/users/restrictions/(?P<id>\d+)', [
|
||||
'methods' => 'DELETE',
|
||||
'callback' => [$this, 'remove_user_restriction'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Restriction stats (admin)
|
||||
register_rest_route(self::API_NAMESPACE, '/users/restrictions/stats', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_restriction_stats'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* GET/POST /settings/mail-templates — 邮件内容模板
|
||||
*/
|
||||
public function handle_mail_templates(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$option_key = 'aksrt_mail_templates';
|
||||
$fields = [
|
||||
'welcome_subject', 'welcome_body',
|
||||
'comment_notify_subject', 'comment_notify_body',
|
||||
'comment_reply_subject', 'comment_reply_body',
|
||||
'password_reset_subject', 'password_reset_body',
|
||||
'email_verify_subject', 'email_verify_body',
|
||||
];
|
||||
|
||||
if ($request->get_method() === 'GET') {
|
||||
$stored = get_option($option_key, []);
|
||||
if (!is_array($stored)) $stored = [];
|
||||
$result = [];
|
||||
foreach ($fields as $f) {
|
||||
$result[$f] = sanitize_text_field((string) ($stored[$f] ?? ''));
|
||||
}
|
||||
return $this->success(['data' => $result]);
|
||||
}
|
||||
|
||||
// POST
|
||||
$params = $this->get_json_params($request);
|
||||
$clean = [];
|
||||
foreach ($fields as $f) {
|
||||
$clean[$f] = wp_kses_post((string) ($params[$f] ?? ''));
|
||||
}
|
||||
update_option($option_key, $clean);
|
||||
|
||||
return $this->success(['message' => __('邮件模板已保存', 'aksrt')]);
|
||||
}
|
||||
|
||||
public function rest_handle_credit_settings(\WP_REST_Request $request): \WP_REST_Response {
|
||||
if ($request->get_method() === 'GET') {
|
||||
$config = \AKSRT\Settings\CreditsRuntime::get_credit_settings();
|
||||
return $this->success(['data' => $config]);
|
||||
}
|
||||
|
||||
$params = $this->get_json_params($request);
|
||||
$current = get_option('aksrt_credit_settings', []);
|
||||
if (!is_array($current)) {
|
||||
$current = [];
|
||||
}
|
||||
$merged = array_replace_recursive($current, $params);
|
||||
update_option('aksrt_credit_settings', $merged);
|
||||
|
||||
return $this->success(['message' => __('积分配置已保存', 'aksrt')]);
|
||||
}
|
||||
|
||||
public function rest_handle_auth_settings(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$provider = SchemaProvider::get_instance();
|
||||
$allowed = $provider->get_allowed_fields('users', 'auth');
|
||||
|
||||
if ($request->get_method() === 'GET') {
|
||||
$data = \AKSRT\Settings\Settings::get_all();
|
||||
$invite = class_exists('\AKSRT\Settings\CreditsRuntime')
|
||||
? \AKSRT\Settings\CreditsRuntime::get_invite_registration_config()
|
||||
: [];
|
||||
|
||||
return $this->success(['data' => [
|
||||
'registration_email_verification_enabled' => \AKSRT\Settings\Settings::registration_requires_email_verification(),
|
||||
'registration_email_verification_method' => \AKSRT\Settings\Settings::registration_verification_method(),
|
||||
'invite_registration_enabled' => $invite['enabled'] ?? true,
|
||||
'invite_code_length' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::invite_code_length() : 6,
|
||||
'invite_register_field' => $invite['register_field'] ?? 'optional',
|
||||
'invite_reject_invalid' => $invite['reject_invalid'] ?? false,
|
||||
] + array_intersect_key($data, $allowed)]);
|
||||
}
|
||||
|
||||
$params = $this->get_json_params($request);
|
||||
$settings = \AKSRT\Settings\Settings::get_all();
|
||||
$sanitized = $this->sanitize_fields($params, $allowed);
|
||||
$settings = array_merge($settings, $sanitized);
|
||||
|
||||
if (array_key_exists('invite_registration_enabled', $params)) {
|
||||
$settings['invite_registration_enabled'] = !empty($params['invite_registration_enabled']);
|
||||
}
|
||||
if (array_key_exists('invite_code_length', $params)) {
|
||||
$settings['invite_code_length'] = max(4, min(12, (int) $params['invite_code_length']));
|
||||
}
|
||||
if (array_key_exists('invite_register_field', $params)) {
|
||||
$field = (string) $params['invite_register_field'];
|
||||
$settings['invit_code_mode'] = $field === 'required' ? 'must' : ($field === 'hidden' ? 'close' : 'open');
|
||||
}
|
||||
if (array_key_exists('invite_reject_invalid', $params)) {
|
||||
$reward = is_array($settings['invite_reward'] ?? null) ? $settings['invite_reward'] : [];
|
||||
$reward['reject_invalid'] = !empty($params['invite_reject_invalid']);
|
||||
$settings['invite_reward'] = $reward;
|
||||
}
|
||||
if (array_key_exists('registration_email_verification_enabled', $params)) {
|
||||
$settings['registration_email_verification_enabled'] = !empty($params['registration_email_verification_enabled']);
|
||||
}
|
||||
if (array_key_exists('registration_email_verification_method', $params)) {
|
||||
$method = (string) $params['registration_email_verification_method'];
|
||||
$settings['registration_email_verification_method'] = in_array($method, ['link', 'code'], true) ? $method : 'link';
|
||||
}
|
||||
|
||||
update_option('aksrt_settings', $settings);
|
||||
\AKSRT\Settings\Settings::flush_settings_cache();
|
||||
|
||||
return $this->success(['message' => __('注册登录配置已保存', 'aksrt')]);
|
||||
}
|
||||
|
||||
public function rest_handle_notification_settings(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$provider = SchemaProvider::get_instance();
|
||||
$allowed = $provider->get_allowed_fields('users', 'notifications');
|
||||
|
||||
if ($request->get_method() === 'GET') {
|
||||
$data = \AKSRT\Settings\Settings::get_all();
|
||||
return $this->success(['data' => array_intersect_key($data, $allowed)]);
|
||||
}
|
||||
|
||||
$params = $this->get_json_params($request);
|
||||
$settings = \AKSRT\Settings\Settings::get_all();
|
||||
$settings = array_merge($settings, $this->sanitize_fields($params, $allowed));
|
||||
update_option('aksrt_settings', $settings);
|
||||
\AKSRT\Settings\Settings::flush_settings_cache();
|
||||
|
||||
return $this->success(['message' => __('消息通知配置已保存', 'aksrt')]);
|
||||
}
|
||||
|
||||
public function rest_get_notification_overview(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$page = max(1, (int) $request->get_param('page'));
|
||||
$per_page = min(100, max(1, (int) $request->get_param('per_page')));
|
||||
$type = sanitize_key((string) $request->get_param('type'));
|
||||
$is_read = $request->get_param('is_read');
|
||||
|
||||
$items = [];
|
||||
$unread = 0;
|
||||
if (class_exists('\AKSRT\Messages\Message')) {
|
||||
$args = ['limit' => $per_page, 'offset' => ($page - 1) * $per_page];
|
||||
if ($type !== '') {
|
||||
$args['type'] = $type;
|
||||
}
|
||||
$items = \AKSRT\Messages\Message::get_instance()->get_notifications(get_current_user_id(), $args);
|
||||
if ($is_read !== null && $is_read !== '') {
|
||||
$want_read = (string) $is_read === '1';
|
||||
$items = array_values(array_filter($items, static function ($item) use ($want_read) {
|
||||
return !empty($item['is_read']) === $want_read;
|
||||
}));
|
||||
}
|
||||
$unread = \AKSRT\Messages\Message::get_instance()->get_unread_count(get_current_user_id());
|
||||
}
|
||||
|
||||
$total = count($items);
|
||||
$types = [];
|
||||
$today = 0;
|
||||
$system = 0;
|
||||
foreach ($items as $item) {
|
||||
$itemType = sanitize_key((string) ($item['type'] ?? 'system'));
|
||||
$types[$itemType] = ($types[$itemType] ?? 0) + 1;
|
||||
if ($itemType === 'system' || $itemType === 'notice') {
|
||||
$system++;
|
||||
}
|
||||
$created = (string) ($item['created_at'] ?? '');
|
||||
if ($created !== '' && str_starts_with($created, gmdate('Y-m-d'))) {
|
||||
$today++;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->success(['data' => [
|
||||
'recent' => $items,
|
||||
'types' => array_map(static fn($key, $count) => ['type' => $key, 'count' => $count], array_keys($types), array_values($types)),
|
||||
'summary' => [
|
||||
'total' => $total,
|
||||
'unread' => $unread,
|
||||
'today' => $today,
|
||||
'system' => $system,
|
||||
],
|
||||
'pagination' => [
|
||||
'page' => $page,
|
||||
'per_page' => $per_page,
|
||||
'total_items' => $total,
|
||||
'total_pages' => 1,
|
||||
],
|
||||
]]);
|
||||
}
|
||||
|
||||
public function rest_mark_notification_read(\WP_REST_Request $request): \WP_REST_Response {
|
||||
if (!class_exists('\AKSRT\Messages\Message')) {
|
||||
return $this->success(['message' => __('消息系统未启用', 'aksrt')]);
|
||||
}
|
||||
|
||||
$params = $this->get_json_params($request);
|
||||
$msg = \AKSRT\Messages\Message::get_instance();
|
||||
if (!empty($params['mark_all'])) {
|
||||
$msg->mark_all_read(get_current_user_id());
|
||||
} else {
|
||||
$id = sanitize_text_field((string) ($params['id'] ?? ''));
|
||||
if ($id !== '') {
|
||||
$msg->mark_read(get_current_user_id(), $id);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->success(['message' => __('已更新消息状态', 'aksrt')]);
|
||||
}
|
||||
|
||||
public function rest_delete_notification_item(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$user_id = get_current_user_id();
|
||||
if ($user_id <= 0) {
|
||||
return $this->error(__('请先登录', 'aksrt'), 401);
|
||||
}
|
||||
$params = $this->get_json_params($request);
|
||||
$id = sanitize_text_field((string) ($params['id'] ?? $request->get_param('id') ?? ''));
|
||||
if ($id === '') {
|
||||
return $this->error(__('参数错误', 'aksrt'), 400);
|
||||
}
|
||||
if (function_exists('aksrt_delete_user_notification')) {
|
||||
aksrt_delete_user_notification($user_id, $id);
|
||||
} elseif (class_exists('\AKSRT\Messages\Message')) {
|
||||
\AKSRT\Messages\Message::get_instance()->mark_read($user_id, $id);
|
||||
}
|
||||
return $this->success([
|
||||
'message' => __('消息已删除', 'aksrt'),
|
||||
'unread' => function_exists('aksrt_get_user_unread_notification_count')
|
||||
? aksrt_get_user_unread_notification_count($user_id)
|
||||
: 0,
|
||||
]);
|
||||
}
|
||||
|
||||
public function rest_run_notification_cleanup(\WP_REST_Request $request): \WP_REST_Response {
|
||||
return $this->success(['message' => __('消息清理任务已受理', 'aksrt')]);
|
||||
}
|
||||
|
||||
public function rest_handle_oauth(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$provider = SchemaProvider::get_instance();
|
||||
$allowed = $provider->get_allowed_fields('users', 'oauth');
|
||||
|
||||
if ($request->get_method() === 'GET') {
|
||||
$data = \AKSRT\Settings\Settings::get_all();
|
||||
return $this->success(['data' => array_intersect_key($data, $allowed)]);
|
||||
}
|
||||
|
||||
$params = $this->get_json_params($request);
|
||||
$settings = \AKSRT\Settings\Settings::get_all();
|
||||
$settings = array_merge($settings, $this->sanitize_fields($params, $allowed));
|
||||
update_option('aksrt_settings', $settings);
|
||||
\AKSRT\Settings\Settings::flush_settings_cache();
|
||||
|
||||
return $this->success(['message' => __('第三方登录配置已保存', 'aksrt')]);
|
||||
}
|
||||
|
||||
public function rest_handle_oauth_proxy(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$keys = [
|
||||
'oauth_proxy_mode',
|
||||
'oauth_proxy_secret',
|
||||
'oauth_proxy_server_url',
|
||||
'oauth_proxy_server_providers',
|
||||
'oauth_proxy_client_providers',
|
||||
'oauth_proxy_gzh_type',
|
||||
];
|
||||
|
||||
if ($request->get_method() === 'GET') {
|
||||
$all = \AKSRT\Settings\Settings::get_all();
|
||||
$data = [];
|
||||
foreach ($keys as $key) {
|
||||
$data[$key] = $all[$key] ?? null;
|
||||
}
|
||||
return $this->success(['data' => $data]);
|
||||
}
|
||||
|
||||
$params = $this->get_json_params($request);
|
||||
$settings = \AKSRT\Settings\Settings::get_all();
|
||||
foreach ($keys as $key) {
|
||||
if (!array_key_exists($key, $params)) {
|
||||
continue;
|
||||
}
|
||||
$settings[$key] = is_array($params[$key])
|
||||
? array_values(array_map('sanitize_key', (array) $params[$key]))
|
||||
: sanitize_text_field((string) $params[$key]);
|
||||
}
|
||||
update_option('aksrt_settings', $settings);
|
||||
\AKSRT\Settings\Settings::flush_settings_cache();
|
||||
|
||||
return $this->success(['message' => __('OAuth 代理配置已保存', 'aksrt')]);
|
||||
}
|
||||
|
||||
public function rest_upload_comment_image(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$user_id = get_current_user_id();
|
||||
if ($user_id <= 0) {
|
||||
return $this->error(__('请先登录', 'aksrt'), 401);
|
||||
}
|
||||
if (empty($_FILES['image']) && empty($_FILES['file'])) {
|
||||
return $this->error(__('请选择要上传的图片', 'aksrt'), 400);
|
||||
}
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/media.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/image.php';
|
||||
|
||||
$file_key = !empty($_FILES['image']) ? 'image' : 'file';
|
||||
$attachment_id = media_handle_upload($file_key, 0);
|
||||
if (is_wp_error($attachment_id)) {
|
||||
return $this->error($attachment_id->get_error_message(), 400);
|
||||
}
|
||||
$url = wp_get_attachment_url((int) $attachment_id);
|
||||
if (!$url) {
|
||||
return $this->error(__('上传失败', 'aksrt'), 500);
|
||||
}
|
||||
return $this->success([
|
||||
'message' => __('图片上传成功', 'aksrt'),
|
||||
'data' => [
|
||||
'url' => $url,
|
||||
'attachment_id' => (int) $attachment_id,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function rest_get_credits_me(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$user_id = get_current_user_id();
|
||||
return $this->success(['data' => [
|
||||
'user_id' => $user_id,
|
||||
'balance' => class_exists('\AKSRT\Credits\Credits') ? \AKSRT\Credits\Credits::balance($user_id) : 0,
|
||||
]]);
|
||||
}
|
||||
|
||||
public function rest_list_credit_users(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$args = [
|
||||
'search' => (string) $request->get_param('search'),
|
||||
'page' => (int) $request->get_param('page'),
|
||||
'per_page' => (int) $request->get_param('per_page'),
|
||||
];
|
||||
$data = class_exists('\AKSRT\Credits\Credits') ? \AKSRT\Credits\Credits::list_users($args) : ['items' => [], 'total' => 0, 'page' => 1, 'per_page' => 20];
|
||||
return $this->success(['data' => $data]);
|
||||
}
|
||||
|
||||
public function rest_adjust_user_credits(\WP_REST_Request $request): \WP_REST_Response {
|
||||
if (!class_exists('\AKSRT\Credits\Credits')) {
|
||||
return $this->error(__('积分系统不可用', 'aksrt'), 500);
|
||||
}
|
||||
|
||||
$user_id = (int) $request->get_param('id');
|
||||
$params = $this->get_json_params($request);
|
||||
$delta = (int) ($params['delta'] ?? 0);
|
||||
$reason = sanitize_text_field((string) ($params['reason'] ?? 'admin'));
|
||||
|
||||
if ($user_id <= 0 || $delta === 0) {
|
||||
return $this->error(__('用户或积分变动值无效', 'aksrt'), 422);
|
||||
}
|
||||
|
||||
if ($delta > 0) {
|
||||
$result = \AKSRT\Credits\Credits::add($user_id, $delta, $reason, ['type' => 'user', 'id' => $user_id], 'Admin adjustment');
|
||||
} else {
|
||||
$result = \AKSRT\Credits\Credits::deduct($user_id, abs($delta), $reason, ['type' => 'user', 'id' => $user_id], 'Admin adjustment');
|
||||
}
|
||||
|
||||
if (is_wp_error($result)) {
|
||||
return $this->error($result->get_error_message(), 422);
|
||||
}
|
||||
|
||||
return $this->success(['data' => [
|
||||
'user_id' => $user_id,
|
||||
'balance' => (int) $result,
|
||||
], 'message' => __('积分调整已保存', 'aksrt')]);
|
||||
}
|
||||
|
||||
public function rest_get_credits_log(\WP_REST_Request $request): \WP_REST_Response {
|
||||
$args = [
|
||||
'user_id' => (int) $request->get_param('user_id'),
|
||||
'reason' => (string) $request->get_param('reason'),
|
||||
'page' => (int) $request->get_param('page'),
|
||||
'per_page' => (int) $request->get_param('per_page'),
|
||||
'date_from' => (string) $request->get_param('date_from'),
|
||||
'date_to' => (string) $request->get_param('date_to'),
|
||||
];
|
||||
$data = class_exists('\AKSRT\Credits\Credits') ? \AKSRT\Credits\Credits::get_log($args) : ['items' => [], 'total' => 0, 'page' => 1, 'per_page' => 20];
|
||||
return $this->success(['data' => $data]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user