true]; } } } namespace { define('ABSPATH', dirname(__DIR__, 2) . DIRECTORY_SEPARATOR); define('ARRAY_A', 'ARRAY_A'); class WP_User { public function __construct(public int $ID, public string $display_name) {} } class WP_User_Query {} class WP_Post { public string $post_status = 'publish'; public function __construct(public int $ID) {} } class WP_REST_Request { public function __construct(private array $params = []) {} public function get_json_params(): array { return $this->params; } public function get_param(string $key) { return $this->params[$key] ?? null; } } class WP_REST_Response { public function __construct(private array $data = [], private int $status = 200) {} public function get_data(): array { return $this->data; } public function get_status(): int { return $this->status; } } require_once ABSPATH . 'src/Messages/ReportCenter.php'; require_once ABSPATH . 'src/Settings/UserRuntime.php'; require_once ABSPATH . 'src/Admin/UserControllerReportOperations.php'; final class TestWpdb { public string $prefix = 'wp_'; public int $insert_id = 0; public string $last_error = ''; public bool $fail_insert = false; public array $rows = []; public array $insert_calls = []; private int $next_id = 1; private array $last_args = []; public function prepare(string $query, ...$args): string { if (count($args) === 1 && is_array($args[0])) { $args = $args[0]; } $this->last_args = $args; return $query; } public function insert(string $table, array $data, array $format = []) { $this->insert_calls[] = [$table, $data, $format]; if ($this->fail_insert) { return false; } $id = $this->next_id++; $this->insert_id = $id; $this->rows[] = array_merge(['id' => $id], $data, ['notes_json' => '[]']); return 1; } public function get_var(string $query) { if (str_contains($query, 'reporter_id = %d')) { [$reporter_id, $target_type, $target_id] = array_pad($this->last_args, 3, null); foreach ($this->rows as $row) { if ((int) $row['reporter_id'] === (int) $reporter_id && (string) $row['target_type'] === (string) $target_type && (int) $row['target_id'] === (int) $target_id && (string) $row['status'] === 'pending' ) { return (int) $row['id']; } } return null; } if (str_contains($query, 'COUNT(*)') && str_contains($query, 'target_type = %s')) { [$target_type, $target_id] = array_pad($this->last_args, 2, null); return count(array_filter($this->rows, static fn (array $row): bool => (string) $row['target_type'] === (string) $target_type && (int) $row['target_id'] === (int) $target_id )); } return 0; } public function get_results(string $query, $output = null): array { if (str_contains($query, 'GROUP BY status')) { $counts = []; foreach ($this->rows as $row) { $status = (string) ($row['status'] ?? ''); $counts[$status] = ($counts[$status] ?? 0) + 1; } $results = []; foreach ($counts as $status => $count) { $results[] = ['status' => $status, 'cnt' => $count]; } return $results; } $rows = $this->rows; $index = 0; foreach (['status', 'category', 'target_type'] as $field) { if (str_contains($query, $field . ' = %s')) { $value = (string) ($this->last_args[$index++] ?? ''); $rows = array_values(array_filter($rows, static fn (array $row): bool => (string) ($row[$field] ?? '') === $value )); } } return $rows; } public function get_row(string $query, $output = null) { $id = (int) ($this->last_args[0] ?? 0); foreach ($this->rows as $row) { if ((int) $row['id'] === $id) { return $output === ARRAY_A ? $row : (object) $row; } } return null; } public function update(string $table, array $data, array $where, array $format = [], array $where_format = []) { unset($table, $format, $where_format); foreach ($this->rows as &$row) { if ((int) ($row['id'] ?? 0) === (int) ($where['id'] ?? 0)) { $row = array_merge($row, $data); unset($row); return 1; } } unset($row); return false; } } final class ReportFixtureController { use \Jio\Admin\UserControllerReportOperations; protected function success($data = [], int $status = 200): WP_REST_Response { return new WP_REST_Response(array_merge(['success' => true], $data), $status); } protected function error(string $message, int $status = 400): WP_REST_Response { return new WP_REST_Response(['success' => false, 'message' => $message], $status); } protected function get_json_params(WP_REST_Request $request): array { return $request->get_json_params(); } private function build_admin_user_summary(int $user_id, $user): array { return [ 'id' => $user_id, 'display_name' => $user ? $user->display_name : '', 'email' => '', ]; } } function __(string $text, string $domain = ''): string { return $text; } 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 esc_url_raw($url): string { return (string) $url; } function wp_kses_post($value): string { return strip_tags((string) $value); } function current_time(string $type): string { unset($type); return '2026-10-30 12:00:00'; } function wp_json_encode($value): string { return json_encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?: '[]'; } function get_current_user_id(): int { return (int) ($GLOBALS['jio_test_user_id'] ?? 0); } function get_userdata(int $user_id) { return $user_id > 0 ? new WP_User($user_id, 'Reporter ' . $user_id) : false; } function get_users(array $args = []): array { unset($args); return [901]; } function admin_url(string $path = ''): string { return 'https://example.test/wp-admin/' . ltrim($path, '/'); } function get_post(int $id) { return $id > 0 ? new WP_Post($id) : false; } function get_the_title($post): string { return 'Article #' . (is_object($post) ? $post->ID : (int) $post); } function get_permalink($post): string { return 'https://example.test/post/' . (is_object($post) ? $post->ID : (int) $post); } function do_action(string $hook, ...$args): void { if ($hook === 'jio_report_submitted') { $GLOBALS['jio_test_actions'][] = $args; } } if (!function_exists('mb_substr')) { function mb_substr(string $text, int $start, ?int $length = null): string { return $length === null ? substr($text, $start) : substr($text, $start, $length); } } function reset_report_fixture(array $preset_names = ['垃圾信息', '人身攻击']): void { $GLOBALS['wpdb'] = new TestWpdb(); $GLOBALS['jio_test_user_id'] = 42; $GLOBALS['jio_test_actions'] = []; $GLOBALS['jio_test_messages'] = []; $GLOBALS['jio_test_claims'] = []; \Jio\User\Restriction::$calls = []; \Jio\Settings\Settings::$values = [ 'ban_preset_reason' => array_map(static fn (string $name): array => ['t' => $name], $preset_names), 'user_report_img_s' => true, ]; } function submit_report_case(array $payload): WP_REST_Response { return (new ReportFixtureController())->submit_report(new WP_REST_Request($payload)); } function snapshot_response(WP_REST_Response $response): array { $wpdb = $GLOBALS['wpdb']; return [ 'response' => $response->get_data(), 'status' => $response->get_status(), 'rows' => $wpdb->rows, 'insert_calls' => $wpdb->insert_calls, 'actions' => $GLOBALS['jio_test_actions'], 'messages' => $GLOBALS['jio_test_messages'], 'claims' => $GLOBALS['jio_test_claims'], ]; } $results = []; reset_report_fixture(['垃圾信息', '人身攻击']); $results['runtime_reasons'] = \Jio\Settings\UserRuntime::ban_settings()['reasons']; reset_report_fixture(); $results['preset_with_evidence'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 73, 'category' => '垃圾信息', 'reason' => '补充详情 https://example.test/uploads/proof.png', ])); reset_report_fixture(); $results['preset_label_only'] = snapshot_response(submit_report_case([ 'target_type' => 'comment', 'target_id' => 88, 'category' => '人身攻击', 'reason' => '', ])); reset_report_fixture(['0']); $results['falsey_text'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 90, 'category' => '0', 'reason' => '0', ])); $long_label = '非常长的预置举报分类名称超过数据库原先四十字符限制并且应完整保留在工单及后台列表当中'; reset_report_fixture([$long_label]); $results['long_preset_label'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 19, 'category' => $long_label, 'reason' => '', ])); reset_report_fixture(); $results['other_with_details'] = snapshot_response(submit_report_case([ 'target_type' => 'comment', 'target_id' => 99, 'category' => '其他原因', 'reason' => '请核查相关资料', ])); reset_report_fixture(); $results['sanitized_snapshot'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 12, 'category' => ' 垃圾信息 ', 'reason' => '补充详情', ])); reset_report_fixture(); $results['blank_category'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 5, 'category' => '', 'reason' => '详情', ])); reset_report_fixture(); $results['missing_other_details'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 5, 'category' => '其他原因', 'reason' => ' ', ])); reset_report_fixture(); $results['unknown_category'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 5, 'category' => '未配置的分类', 'reason' => '详情', ])); reset_report_fixture(); $results['hash_category'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 5, 'category' => 'ab73c91f054e', 'reason' => '详情', ])); reset_report_fixture(); $GLOBALS['jio_test_user_id'] = 0; $results['unauthenticated'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 5, 'category' => '垃圾信息', 'reason' => '', ])); reset_report_fixture(); $results['invalid_target'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 0, 'category' => '垃圾信息', 'reason' => '', ])); reset_report_fixture(); $GLOBALS['wpdb']->fail_insert = true; $GLOBALS['wpdb']->insert_id = 777; $results['insert_failure'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 5, 'category' => '垃圾信息', 'reason' => '含有举证', ])); reset_report_fixture(); $GLOBALS['wpdb']->rows[] = [ 'id' => 51, 'reporter_id' => 42, 'target_type' => 'post', 'target_id' => 73, 'reason' => '既有详情', 'category' => '垃圾信息', 'status' => 'pending', 'created_at' => '2026-10-30 11:00:00', 'updated_at' => '', 'notes_json' => '[]', ]; $results['duplicate'] = snapshot_response(submit_report_case([ 'target_type' => 'post', 'target_id' => 73, 'category' => '垃圾信息', 'reason' => '重复提交', ])); reset_report_fixture(['涉嫌侵权']); $admin_controller = new ReportFixtureController(); $submit_response = submit_report_case([ 'target_type' => 'post', 'target_id' => 31, 'category' => '涉嫌侵权', 'reason' => '', ]); $list_response = $admin_controller->get_report_list(new WP_REST_Request(['category' => '涉嫌侵权'])); $list_data = $list_response->get_data()['data'] ?? []; $detail_response = $admin_controller->get_report_detail(new WP_REST_Request(['id' => 1])); $detail_data = $detail_response->get_data()['data'] ?? []; $results['admin_category'] = [ 'submit_success' => !empty($submit_response->get_data()['success']), 'list_items' => $list_data['items'] ?? [], 'list_options' => $list_data['options']['categories'] ?? [], 'detail_report' => $detail_data['report'] ?? [], ]; reset_report_fixture(); $service_id = \Jio\Messages\ReportCenter::get_instance()->submit(42, 'post', 6, '详情', ''); $results['service_blank_category'] = [ 'id' => $service_id, 'rows' => $GLOBALS['wpdb']->rows, 'insert_calls' => $GLOBALS['wpdb']->insert_calls, ]; reset_report_fixture(['提交时的分类', '待删除的分类']); $first_snapshot_submit = submit_report_case([ 'target_type' => 'post', 'target_id' => 61, 'category' => '提交时的分类', 'reason' => '', ]); $second_snapshot_submit = submit_report_case([ 'target_type' => 'post', 'target_id' => 62, 'category' => '待删除的分类', 'reason' => '', ]); $admin_controller = new ReportFixtureController(); \Jio\Settings\Settings::$values['ban_preset_reason'] = [['t' => '当前新分类']]; $changed_list = $admin_controller->get_report_list(new WP_REST_Request())->get_data()['data'] ?? []; \Jio\Settings\Settings::$values['ban_preset_reason'] = []; $removed_list = $admin_controller->get_report_list(new WP_REST_Request())->get_data()['data'] ?? []; $first_detail = $admin_controller->get_report_detail(new WP_REST_Request(['id' => 1]))->get_data()['data']['report'] ?? []; $second_detail = $admin_controller->get_report_detail(new WP_REST_Request(['id' => 2]))->get_data()['data']['report'] ?? []; $results['category_snapshot'] = [ 'submit_success' => !empty($first_snapshot_submit->get_data()['success']) && !empty($second_snapshot_submit->get_data()['success']), 'changed_list_categories' => array_column($changed_list['items'] ?? [], 'category'), 'changed_list_options' => array_column($changed_list['options']['categories'] ?? [], 'value'), 'removed_list_categories' => array_column($removed_list['items'] ?? [], 'category'), 'details' => [ (string) ($first_detail['category'] ?? ''), (string) ($second_detail['category'] ?? ''), ], ]; reset_report_fixture(['人身攻击']); $GLOBALS['wpdb']->rows[] = [ 'id' => 101, 'reporter_id' => 42, 'target_type' => 'user', 'target_id' => 701, 'reason' => '', 'category' => '人身攻击', 'status' => 'pending', 'created_at' => '2026-10-30 11:00:00', 'updated_at' => null, 'notes_json' => '[]', ]; $preset_process = (new ReportFixtureController())->process_report(new WP_REST_Request([ 'id' => 101, 'status' => 'resolved', 'action_taken' => 'warn', 'note' => '', ])); $preset_row = $GLOBALS['wpdb']->rows[0]; $results['process_preset_only'] = [ 'success' => !empty($preset_process->get_data()['success']), 'restriction' => \Jio\User\Restriction::$calls[0] ?? [], 'report_reason' => $preset_row['reason'], 'report_category' => $preset_row['category'], ]; reset_report_fixture(); $custom_reason = '自定义说明不能丢'; $GLOBALS['wpdb']->rows[] = [ 'id' => 102, 'reporter_id' => 42, 'target_type' => 'user', 'target_id' => 702, 'reason' => $custom_reason, 'category' => '其他原因', 'status' => 'pending', 'created_at' => '2026-10-30 11:00:00', 'updated_at' => null, 'notes_json' => '[]', ]; $other_process = (new ReportFixtureController())->process_report(new WP_REST_Request([ 'id' => 102, 'status' => 'resolved', 'action_taken' => 'warn', 'note' => '', ])); $other_row = $GLOBALS['wpdb']->rows[0]; $results['process_other_with_details'] = [ 'success' => !empty($other_process->get_data()['success']), 'restriction' => \Jio\User\Restriction::$calls[0] ?? [], 'report_reason' => $other_row['reason'], 'report_category' => $other_row['category'], ]; echo json_encode($results, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR); }