laoyang
|
203721b1fe
|
fix(avatar): 注册用户保留原头像;人脸风格肤色只留黄种人区间
#8 邮箱能在本站用户表查到的,一律用他自己的头像,不再替换
· 新增 yang_avatar_is_registered_email():get_user_by('email') 查表,
邮箱先 trim + strtolower 规范化(导入用户/插件写库/老数据都有大小写混用)
· 加请求内 static $memo 缓存:评论列表一页 20 条、同一个人常有 2~3 条,
不缓存就是同一个邮箱反复打库(实测 20 次 → 1 次)
· 新增 yang_avatar_keep_member() 读开关,运行时默认 '1'
· 过滤器在拼 data: URI 之前拦截,命中即原样 return $avatar
· 后台新增「注册用户保留原头像」复选框
· 关于「注册用户自己也没有真 Gravatar」:WP 的 get_avatar() 从不检查图上
是否存在,只拼 URL 交给浏览器;要分辨必须向 gravatar.com 发请求,
而本功能坚持零外网调用(发布脚本会断言)。因此做成开关、默认保留,
这类用户保持灰人像、不猜。
#9 肤色从 7 档收窄到 4 档,只留最浅到偏黄
· 移除 d9a066(偏深)、c68642(深棕)、8d5524(最深)
· 安全性依据:Prng::pick() 用 integer(0, count-1) 取索引,只消耗一次
next(),与区间跨度无关 ⇒ 缩短数组不改变 PRNG 消耗次数,发型/衣着/
表情/背景抽到的结果一点不变,只有肤色跟着变
(已用 _v39_isolate.php 逐字节证明:7 色与 4 色渲染除肤色外完全相同)
顺带修掉一个老 bug:baseColor 错当肤色
· bottts 的 baseColor 是机器人外壳色(19 种彩色),映射成肤色后外壳被
涂成肉色 e8b98f / f1c27d。从 $map 里去掉 'baseColor' => 'skinColor'
· 「base」这名字像是底色,但各家风格语义并不统一,不能按名字猜
开关位置(踩过的坑)
· 新开关必须排在「头像风格」之前。风格列表是 18 张带缩略图的卡片、
实测高约 2100px,排在它后面的控件会落到 y≈2327px,而设置页视口
约 1000px —— 用户不滚三屏根本看不到。3.2.36 就是栽在这里。
挪到之前后实测 y=216px、首屏可见。
验证
_v39_probe.php 5 / 0 肤色收窄 + bottts 修复
_v39_isolate.php 50 / 0 「只改肤色、其它不变」逐字节隔离证明
_v39_member.php 19 / 0 注册用户判据(含缓存次数精确断言)
_v39_falsify.py 8 / 8 上述判据反向
_guard337_layout.py 25 / 0 布局守卫(新增开关位置三项)
_guard337_layout_falsify.py 5 / 5
_guard336_avatar.py 55 / 0 源码守卫
_guard336_falsify.py 17 / 17
_geo337_avatar_reach.py 34 / 0 真实几何 + 显隐交互
_smoke18.py 18 / 0 18 套风格全量冒烟
_verify4_prod.php 80 / 0 逐字节对官方(对配色无感,见 docblock)
_pkgcheck339.py 52 / 0 包内内容契约
_pkgcheck339_falsify.py 20 / 20 包内断言反向
回归 88/0、56/0、77/0、13/0;93 个 php -l 全通过
PHP 8.4.25 与 8.5.12 严格错误级别均 0 警告
Refs #8 #9
|
2026-10-25 20:19:27 +08:00 |
|
laoyang
|
16cc7d8328
|
3.2.38 自动头像补 4 套风格:avataaars / bottts 及其带底色版 #7
上一版只收录 14 套,把 avataaars、bottts 两个系列漏掉了。原因是 3.2.36
盘点时,这四套的 npm 包里 license 字段写的是「See LICENSE file」,被我
当成「措辞不明、先不收」。点进去看实际条款是
「Free for personal and commercial use」(设计者 Pablo Stanley,
来源 avataaars.com / bottts.com),而且不要求署名 —— 比收录的 CC BY
那十几套还宽松。方向判断反了,这是错误,不是许可限制。
改动:
- 新增 inc/avatar-styles/ 四份模板:avataaars、avataaars_neutral、
bottts、bottts_neutral(合计 227 KB,风格总数 14 → 18)
- yang_avatar_styles() 注册四套中文名与说明,排在「首字母」之后
- avataaars 的 onPostCreate 三条规则逐条复刻:
① style 组为 circle 时清空背景;
② 背景恰好只剩 65c9ff 一项时清空(判「恰好只有一个」,不是「包含」);
③ 戴头巾且胡子概率非 100 时去掉胡子。
为此 yang_avatar_post_create() 增加 $picked 形参(官方读
components.style.name / components.top.name,不传拿不到),
返回值由 2 项改为 3 项($on 会被改,必须带出来)。
- 后台风格说明由「都是 CC0 或 MIT 许可」改为「都可自由使用与商用,
且不要求署名」—— 加了这四套后前者已不准确
- 文件头许可清单补上「作者自定义许可」一类
验证(先证明判据真能红,再谈通过):
- 逐字节 80/0:四套各 20 种种子(含中文、emoji、超长、空串)比对官方
Node 库。第一版 avataaars 20 个全错,差异正是背景那块天蓝,补规则后对齐
- 逐字节反向 3/3:删分支、不清 65c9ff、返回值退 2 项,各红 20 项
- 规则白盒 9/0:circle / 恰好 65c9ff / 多色保留 / 含 65c9ff 不只一项保留 /
头巾 10% 删胡子 / 头巾 100% 保留胡子 / 不戴头巾不受影响 / 别风格不受影响 /
返回 3 项
- 规则反向 6/6:写坏任一分支,都恰好在预期那条上报错
- 原有 14 套回归 108/0(原 84 + 新 24)
- 18 套全量冒烟:每套合法 SVG、三种种子互异
- 严格错误级别 PHP 8.4.25 与 8.5.12(线上同版)各 47/0
- 几何+交互 29/0:18 卡片、18 单选、18 缩略图全部解码
- 源码守卫 55/0,反向 17/17
- 包内契约 34/0,反向 8/8
- 后台标签 88/0、CDN 56/0 与 77/0、3.2.28 13/0
- 93 个 php 文件 php -l 全通过
顺带修正两处错误的守卫(都是这次暴露出来的):
- _guard336_avatar.py 把 avataaars / bottts 错列进「CC BY 禁止收录」
清单,改按实测许可证重写(CC BY 实为 13 套,不含这两个)
- _guard336_falsify.py 的 F2 锚点仍在匹配旧名「自动头像」,3.2.37
改名后恒失效;版本锚点也停在上一个版本
|
2026-10-25 19:41:49 +08:00 |
|
laoyang
|
3fcaf25c58
|
3.2.36 新增「自动头像」:按邮箱本地生成,14 套 CC0/MIT 风格可选 #5
为没有头像的访客按邮箱确定性地生成一张 SVG 头像,替代 Gravatar
那个灰底"神秘人"(cn.gravatar.com 在国内已超时,不勾加速时头像
干脆是空白)。全程纯 PHP,零外网请求、零落盘。
后台「主题设置」新增「自动头像」复选框 + 风格列表:勾上之后才
出现 14 套风格,点一下即时换 16 格预览,保存后全站生效。
实现要点(都是踩出来的):
- PRNG 必须与 DiceBear 9.x 逐位一致:xorshift + hashSeed 全程跑在
JS 的 int32 语义里,PHP 64 位整数要逐步 i32() 归一;
charCodeAt 按 UTF-16 码元取值,emoji 必须真做代理对拆分。
- pickComponent 有简繁两版:只有 glass/rings/shapes/thumbs 额外取
三次整数(rotation/offsetX/offsetY)。给简版也补三次 ⇒ PRNG 多走
3N 步 ⇒ 31 套里 27 套全错。编译期算 pc_has_ints 才治得住。
- 自带人类调色板:官方默认配色几乎全单值,30 个邮箱只出 2 种配色,
那才是"默认头像丑"的真因,光换画风解决不了。
- 只收录 CC0/MIT(13 CC0 + 1 MIT),CC BY 那 13 套要求署名,一律不收——
主题装给用户用,用户不会维护署名,收进来等于转嫁合规义务。
接入 get_avatar 的两个关键修正:
- 必须先看原 src 是不是 Gravatar 家族域名再决定是否替换。原先无条件
替换会把媒体库头像、外链头像、别的插件处理过的 data: 头像一起盖掉。
- 必须删 srcset。只改 src 留着 srcset,浏览器优先用 srcset,
生成的图根本不会被加载(现象是"代码明明换了,页面还是老样子"),
且不能重建 <img> 标签(会丢掉评论头像 CSS 依赖的 class)。
后台三处必须这么做:
- body class 由 PHP 输出(admin_body_class),否则每次进设置页/保存后
重载都会先显示风格列表再藏起来,闪一下。
- 事件监听 radio 的 change,不能监听 label 的 click —— label 会把
click 转发给关联 input,冒泡回来再触发一次 ⇒ 同一风格发两次请求
(实测 hits 2→4)。
- 首屏已渲染的 16 格写进 JS 缓存,否则点一圈回到默认风格会白请求一次。
不依赖任何可选扩展:不用 mbstring(未安装时 mb_substr 是 Fatal error,
整站白屏)、不用 gd/imagick。UTF-8 切分/截断/大写全部自己实现。
PHP 7.0 语法,PHP 8.5 下 E_ALL 无任何 warning。
验证:
- 14 套 × 6 种子 = 84 个用例与 DiceBear 官方 Node 输出逐字节一致,
PHP 8.4 / 8.5 / 无 mbstring(php -n)三种环境均 84/0。
- 静态守卫 55/0;反向验证 17 项注入全部被捕获。
- 后台面板浏览器验证 26/0(显隐、几何、点选、缓存、连点、零报错)。
- 包内内容契约 24/0;包校验反向验证 6 项注入全部被捕获。
- 单次渲染稳态 0.047~0.105ms,峰值内存 2~4MB。
|
2026-10-25 18:38:11 +08:00 |
|