Store readable category snapshots separately from details and evidence, validate report categories, and preserve context in admin displays and moderation actions. Widen report categories to TEXT and bump the schema to 3.2.0 without legacy data conversion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
387 lines
19 KiB
PHP
387 lines
19 KiB
PHP
<?php
|
|
/**
|
|
* Exercise the native ban queue, detail templates, and post handlers with WordPress fixtures.
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
namespace AKSRT\Core {
|
|
final class DBMigrator {
|
|
public static function table(string $name): string { return 'wp_aksrt_' . $name; }
|
|
}
|
|
}
|
|
|
|
namespace AKSRT\User {
|
|
final class Restriction {
|
|
public const TYPE_WARN = 'warn';
|
|
public const TYPE_MUTE = 'mute';
|
|
public const TYPE_SUSPEND = 'suspend';
|
|
public const TYPE_BAN = 'ban';
|
|
public const SCOPE_COMMENT = 'comment';
|
|
public static int $lifted = 0;
|
|
public static function get_instance(): self { return new self(); }
|
|
public function lift_user_restriction(int $user_id): int { self::$lifted++; return $user_id > 0 ? 1 : 0; }
|
|
public function get_user_restrictions(int $user_id, bool $active = false): array { unset($user_id, $active); return []; }
|
|
}
|
|
|
|
final class BanAppeal {
|
|
public const META_STATUS = '_aksrt_ban_appeal_status';
|
|
public const META_PAYLOAD = '_aksrt_ban_appeal_payload';
|
|
public const META_HISTORY = '_aksrt_ban_appeal_history';
|
|
public static function get_status(int $user_id): string {
|
|
return (string) ($GLOBALS['aksrt_test_user_meta'][$user_id][self::META_STATUS] ?? '');
|
|
}
|
|
public static function get_payload(int $user_id): array {
|
|
$value = $GLOBALS['aksrt_test_user_meta'][$user_id][self::META_PAYLOAD] ?? [];
|
|
return is_array($value) ? $value : [];
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace AKSRT\Messages {
|
|
final class ReportCenter {
|
|
private static ?self $instance = null;
|
|
public static function get_instance(): self { return self::$instance ??= new self(); }
|
|
public function update_status(int $id, string $status, string $note): bool {
|
|
$GLOBALS['aksrt_test_reports'][$id]['status'] = $status;
|
|
$GLOBALS['aksrt_test_reports'][$id]['updated_at'] = '2026-10-30 13:00:00';
|
|
$GLOBALS['aksrt_test_report_actions'][] = [$id, $status, $note];
|
|
return true;
|
|
}
|
|
}
|
|
|
|
final class Message {
|
|
private static ?self $instance = null;
|
|
public static function get_instance(): self { return self::$instance ??= new self(); }
|
|
public function send(int $user_id, string $type, string $message, array $args = []): void {
|
|
$GLOBALS['aksrt_test_messages'][] = [$user_id, $type, $message, $args];
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace AKSRT\Admin\Native {
|
|
final class AdminListPagination {
|
|
public static function render(string $slug, int $total, int $page, int $per_page, array $filters = [], string $parent = ''): void {
|
|
$GLOBALS['aksrt_test_pagination'][] = [$slug, $total, $page, $per_page, $filters, $parent];
|
|
echo '<nav data-test-pagination="' . esc_attr((string) $total) . ':' . esc_attr((string) $page) . '"></nav>';
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
define('ABSPATH', dirname(__DIR__, 2) . DIRECTORY_SEPARATOR);
|
|
define('AKSRT_DIR', dirname(__DIR__, 2) . DIRECTORY_SEPARATOR);
|
|
define('AKSRT_URI', 'https://theme.example.test');
|
|
define('ARRAY_A', 'ARRAY_A');
|
|
|
|
class WP_User {
|
|
public function __construct(public int $ID, public string $display_name) {}
|
|
}
|
|
|
|
final class TestRedirect extends \RuntimeException {
|
|
public function __construct(public string $page, public string $redirectMessage, public array $args) {
|
|
parent::__construct($redirectMessage);
|
|
}
|
|
}
|
|
|
|
final class TestWpdb {
|
|
public string $prefix = 'wp_';
|
|
public string $users = 'wp_users';
|
|
public string $last_error = '';
|
|
private array $args = [];
|
|
public function prepare(string $query, $args = []): string {
|
|
$this->args = is_array($args) ? $args : [$args];
|
|
return $query;
|
|
}
|
|
public function esc_like(string $text): string { return addcslashes($text, '_%\\'); }
|
|
public function get_results(string $query, $output = null): array {
|
|
if (str_contains($query, 'notes_json')) {
|
|
return array_map(static fn (int $id): array => [
|
|
'id' => $id,
|
|
'notes_json' => $GLOBALS['aksrt_test_reports'][$id]['notes_json'] ?? '[]',
|
|
], $this->args);
|
|
}
|
|
if (str_contains($query, 'aksrt_user_restriction')) {
|
|
return $GLOBALS['aksrt_test_restrictions'];
|
|
}
|
|
$reports = array_values($GLOBALS['aksrt_test_reports']);
|
|
$search = '';
|
|
$send_user = 0;
|
|
foreach ($this->args as $arg) {
|
|
if (is_string($arg) && str_starts_with($arg, '%') && str_ends_with($arg, '%')) $search = trim($arg, '%');
|
|
if (is_int($arg) && $arg > 0) $send_user = $arg;
|
|
}
|
|
return array_values(array_filter($reports, static function (array $row) use ($search, $send_user): bool {
|
|
if ($send_user > 0 && (int) $row['reporter_id'] !== $send_user) return false;
|
|
if ($search !== '' && stripos(implode(' ', [$row['reason'], $row['category'], $row['target_type'], $row['target_id']]), $search) === false) return false;
|
|
return true;
|
|
}));
|
|
}
|
|
public function get_row(string $query, $output = null) {
|
|
$id = (int) ($this->args[0] ?? 0);
|
|
return $GLOBALS['aksrt_test_reports'][$id] ?? null;
|
|
}
|
|
}
|
|
|
|
$GLOBALS['wpdb'] = new TestWpdb();
|
|
$GLOBALS['aksrt_test_reports'] = [];
|
|
$GLOBALS['aksrt_test_user_meta'] = [];
|
|
$GLOBALS['aksrt_test_restrictions'] = [[
|
|
'user_id' => 7,
|
|
'type' => 'ban',
|
|
'scope' => 'site',
|
|
'reason' => 'fixture restriction',
|
|
'created_at' => '2026-10-01 08:00:00',
|
|
'expires_at' => null,
|
|
]];
|
|
$GLOBALS['aksrt_test_assets'] = ['styles' => [], 'scripts' => []];
|
|
$GLOBALS['aksrt_test_pagination'] = [];
|
|
$GLOBALS['aksrt_test_report_actions'] = [];
|
|
$GLOBALS['aksrt_test_messages'] = [];
|
|
$GLOBALS['aksrt_test_nonce_checks'] = [];
|
|
$GLOBALS['aksrt_test_capability'] = true;
|
|
|
|
function __($text, $domain = null): string { return (string) $text; }
|
|
function esc_html__($text, $domain = null): string { return esc_html((string) $text); }
|
|
function esc_attr__($text, $domain = null): string { return esc_attr((string) $text); }
|
|
function esc_html($value): string { return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
|
|
function esc_attr($value): string { return esc_html((string) $value); }
|
|
function esc_url($url, array $protocols = ['http', 'https']): string {
|
|
$url = trim((string) $url);
|
|
if (preg_match('/^([a-z][a-z0-9+.-]*):/i', $url, $match) && !in_array(strtolower($match[1]), $protocols, true)) return '';
|
|
return esc_attr($url);
|
|
}
|
|
function sanitize_key($value): string { return preg_replace('/[^a-z0-9_\-]/', '', strtolower((string) $value)) ?? ''; }
|
|
function sanitize_text_field($value): string { return trim(preg_replace('/[\r\n\t]+/', ' ', strip_tags((string) $value)) ?? ''); }
|
|
function sanitize_textarea_field($value): string { return trim(strip_tags((string) $value)); }
|
|
function wp_unslash($value) { return $value; }
|
|
function wp_slash($value) { return $value; }
|
|
function absint($value): int { return abs((int) $value); }
|
|
function admin_url(string $path = ''): string { return 'https://example.test/wp-admin/' . ltrim($path, '/'); }
|
|
function add_query_arg($key, $value = null, $url = ''): string {
|
|
if (is_array($key)) {
|
|
$args = $key;
|
|
$base = (string) $value;
|
|
} else {
|
|
$args = [(string) $key => $value];
|
|
$base = (string) $url;
|
|
}
|
|
$parts = parse_url($base);
|
|
$query = [];
|
|
if (!empty($parts['query'])) parse_str($parts['query'], $query);
|
|
$query = array_merge($query, $args);
|
|
$prefix = isset($parts['scheme']) ? $parts['scheme'] . '://' . ($parts['host'] ?? '') : '';
|
|
$prefix .= $parts['path'] ?? '';
|
|
return $prefix . '?' . http_build_query($query);
|
|
}
|
|
function current_user_can(string $capability): bool { return $capability === 'manage_options' && $GLOBALS['aksrt_test_capability']; }
|
|
function wp_die($message): void { throw new \RuntimeException((string) $message); }
|
|
function wp_nonce_field(string $action): void { echo '<input type="hidden" name="_wpnonce" value="' . esc_attr($action . '-nonce') . '">'; }
|
|
function check_admin_referer(string $action): void {
|
|
$GLOBALS['aksrt_test_nonce_checks'][] = $action;
|
|
if (($_POST['_wpnonce'] ?? '') !== $action . '-nonce') throw new \RuntimeException('nonce mismatch');
|
|
}
|
|
function wp_enqueue_style(string $handle, string $src, array $deps = [], string $version = ''): void {
|
|
$GLOBALS['aksrt_test_assets']['styles'][] = [$handle, $src, $deps, $version];
|
|
}
|
|
function wp_enqueue_script(string $handle, string $src, array $deps = [], string $version = '', bool $footer = false): void {
|
|
$GLOBALS['aksrt_test_assets']['scripts'][] = [$handle, $src, $deps, $version, $footer];
|
|
}
|
|
function get_userdata(int $user_id) { return $user_id > 0 ? new WP_User($user_id, $user_id === 7 ? 'Report <script>alert(1)</script>' : 'User ' . $user_id) : false; }
|
|
function get_current_user_id(): int { return 999; }
|
|
function get_user_meta(int $user_id, string $key, bool $single = false) { return $GLOBALS['aksrt_test_user_meta'][$user_id][$key] ?? ''; }
|
|
function update_user_meta(int $user_id, string $key, $value): bool { $GLOBALS['aksrt_test_user_meta'][$user_id][$key] = $value; return true; }
|
|
function delete_user_meta(int $user_id, string $key): bool { unset($GLOBALS['aksrt_test_user_meta'][$user_id][$key]); return true; }
|
|
function get_users(array $args = []): array {
|
|
$ids = array_keys($GLOBALS['aksrt_test_user_meta']);
|
|
if (isset($args['include'])) $ids = array_values(array_intersect($ids, $args['include']));
|
|
$ids = array_values(array_filter($ids, static fn (int $id): bool => \AKSRT\User\BanAppeal::get_status($id) !== ''));
|
|
return $args['fields'] === 'ID' ? $ids : array_map('get_userdata', $ids);
|
|
}
|
|
function update_meta_cache(string $type, array $ids): void { unset($type, $ids); }
|
|
function cache_users(array $ids): void { unset($ids); }
|
|
function _prime_post_caches(array $ids, bool $update_term_cache = true, bool $update_meta_cache = true): void { unset($ids, $update_term_cache, $update_meta_cache); }
|
|
function _prime_comment_caches(array $ids, bool $update_meta_cache = true): void { unset($ids, $update_meta_cache); }
|
|
function get_date_from_gmt(string $date, string $format): string { return $date; }
|
|
function current_time(string $type, bool $gmt = false): string { return '2026-10-30 12:00:00'; }
|
|
function number_format_i18n($number): string { return number_format((float) $number); }
|
|
function get_avatar_url(int $user_id, array $args = []): string { return 'https://example.test/avatar/' . $user_id . '.png'; }
|
|
function get_edit_user_link(int $user_id): string { return admin_url('user-edit.php?user_id=' . $user_id); }
|
|
function get_post(int $id) { return $id === 44 ? (object) ['ID' => $id] : false; }
|
|
function get_the_title(int $id): string { return $id === 44 ? '<img src=x onerror=alert(1)>' : 'Post ' . $id; }
|
|
function get_permalink(int $id): string { return 'https://content.example.test/post/' . $id; }
|
|
function get_comment(int $id) { return false; }
|
|
function get_comment_link(int $id): string { return 'https://content.example.test/comment/' . $id; }
|
|
function get_author_posts_url(int $user_id): string { return 'https://content.example.test/author/' . $user_id; }
|
|
function aksrt_get_user_home_url(int $user_id): string { return 'https://content.example.test/user/' . $user_id; }
|
|
function do_action(string $hook, ...$args): void { unset($hook, $args); }
|
|
|
|
function fixture_report(int $id, int $reporter, string $status, string $time, string $reason = ''): array {
|
|
return [
|
|
'id' => $id,
|
|
'reporter_id' => $reporter,
|
|
'target_type' => 'post',
|
|
'target_id' => 44,
|
|
'reason' => $reason !== '' ? $reason : 'report reason ' . $id,
|
|
'category' => '垃圾信息',
|
|
'status' => $status,
|
|
'created_at' => $time,
|
|
'updated_at' => $time,
|
|
'notes_json' => '[]',
|
|
];
|
|
}
|
|
|
|
for ($id = 1; $id <= 110; $id++) {
|
|
$status = $id === 2 ? 'resolved' : ($id === 3 ? 'dismissed' : ($id === 4 ? 'reviewing' : 'pending'));
|
|
$time = gmdate('Y-m-d H:i:s', strtotime('2026-10-01 00:00:00 UTC') + ($id * 60));
|
|
$reason = $id === 1
|
|
? 'Evidence <script>alert(1)</script> https://evidence.example.test/proof.jpg javascript:alert(2)'
|
|
: 'report reason ' . $id;
|
|
$time = $id === 1 ? '2026-10-30 12:00:00' : ($id === 2 ? '2026-10-29 11:00:00' : $time);
|
|
$GLOBALS['aksrt_test_reports'][$id] = fixture_report($id, $id === 1 ? 7 : 20 + $id, $status, $time, $reason);
|
|
}
|
|
$GLOBALS['aksrt_test_reports'][1]['category'] = '版权投诉';
|
|
$GLOBALS['aksrt_test_reports'][2]['category'] = '人身攻击';
|
|
$GLOBALS['aksrt_test_reports'][2]['reason'] = '';
|
|
$GLOBALS['aksrt_test_reports'][9001] = fixture_report(9001, 7, 'pending', '2026-09-01 09:00:00', 'needle action report');
|
|
$GLOBALS['aksrt_test_reports'][9002] = fixture_report(9002, 7, 'pending', '2026-09-02 09:00:00', 'needle stale report');
|
|
|
|
function fixture_appeal(int $user_id, string $status, string $time, array $payload = []): void {
|
|
$GLOBALS['aksrt_test_user_meta'][$user_id][\AKSRT\User\BanAppeal::META_STATUS] = $status;
|
|
$GLOBALS['aksrt_test_user_meta'][$user_id][\AKSRT\User\BanAppeal::META_PAYLOAD] = array_merge([
|
|
'time' => $time,
|
|
'reason_key' => 'ban reason',
|
|
'reason' => 'appeal explanation',
|
|
'data' => [],
|
|
], $payload);
|
|
}
|
|
fixture_appeal(501, 'pending', '2026-10-29 12:00:00', [
|
|
'reason_key' => 'reason <svg onload=alert(1)>',
|
|
'reason' => 'Appeal note <script>alert(2)</script> https://appeal.example.test/file.pdf javascript:alert(3)',
|
|
'data' => [
|
|
'Name <img src=x onerror=alert(4)>' => 'Applicant <b>value</b>',
|
|
'Evidence' => 'https://appeal.example.test/document.pdf',
|
|
'Ignored array' => ['nested'],
|
|
],
|
|
]);
|
|
fixture_appeal(502, 'approved', '2026-10-20 09:00:00', ['handled_at' => '2026-10-21 09:00:00', 'handled_by' => 999, 'decision' => 'approved']);
|
|
fixture_appeal(503, 'rejected', '2026-10-19 09:00:00', ['handled_at' => '2026-10-20 09:00:00', 'handled_by' => 999, 'decision' => 'rejected']);
|
|
for ($user_id = 600; $user_id < 615; $user_id++) fixture_appeal($user_id, 'pending', '2026-10-02 ' . sprintf('%02d', $user_id - 600) . ':00:00');
|
|
fixture_appeal(7001, 'pending', '2026-09-03 09:00:00', ['reason' => 'pending appeal action']);
|
|
fixture_appeal(7002, 'pending', '2026-09-04 09:00:00', ['reason' => 'pending appeal approve']);
|
|
|
|
require_once AKSRT_DIR . 'src/Admin/Native/NativeUi.php';
|
|
require_once AKSRT_DIR . 'src/Admin/Native/UsersMenusBanQuery.php';
|
|
require_once AKSRT_DIR . 'src/Admin/Native/UsersMenusBanDialogs.php';
|
|
require_once AKSRT_DIR . 'src/Admin/Native/UsersMenusBanActions.php';
|
|
require_once AKSRT_DIR . 'src/Admin/Native/UsersMenusBan.php';
|
|
|
|
final class BanFixtureMenu {
|
|
use \AKSRT\Admin\Native\UsersMenusBan;
|
|
public const CAPABILITY = 'manage_options';
|
|
public function ensure_cap(): void {}
|
|
public function flash(): void {}
|
|
public function redirect(string $page, string $message, array $args = []): void { throw new TestRedirect($page, $message, $args); }
|
|
public function record(string $kind, int $id): ?array { return $this->find_ban_request($kind, $id); }
|
|
public function filters(array $input): array { return $this->get_ban_filters($input); }
|
|
public function version(array $row): string { return $this->ban_record_version($row); }
|
|
public function query(array $filters, int $page): array {
|
|
return $this->query_ban_requests($this->get_ban_filters($filters), $page);
|
|
}
|
|
public function query_record(string $kind, int $id): ?array {
|
|
$filters = $this->get_ban_filters(['type' => $kind, 'status' => '']);
|
|
$firstPage = $this->query_ban_requests($filters, 1);
|
|
$pages = max(1, (int) ceil($firstPage['total'] / 20));
|
|
for ($page = 1; $page <= $pages; $page++) {
|
|
$result = $page === 1 ? $firstPage : $this->query_ban_requests($filters, $page);
|
|
foreach ($result['items'] as $row) if ($row['kind'] === $kind && (int) $row['id'] === $id) return $row;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function render_ban_page(array $get): string {
|
|
$_GET = $get;
|
|
ob_start();
|
|
(new BanFixtureMenu())->render_ban_page();
|
|
return (string) ob_get_clean();
|
|
}
|
|
|
|
function call_action(BanFixtureMenu $menu, string $method, string $nonce_action, array $post): array {
|
|
$_POST = array_merge($post, ['_wpnonce' => $nonce_action . '-nonce']);
|
|
try {
|
|
$menu->{$method}();
|
|
return ['redirected' => false];
|
|
} catch (TestRedirect $redirect) {
|
|
return ['redirected' => true, 'page' => $redirect->page, 'message' => $redirect->redirectMessage, 'args' => $redirect->args];
|
|
}
|
|
}
|
|
|
|
$queueMenu = new BanFixtureMenu();
|
|
$all = $queueMenu->query(['status' => ''], 2);
|
|
$overlargePage = $queueMenu->query(['status' => ''], 99);
|
|
$filters = $queueMenu->filters([
|
|
'type' => 'report', 'status' => '', 's' => 'needle', 'send_user' => '7',
|
|
'orderby' => 'updated', 'order' => 'ASC',
|
|
]);
|
|
$html = render_ban_page(['page' => 'aksrt_user_ban', 'status' => '', 'orderby' => 'time', 'order' => 'DESC']);
|
|
$filteredHtml = render_ban_page([
|
|
'page' => 'aksrt_user_ban', 'type' => 'report', 'status' => 'pending', 's' => 'needle',
|
|
'send_user' => '7', 'orderby' => 'updated', 'order' => 'ASC', 'paged' => '1',
|
|
]);
|
|
|
|
$GLOBALS['aksrt_test_assets'] = ['styles' => [], 'scripts' => []];
|
|
$assetMenu = new BanFixtureMenu();
|
|
$assetMenu->enqueue_ban_assets('users_page_aksrt_user_ban');
|
|
$assetMenu->enqueue_ban_assets('users_page_other');
|
|
|
|
$menu = new BanFixtureMenu();
|
|
$reportQueryRow = $menu->query_record('report', 9001);
|
|
$reportVersion = $menu->version($reportQueryRow);
|
|
$reportBase = [
|
|
'report_id' => '9001', 'new_status' => 'resolved', 'note' => 'Reviewed', 'record_version' => $reportVersion,
|
|
'filter_type' => 'report', 'filter_status' => 'pending', 's' => 'needle', 'send_user' => '7',
|
|
'orderby' => 'updated', 'order' => 'ASC', 'paged' => '2',
|
|
];
|
|
$blankReport = call_action($menu, 'handle_update_report', 'aksrt_users_update_report_9001', array_merge($reportBase, ['new_status' => 'dismissed', 'note' => ' ']));
|
|
$staleReport = call_action($menu, 'handle_update_report', 'aksrt_users_update_report_9002', array_merge($reportBase, ['report_id' => '9002', 'record_version' => 'stale-version']));
|
|
$validReport = call_action($menu, 'handle_update_report', 'aksrt_users_update_report_9001', $reportBase);
|
|
|
|
$appealRow = $menu->query_record('appeal', 7001);
|
|
$appealVersion = $menu->version($appealRow);
|
|
$appealBase = [
|
|
'user_id' => '7001', 'decision' => 'reject', 'note' => ' Missing evidence ', 'record_version' => $appealVersion,
|
|
'filter_type' => 'appeal', 'filter_status' => 'pending', 's' => 'needle', 'send_user' => '7001',
|
|
'orderby' => 'updated', 'order' => 'ASC', 'paged' => '3',
|
|
];
|
|
$blankAppeal = call_action($menu, 'handle_process_appeal', 'aksrt_users_process_appeal_7001', array_merge($appealBase, ['note' => ' ']));
|
|
$validAppeal = call_action($menu, 'handle_process_appeal', 'aksrt_users_process_appeal_7001', $appealBase);
|
|
|
|
$approveRow = $menu->query_record('appeal', 7002);
|
|
$approve = call_action($menu, 'handle_process_appeal', 'aksrt_users_process_appeal_7002', [
|
|
'user_id' => '7002', 'decision' => 'approve', 'note' => '', 'record_version' => $menu->version($approveRow),
|
|
]);
|
|
|
|
$filtersHtml = render_ban_page(['page' => 'aksrt_user_ban', 'type' => 'report', 'status' => 'pending', 's' => 'needle', 'send_user' => '7', 'orderby' => 'updated', 'order' => 'ASC']);
|
|
|
|
echo json_encode([
|
|
'queue' => [
|
|
'total' => $all['total'], 'page' => $all['page'], 'counts' => $all['counts'], 'items' => count($all['items']),
|
|
'overlarge_page' => $overlargePage['page'], 'overlarge_items' => count($overlargePage['items']),
|
|
],
|
|
'filters' => $filters,
|
|
'html' => $html,
|
|
'filtered_html' => $filteredHtml,
|
|
'assets' => $GLOBALS['aksrt_test_assets'],
|
|
'actions' => [
|
|
'blank_report' => $blankReport, 'stale_report' => $staleReport, 'valid_report' => $validReport,
|
|
'blank_appeal' => $blankAppeal, 'valid_appeal' => $validAppeal, 'approve_appeal' => $approve,
|
|
'report_calls' => $GLOBALS['aksrt_test_report_actions'], 'messages' => $GLOBALS['aksrt_test_messages'],
|
|
'appeal_status' => \AKSRT\User\BanAppeal::get_status(7001),
|
|
'appeal_payload' => \AKSRT\User\BanAppeal::get_payload(7001),
|
|
'approved_status' => \AKSRT\User\BanAppeal::get_status(7002),
|
|
'restrictions_lifted' => \AKSRT\User\Restriction::$lifted,
|
|
],
|
|
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
|
|
}
|