Files
wordpress-kratos-yang/functions.php
T
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

80 lines
3.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 模板函数
* @author Yongquan Yang <yangyq.net>
* @license MIT License
* @version 2020.03.17
*/
define('THEME_VERSION', wp_get_theme()->get('Version'));
// 主题配置
require get_template_directory() . '/inc/options-framework/autoload.php';
// 自定义代码(CSS / JS,存选项表而非主题目录)
require get_template_directory() . '/inc/theme-custom-code.php';
// 更新配置
require get_template_directory() . '/inc/update-checker/autoload.php';
// 核心配置
require get_template_directory() . '/inc/theme-core.php';
// 图片类选项的默认值(Logo/favicon/404/分享图… 空值时落到包内默认图)。
// 必须排在 theme-core.php 之后:它要用 ASSET_PATH 与 kratos_option。
require get_template_directory() . '/inc/theme-option-defaults.php';
// 站点配置
require get_template_directory() . '/inc/theme-setting.php';
// 纪念日自动哀悼(按日期判断,需在 theme-setting 之后,
// 因为它用到 kratos_option)
require get_template_directory() . '/inc/theme-mourning.php';
// 哀悼说明页(固定路径 /memory,由主题判定路由,不写数据库)
require get_template_directory() . '/inc/theme-mourning-page.php';
// 文章配置
require get_template_directory() . '/inc/theme-article.php';
// 评论区(统一渲染 + AJAX + 评论通知)。
// 必须在 theme-article.php 之后:后者不再定义评论函数,
// 但评论模板 comments.php 里引用的 comment_callbacks 由本文件提供。
// 也必须早于 theme-mail.php(评论通知要调 yang_mail_render)。
require get_template_directory() . '/inc/theme-comments.php';
// 小工具配置
require get_template_directory() . '/inc/theme-widgets.php';
// 文章增强
require get_template_directory() . '/inc/theme-shortcode.php';
// 文章目录([TOC] 短代码)
require get_template_directory() . '/inc/theme-toc.php';
// 添加导航目录
require get_template_directory() . '/inc/theme-navwalker.php';
// 对象存储配置
require get_template_directory() . '/inc/theme-dogecloud.php';
// CDN 加速(地址改写:CDN 地址 + 白名单 + 黑名单)。
// 必须排在 theme-core.php 之后:它要用 kratos_option 与 wp_parse_url。
// 挂在 template_redirect 上开输出缓冲,所以本文件晚加载不影响生效。
require get_template_directory() . '/inc/theme-cdn.php';
// 自动头像:为没有头像的访客按邮箱生成一张(纯 PHP,零外网请求)。
// 必须排在 theme-core.php 之后:它要用 kratos_option。
// 它挂在 get_avatar 过滤器上(优先级 20,晚于 theme-core.php 里
// 那个改 Gravatar 域名的过滤器),所以要保证 theme-core.php 先加载。
require get_template_directory() . '/inc/theme-avatar.php';
// 邮件模板:必须先于 theme-mail.php 加载,
// 因为后者在发信时会调用 yang_mail_render()
require get_template_directory() . '/inc/theme-mail-template.php';
// 邮件治理:统一接管发信通道、去重、关掉重复通知
require get_template_directory() . '/inc/theme-mail.php';
// SMTP 配置(连通性相关,实际接管在 theme-mail.php)
require get_template_directory() . '/inc/theme-smtp.php';