/** * 第三方登录头像契约(参考主题 1:1)。 * * 硬约束: * 1) 第三方头像只在建档/首次绑定时补齐,之后不覆盖用户自己的选择 * (参考主题:`if ($args['avatar'] && !$custom_avatar)`)。 * 2) 解析顺序:上传头像 → 第三方头像 → 外部服务 → 默认头像。 * 3) 「恢复默认头像」必须同时清掉第三方头像,否则点了也换不掉。 * 4) 百度头像域名需要换成可访问的 himg.bdimg.com。 */ 'use strict'; const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const test = require('node:test'); const root = path.resolve(__dirname, '..', '..'); const read = (file) => fs.readFileSync(path.join(root, file), 'utf8'); test('第三方头像在解析链里位于上传头像之后、外部服务之前', () => { const helpers = read('inc/helpers/jio-avatar.php'); // 上传头像分支必须排在第三方头像之前。 const uploadAt = helpers.indexOf("get_user_meta($user_id, 'jio_avatar_attachment_id', true)"); const oauthAt = helpers.indexOf('jio_get_oauth_avatar_url($user_id)'); assert.ok(uploadAt >= 0 && oauthAt > uploadAt, 'uploaded avatar must win over the OAuth one'); // 第三方头像整体仍在外部头像服务之前。 const chain = helpers.slice(helpers.indexOf('function jio_get_avatar_url')); const customAt = chain.indexOf('jio_get_custom_avatar_url'); const externalAt = chain.indexOf('jio_get_external_avatar_url'); assert.ok(customAt >= 0 && customAt < externalAt); }); test('百度头像域名为可访问地址', () => { const helpers = read('inc/helpers/jio-avatar.php'); assert.match(helpers, /str_replace\('tb\.himg\.baidu\.com', 'himg\.bdimg\.com', \$url\)/); }); test('第三方头像只在空缺时写入,不覆盖用户头像', () => { const service = read('src/Auth/OAuthAccountService.php'); assert.match(service, /private static function seed_avatar\(int \$user_id, array \$identity\): void/); // 已有上传头像或已存第三方头像时直接返回,不写 meta。 assert.match(service, /\(int\) get_user_meta\(\$user_id, 'jio_avatar_attachment_id', true\) > 0\) \{\s*return;/); assert.match(service, /get_user_meta\(\$user_id, 'jio_oauth_avatar', true\)\) !== ''\) \{\s*return;/); // 两条写入路径(绑定 / 登录刷新)都改走同一守卫,不再直接写 meta。 const directWrites = service.match(/update_user_meta\(\$user_id, 'jio_oauth_avatar'/g) || []; assert.equal(directWrites.length, 1, 'only seed_avatar may write the OAuth avatar'); assert.equal((service.match(/self::seed_avatar\(/g) || []).length, 2); }); test('恢复默认头像会一并清除第三方头像', () => { const rest = read('src/Admin/UserControllerProfileMediaOperations.php'); const admin = read('src/User/ProfileAdmin.php'); assert.match(rest, /delete_user_meta\(\$user_id, 'jio_oauth_avatar'\)/); assert.match(admin, /delete_user_meta\(\$user_id, 'jio_oauth_avatar'\)/); });