prefix . 'aksrt_user_restriction'; } /** * Add a restriction to a user. */ public function restrict(int $user_id, string $type, string $reason, string $scope = self::SCOPE_GLOBAL, string $expires_at = '', int $created_by = 0): array { global $wpdb; if (!in_array($type, self::TYPES, true)) { return ['success' => false, 'message' => 'Invalid restriction type.']; } if (!in_array($scope, self::SCOPES, true)) { return ['success' => false, 'message' => 'Invalid scope.']; } if ($created_by <= 0) { $created_by = get_current_user_id(); } $data = [ 'user_id' => $user_id, 'type' => $type, 'reason' => sanitize_textarea_field($reason), 'scope' => $scope, 'expires_at' => $expires_at ? gmdate('Y-m-d H:i:s', strtotime($expires_at)) : null, 'created_by' => $created_by, 'created_at' => current_time('mysql', true), ]; $result = $wpdb->insert($this->table(), $data); if ($result === false) { return ['success' => false, 'message' => 'Database error.']; } // 封禁立即生效:销毁目标用户全部登录会话 if ($type === self::TYPE_BAN && $user_id > 0) { \WP_Session_Tokens::get_instance($user_id)->destroy_all(); } do_action('aksrt_user_restriction_changed', $user_id, $type, 'applied', (string) $data['reason']); return ['success' => true, 'id' => $wpdb->insert_id]; } /** * Remove a restriction by ID. */ public function remove_restriction(int $restriction_id): bool { global $wpdb; $restriction = $this->get_restriction($restriction_id); if (!$restriction) return false; $result = $wpdb->delete($this->table(), ['id' => $restriction_id]); if ($result) { do_action('aksrt_user_restriction_changed', (int) $restriction['user_id'], (string) ($restriction['type'] ?? ''), 'removed', ''); } return (bool) $result; } /** * 解除用户生效中的限制(可选按类型过滤),用于申诉通过或举报工单"解除限制"。 * * @param int $user_id 用户 ID * @param array $types 要解除的类型,默认解除 ban/suspend/mute(保留 warn 警告记录) * @return int 解除的记录数 */ public function lift_user_restriction(int $user_id, array $types = [self::TYPE_BAN, self::TYPE_SUSPEND, self::TYPE_MUTE]): int { global $wpdb; $types = array_values(array_intersect($types, self::TYPES)); if ($user_id <= 0 || empty($types)) { return 0; } $placeholders = implode(',', array_fill(0, count($types), '%s')); $deleted = $wpdb->query($wpdb->prepare( "DELETE FROM {$this->table()} WHERE user_id = %d AND (expires_at IS NULL OR expires_at > %s) AND type IN ({$placeholders})", array_merge([$user_id, current_time('mysql', true)], $types) )); if ($deleted > 0) { do_action('aksrt_user_restriction_changed', $user_id, implode(',', $types), 'lifted', ''); } return (int) $deleted; } /** * Get a single restriction by ID. */ public function get_restriction(int $restriction_id): ?array { global $wpdb; $row = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$this->table()} WHERE id = %d", $restriction_id ), ARRAY_A); return $row ?: null; } /** * Get all active restrictions for a user. */ public function get_user_restrictions(int $user_id, bool $active_only = true): array { global $wpdb; $now = current_time('mysql', true); if ($active_only) { $rows = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$this->table()} WHERE user_id = %d AND (expires_at IS NULL OR expires_at > %s) ORDER BY created_at DESC", $user_id, $now ), ARRAY_A); } else { $rows = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$this->table()} WHERE user_id = %d ORDER BY created_at DESC", $user_id ), ARRAY_A); } return $rows ?: []; } /** * Check if a user has an active restriction of a given type and scope. */ public function is_restricted(int $user_id, string $type = '', string $scope = ''): bool { $restrictions = $this->get_user_restrictions($user_id, true); foreach ($restrictions as $r) { if ($type && $r['type'] !== $type) continue; if ($scope && $r['scope'] !== $scope && $r['scope'] !== self::SCOPE_GLOBAL) continue; return true; } return false; } /** * Check if a user is banned (global). */ public function is_banned(int $user_id): bool { return $this->is_restricted($user_id, self::TYPE_BAN, self::SCOPE_GLOBAL); } /** * Get the active ban restriction for a user (if any). */ public function get_active_ban(int $user_id): ?array { $restrictions = $this->get_user_restrictions($user_id, true); foreach ($restrictions as $r) { if ($r['type'] === self::TYPE_BAN && $r['scope'] === self::SCOPE_GLOBAL) { return $r; } } return null; } /** * Enforce ban on login. */ public function enforce_login_ban($user, string $username, string $password) { if (is_wp_error($user) || !$user instanceof \WP_User) { return $user; } if ($this->is_banned($user->ID)) { $ban = $this->get_active_ban($user->ID); $message = '您的账号已被封禁。'; if (!empty($ban['reason'])) { $message .= '原因:' . $ban['reason']; } return new \WP_Error('user_banned', $message); } return $user; } /** * Enforce comment mute. */ public function enforce_comment_mute($post_id) { $user_id = get_current_user_id(); if ($user_id > 0 && $this->is_restricted($user_id, self::TYPE_MUTE, self::SCOPE_COMMENT)) { wp_die('您已被限制评论。', '评论限制', ['response' => 403]); } return $post_id; } /** * Get restriction stats for admin overview. */ public function get_stats(): array { global $wpdb; $now = current_time('mysql', true); $table = $this->table(); $total = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$table}"); $active = (int) $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM {$table} WHERE expires_at IS NULL OR expires_at > %s", $now )); $banned = (int) $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM {$table} WHERE type = %s AND (expires_at IS NULL OR expires_at > %s)", self::TYPE_BAN, $now )); return ['total' => $total, 'active' => $active, 'banned' => $banned]; } }