diff --git a/src/Settings/UserRuntime.php b/src/Settings/UserRuntime.php index aef2d9c4..ca881667 100644 --- a/src/Settings/UserRuntime.php +++ b/src/Settings/UserRuntime.php @@ -178,7 +178,6 @@ class UserRuntime { 'public_entry' => !isset($settings['user_report_public_entry']) || !empty($settings['user_report_public_entry']), 'public_notice' => !isset($settings['user_report_public_notice']) || !empty($settings['user_report_public_notice']), 'ban_notice_text' => $ban_notice_text !== '' ? $ban_notice_text : __('当前账号处于限制状态,部分互动能力已关闭。', 'aksrt'), - 'categories' => self::parse_report_categories((string) ($settings['user_report_categories'] ?? "spam|垃圾信息\nabuse|人身攻击\ncopyright|版权投诉")), ], ]; } @@ -196,11 +195,26 @@ class UserRuntime { } } + /** + * 禁封/举报分区的运行时读取。 + * + * get_all() 是裸 option:用户从未保存过“禁封/举报”分区时, + * ban_preset_reason / user_report_img_s / user_report_desc 等键不存在, + * schema 默认值只活在后台 UI 里。参考主题 _pz($key, $default) 的语义是 + * 缺键即用默认值,因此这里改走 SchemaProvider 的带默认读取。 + */ + private static function read_report_section(): array { + $settings = class_exists('\AKSRT\Admin\SchemaProvider') + ? Settings::read_domain('users', 'report') + : []; + return is_array($settings) && $settings ? $settings : Settings::get_all(); + } + /** * 禁封设置 */ public static function ban_settings(): array { - $settings = Settings::get_all(); + $settings = self::read_report_section(); // 预置原因:group 数组 [{t:...}](对齐参考主题)或旧版每行一条文本 $reasons_raw = $settings['ban_preset_reason'] ?? null; @@ -251,7 +265,7 @@ class UserRuntime { * 举报设置 */ public static function report_settings(): array { - $settings = Settings::get_all(); + $settings = self::read_report_section(); return [ // 默认开启:对齐后台 schema default true 与参考主题 _pz('user_report_s', true)。 'enabled' => (bool) ($settings['user_report_s'] ?? $settings['user_report_enabled'] ?? true), @@ -390,32 +404,4 @@ class UserRuntime { unset($raw); return []; } - - /** - * @return array - */ - public static function parse_report_categories(string $raw): array { - $lines = preg_split('/[\r\n]+/', $raw, -1, PREG_SPLIT_NO_EMPTY); - $items = []; - - foreach ((array) $lines as $line) { - $parts = array_map('trim', explode('|', (string) $line)); - if (count($parts) < 2) { - continue; - } - - $slug = sanitize_key((string) $parts[0]); - $label = sanitize_text_field((string) $parts[1]); - if ($slug === '' || $label === '') { - continue; - } - - $items[] = [ - 'slug' => $slug, - 'label' => $label, - ]; - } - - return $items; - } } diff --git a/tests/widget-system/report-ban-contract.test.cjs b/tests/widget-system/report-ban-contract.test.cjs index aad3ca27..1f78bfe9 100644 --- a/tests/widget-system/report-ban-contract.test.cjs +++ b/tests/widget-system/report-ban-contract.test.cjs @@ -105,6 +105,12 @@ test('ban/report settings page mirrors the reference theme schema', () => { assert.match(runtime, /ban_settings\(\): array/) assert.match(runtime, /report_settings\(\): array/) assert.match(runtime, /user_report_s/) + // 缺键回退 schema 默认值(参考主题 _pz 语义):运行时经 read_domain 读取, + // 裸 get_all() 会让未保存过分区的站点拿不到 ban_preset_reason 默认值。 + assert.match(runtime, /read_domain\('users', 'report'\)/) + // 死链清理:user_report_categories 从不是真实存储键,解析器必须删除。 + assert.ok(!runtime.includes('parse_report_categories'), 'dead parse_report_categories must stay removed') + assert.ok(!runtime.includes('user_report_categories'), 'dead user_report_categories key must stay removed') const appeal = read('src/User/BanAppeal.php') assert.match(appeal, /ban_appeal_keys/) assert.match(appeal, /ban_appeal_desc/)