在主题设置页做一个访问统计面板:网站加一段第三方统计代码,我们在后端调用他们的 API,把数据显示在主题设置页面里。
这是一个需求,内含三个可独立验收的部分,但必须一起才算完成(少任何一步面板都不可用),所以不拆单:
① 前端埋点
hm.js
seo_statistical
② 后端拉数据
ACCESS_TOKEN
refresh_token
③ 后台面板
info
<script>
"--"
(int)"--" === 0
<head>
php -l
百度统计的 API Key / Secret Key,以及完成一次 OAuth 授权拿到 refresh_token。没有这些我无法端到端验证真实数据,只能验证降级路径。
实测该服务器 2 核 / load 2.28(已近满载),Umami 容器 183~255MB + PostgreSQL,官方最低要求 1GB 内存整机。内存够但 CPU 不够,会明显加重现有负载。除非先上 Redis 对象缓存把基线压下来,否则不碰。
代码提交:c125388(已推送 main) 发布包:https://yangyq.net/theme-update/kratos_yang-4.1.0.zip md5:5eeaca87ae06d0a4c92adaaa3f293c67 (update.json 已指向 4.1.0,后台「外观 → 主题」应能看到升级提示)
c125388
https://yangyq.net/theme-update/kratos_yang-4.1.0.zip
5eeaca87ae06d0a4c92adaaa3f293c67
update.json
① 前台能看到统计代码,且只在开关打开时输出 ✅
footer.php 把原有一行改成:
footer.php
if (yang_stat_tracking_enabled() && kratos_option('seo_statistical')) { echo '<p>' . kratos_option('seo_statistical') . '</p>'; }
开关是新增的 stat_track_enable(复选框),默认开。三态处理:从未配置 ⇒ 开(和你原来的行为一致)、显式勾选 ⇒ 开、显式取消 ⇒ 关。false 被当成"用户主动关掉"而不是"没配置"——这是 of_sanitize_checkbox 未勾选写 false 带来的坑,判据专门钉了这一条。
stat_track_enable
false
of_sanitize_checkbox
② 设置页出现统计面板并显示真实数字 ⚠️ 代码就绪,等你补凭据
面板、13 个指标、缓存、自动续期全都做完了。但你还没有填凭据,所以现在打开设置页会看到一块引导("还没有接通百度统计" + 四步操作指引),不是数字。这是有意的:未配置时不打任何接口,不可能卡住。
③ 凭据错误时优雅降级 ✅
取数失败 ⇒ 面板显示「统计暂不可用」+ 具体原因,下面一行「设置页其它部分不受影响,可以照常修改并保存」。设置页其余控件完全正常。
1. 刷新按钮是摆设 —— 面板 JS 点「刷新数据」会发 force=1,AJAX 处理器也读出了 $force,然后把它丢了,转头调渲染函数不带参数。后果:成功缓存 1800 秒,用户点刷新拿到的还是同一份数据,时间戳都不变,按钮看起来完全没反应。而"面板渲染"和"缓存"两段判据当时全绿——每一步单独看都对。修法是把 $force 一路传到 yang_stat_fetch(),并且加了 8 条判据(静态 4 条 + 真调 AJAX 的行为 4 条)专门盯这个参数链路。
force=1
$force
yang_stat_fetch()
2. 百度统计的错误格式和文档不一样 —— 我加了真实接口连通性测试(_stat_api_real.php),实测:
_stat_api_real.php
{"error":"invalid_client","error_description":"unknown client id"}
{"error_code":110,"error_msg":"Access token invalid or no longer valid"}
第一版代码只判了 200 和 error 字段,两种情况都会报成"接口返回里找不到 result 节点"——一句完全指向错误方向的话。已改成三种格式都认,token 失效还会额外提示「请重新走一次授权」。
200
error
3. yang_stat_num(1234.0) 返回 float 不返回 int —— is_float() 分支直接 return,跳过了整型归一,下游按类型分支的判断全错。
yang_stat_num(1234.0)
is_float()
wp-content/uploads/.yang-stat-credentials.php
views
_stat410.php
_stat410_falsify.php
_mkzip410.py
_mkzip410_falsify.py
_publish410_falsify.sh
发布流程按红线执行:只写 theme-update/,线上主题目录未被覆盖(脚本有断言:kratos_yang/style.css 仍是 4.0.0、目录里没有 theme-stat.php)。PUC 已实测能读到 4.1.0(直接调 checkForUpdates() 拿到的 version=4.1.0、package 指向本版包)。
theme-update/
kratos_yang/style.css
theme-stat.php
checkForUpdates()
顺带修了发布脚本自己三处判据缺陷:while read 里 ssh 吃掉 stdin 导致只 lint 了 1 个文件却报"全部通过"(假绿)、本地拿远端 php 路径解析 JSON 失败后空值走了 ok 分支(假绿)、把第三方 vendor 的 Deprecated 当语法错误(假红)。
while read
ssh
1. 在后台点升级(外观 → 主题 → 检查更新 → 升级到 4.1.0)
升级完告诉我,我要做两件收尾:重设 theme-update 目录 ACL(升级会重置权限),以及清 PUC transient 让后台立刻稳定显示 4.1.0。
theme-update
2. 补百度统计凭据(这是面板出真数字的前提)
昨天你问「百度统计是不是停止维护了」——查证了,产品正常在维护。但有个更要紧的发现需要你核对:
你填的那串 192a62f2ae923a591128f92554cc80e0,在百度统计侧不是一个有效站点。
192a62f2ae923a591128f92554cc80e0
我是这么验的(交叉对照):
96951609…
youth.cn
yangyq.net
192a62f2…
规律很清楚:有效 hash + 任意 Referer → 30278 字节;无效 hash → 恒 0 字节(无 Referer 时连有效 hash 也返回 0,所以不能用 curl 直接判埋点)。
也就是说,主题注入的代码完全正确(标准片段、async:true、HTTP 200 全部对),问题在百度后台这个 site_id 没有生效。麻烦你到「管理 → 网站列表」看一下 yangyq.net 那一行:域名是否填对、状态是否在"正常"、是不是建了但没提交校验。
async:true
这不阻塞代码——凭据和有效站点补齐后,面板立刻能出真数字。
发布反证脚本(_publish410_falsify.sh)为了测「PUC 读到错包地址时判据会不会红」, 临时把线上 update.json 改成指向 kratos_yang-9.9.9-nonexistent.zip, 跑完立刻用 printf 还原,并做了字节级复核:
kratos_yang-9.9.9-nonexistent.zip
printf
[OK] update.json 已还原 [OK] 公网复核:update.json 内容与原文逐字节一致
两条全绿,看起来干净。但真实状态是:后台点「升级到 4.1.0」会下载 404。
测试那一下调用了 $myUpdateChecker->checkForUpdates(),PUC 把假地址 写进了 site_transient('update_themes')。transient 里的 response['kratos_yang']['package'] 是独立于 update.json 的一份拷贝, 还原文件不会让它失效 —— 而前台「检查更新」读的正是这份缓存,默认最长 12 小时。
$myUpdateChecker->checkForUpdates()
site_transient('update_themes')
response['kratos_yang']['package']
实测证据(独立 PHP 进程读 transient):
RESP kratos_yang => new=4.1.0 url=https://yangyq.net/theme-update/kratos_yang-9.9.9-nonexistent.zip
线上:delete_site_transient('update_themes') + 强制 PUC 重拉, 独立进程复核,当前终态:
delete_site_transient('update_themes')
FINAL new=4.1.0 pkg=https://yangyq.net/theme-update/kratos_yang-4.1.0.zip FINAL_VERDICT=CLEAN
且 update.json、主题目录均未被污染(无 9.9.9 残留,theme-stat.php 仍不存在, 线上主题仍是 4.0.0 —— 红线守住)。
9.9.9
反证脚本:新增「2c. 清掉 PUC 缓存里残留的错包地址」段,还原文件之后显式清 transient, 并断言缓存里必须是正确地址(不是"没有 nonexistent"就算过 —— 空也是错):
[OK] 缓存已回到正确包地址(https://yangyq.net/theme-update/kratos_yang-4.1.0.zip) [OK] PUC 复读版本号仍是 4.1.0
反证现为 23 通过 / 0 失败(原 21 条 + 新增 2 条)。
记忆:记为红线 #496(反证还原了文件却没还原由文件派生的缓存)。
delete_site_transient() 之后立刻 get_site_transient() 读到"还在"是正常的 —— PUC 走 site_transient_update_themes 过滤器注入(见 #495),删完一读就重新填充。 所以不能用 $t === false 判"清干净了",要判重新填充出来的内容对不对。 这一点让"删除 → 复核"这条最直觉的写法假红,差点让我以为清不掉。
delete_site_transient()
get_site_transient()
site_transient_update_themes
$t === false
没有影响。修复后后台检查更新读到的就是正确的 4.1.0 包地址, 可以直接点升级。这个小插曲只在"反证跑完到发现它"的这几分钟内存在, 且当时并无用户在点升级。
4.1.0
前面六套判据全绿之后,我做了一件之前没做的事:把发布包解到服务器上, 在真实 WordPress + PHP 8.5 里加载 4.1.0 的 theme-stat.php。 本地判据都是桩环境(_stat410.php 自带一套假的 kratos_option/get_option), 桩能证明逻辑对,证明不了它在真 WP 里不炸、也证明不了它输出给用户的是什么样子。
kratos_option
get_option
yang_stat_render_shell() 渲染出的 HTML:
yang_stat_render_shell()
<li>把下面这个地址粘到浏览器,用**你自己的百度账号**登录并同意授权:</li>
浏览器会原样显示两个星号。同批还有一处,在 stat_track_enable 的 desc 里 (代码本身**不会被删除**),以及 readme 里一处(这十三项**都能单独关掉**)。
desc
代码本身**不会被删除**
这十三项**都能单独关掉**
根因是这个项目的 PHP 注释/文档习惯用 **加粗** 写重点, 这串文字被搬进 HTML 字符串和 __() 文案时,星号就跟着进去了。
**加粗**
__()
三处 **…** → <b>…</b>,inc/theme-stat.php、inc/theme-options.php 各一行,readme 由 _readme410.py 重新生成。
**…**
<b>…</b>
inc/theme-stat.php
inc/theme-options.php
_readme410.py
<b>
**
关键细节:判据必须先剥 PHP 注释再判 —— 否则会把所有用 ** 写重点的 技术注释都误报(本项目注释里到处都是)。
_stat410.php 自己跑不起来。文件头文档写「跑法:php _stat410.php」, 但 $GLOBALS['__theme_dir'] 只有反证脚本会注入,直接跑就 Fatal error: Failed opening required '/inc/theme-stat.php'。 判据脚本自己跑不起来 = 零判据绿灯,比假绿更难发现。 ⇒ 加回落路径;找不到被测文件时 exit 2 并明说「没跑任何判据,这不是通过」。
php _stat410.php
$GLOBALS['__theme_dir']
Fatal error: Failed opening required '/inc/theme-stat.php'
exit 2
_publish410.sh 的 LOCAL_RD 默认值指向上一版遗留文件。 默认写的是 /d/tmp/readme410.html,而 _readme410.py 的真实输出是 /d/tmp/_readme_410.html。首跑就把上一版 readme 传上去了, 出现 1 条失败;我第二次跑时手工加了 YANG_LOCAL_RD=... 又"好了"。 「失败一次、重跑就好」这种偶发最容易被当成网络抖动糊过去, 实际是默认值错位 + 手工覆盖掩盖。⇒ 改默认值,且默认路径不存在时直接停。
_publish410.sh
LOCAL_RD
/d/tmp/readme410.html
/d/tmp/_readme_410.html
YANG_LOCAL_RD=...
update.json : version 4.1.0, md5 5cf4e1b3242a2e092233fd573d0196d4 包三方 md5 : 本地 / update.json / 公网下载 全部一致 readme : 57 节,星号 0 个 主题目录 : 仍是 4.0.0,无 theme-stat.php —— 红线守住,等你在后台点升级
真实 WP 环境复验:
LEN=1105 HAS_MD_STAR=no HAS_BOLD_TAG=yes
之前 hm.js?192a62f2… 一直返回 0 字节,说明百度侧那个 site_id 没生效。 你今天在后台补的统计代码已经存进 seo_statistical,现在实测:
hm.js?192a62f2…
hm.js?192a62f2… → HTTP 200,29896 字节 首页输出 → <p><script> … hm.baidu.com/hm.js?192a62f2… </p>
埋点已真正生效,访问数据会开始积累。
「数据导出服务」那个链接点下去,在本页跳走了,把正在改的设置页顶掉。
源码里 target="_blank" 一直在(inc/theme-options.php:853)。真正的原因是 框架渲染 desc 时会过一遍 HTML 白名单:
target="_blank"
inc/theme-options.php:853
// inc/options-framework/includes/class-options-interface.php:210 / 315 $output .= '<div class="explain">' . wp_kses($explain_value, $allowedtags) . '</div>';
而 WordPress 的全局 $allowedtags['a'] 只有 href 和 title。实测:
$allowedtags['a']
href
title
输入:<a href="..." target="_blank" rel="noopener">数据导出服务</a> 输出:<a href="...">数据导出服务</a> ← target 和 rel 都不见了
wp_kses 剥属性时不报错、不留痕,所以代码上完全看不出来。
wp_kses
在 kratos_options() 开头给白名单补两个属性(只补这两个,不放宽别的):
kratos_options()
global $allowedtags; $allowedtags['a']['target'] = true; $allowedtags['a']['rel'] = true;
时机是对的:_optionsframework_options() 在第 47 行就调 kratos_options(), 早于所有 wp_kses 调用。
_optionsframework_options()
同一个原因,设置页里 5 处链接都点不开新窗口,一并修好了:
你已经把主题升到 4.1.0 了。PUC 用 version_compare($new, $installed, '>') 判严格大于 —— 同一版本号重发多少遍,后台都不会提示更新,你永远拿不到这次修复。 所以升到 4.1.1。
version_compare($new, $installed, '>')
readme 按你选的方案 并入现有 V4.1.0 节,不新增一节(节数仍是 57), 在里面注明「这一条是 4.1.1 补的」以及 4.1.0 当时为什么没生效。
线上真实 WordPress 环境(不是桩):
ALLOWED_BEFORE=href,title ALLOWED_AFTER=href,title,target,rel HAS_TARGET=YES
PUC 实测:
INSTALLED=4.1.0 NEW=4.1.1 PKG=https://yangyq.net/theme-update/kratos_yang-4.1.1.zip HAS_UPDATE=YES
反证要点:删掉白名单补充必须变红、把补充挪出 kratos_options() 也必须变红 —— 两条都验过了,不是恒真。
update.json : 4.1.1, md5 bd12b67f2c4ca5bec5053a02e49f2fe6 4.1.1 包 : 200(4.6 MB) 4.1.0 / 4.0.0 旧包 : 仍 200(旧客户端不 404) readme : 57 节,含「这一条是 4.1.1 补的」 主题目录 : 仍是 4.1.0(未被覆盖)—— 等你在后台点升级 git : 51c1620 已推送
Version: 4.1.0
明白,明天再申请。API Key / Secret / site_id / 授权码齐了告我, 我这边只差这一步就能看到真数据。
用户确认可以关闭,凭据后续由站长自行在后台填写。
交付内容:主题设置页新增「访问统计」面板,调用百度统计 Tongji API 把数据直出后台,commit 见 4.1.0 / 4.1.1(c058ecc 之前的批次)。
c058ecc
关键设计三条:① 凭据(API Key / Secret Key / refresh_token)不进 options 表,单独存凭据文件,因此表单永远回显空框,空值语义必须是"不修改"而不是"清空";② 连接超时压到 5 秒 + blocking=false,任何失败路径都返回含 error 字段的数组,渲染层只负责显示不负责判成败,全链路无 wp_die 与异常外抛,后台绝不被外部 API 拖死;③ stat_auth_code 是一次性的,换完 refresh_token 即弃、不落库。
4.1.1 另修了该页链接无法新窗口打开的问题(wp_kses 静默剥 target/rel,在 kratos_options() 开头补白名单)。
线上已升级至 4.2.0 并验证通过。
No dependencies set.
The note is not visible to the blocked user.
需求
在主题设置页做一个访问统计面板:网站加一段第三方统计代码,我们在后端调用他们的 API,把数据显示在主题设置页面里。
拆解
这是一个需求,内含三个可独立验收的部分,但必须一起才算完成(少任何一步面板都不可用),所以不拆单:
① 前端埋点
hm.js)seo_statistical),不加新字段:那个框本来就是给用户填统计脚本的② 后端拉数据
ACCESS_TOKEN有效期 30 天,refresh_token10 年 ⇒ 必须做自动续期③ 后台面板
info类型块渲染硬性约束
<script>,后端只在后台被访问时查 API"--"表示无数据,(int)"--" === 0,必须单独判,不能当 0 参与计算验收标准
<head>或页脚能看到百度统计代码,且只在开关打开时输出php -l全量通过;判据 + 反证全绿前置依赖(需用户提供)
百度统计的 API Key / Secret Key,以及完成一次 OAuth 授权拿到
refresh_token。没有这些我无法端到端验证真实数据,只能验证降级路径。附:为什么不选自建 Umami
实测该服务器 2 核 / load 2.28(已近满载),Umami 容器 183~255MB + PostgreSQL,官方最低要求 1GB 内存整机。内存够但 CPU 不够,会明显加重现有负载。除非先上 Redis 对象缓存把基线压下来,否则不碰。
4.1.0 已开发完成并发布到更新源,等你升级验证
代码提交:
c125388(已推送 main)发布包:
https://yangyq.net/theme-update/kratos_yang-4.1.0.zipmd5:
5eeaca87ae06d0a4c92adaaa3f293c67(
update.json已指向 4.1.0,后台「外观 → 主题」应能看到升级提示)三项验收标准逐条对照
① 前台能看到统计代码,且只在开关打开时输出 ✅
footer.php把原有一行改成:开关是新增的
stat_track_enable(复选框),默认开。三态处理:从未配置 ⇒ 开(和你原来的行为一致)、显式勾选 ⇒ 开、显式取消 ⇒ 关。false被当成"用户主动关掉"而不是"没配置"——这是of_sanitize_checkbox未勾选写false带来的坑,判据专门钉了这一条。② 设置页出现统计面板并显示真实数字 ⚠️ 代码就绪,等你补凭据
面板、13 个指标、缓存、自动续期全都做完了。但你还没有填凭据,所以现在打开设置页会看到一块引导("还没有接通百度统计" + 四步操作指引),不是数字。这是有意的:未配置时不打任何接口,不可能卡住。
③ 凭据错误时优雅降级 ✅
取数失败 ⇒ 面板显示「统计暂不可用」+ 具体原因,下面一行「设置页其它部分不受影响,可以照常修改并保存」。设置页其余控件完全正常。
本轮抓到的三个真 bug(都修了)
1. 刷新按钮是摆设 —— 面板 JS 点「刷新数据」会发
force=1,AJAX 处理器也读出了$force,然后把它丢了,转头调渲染函数不带参数。后果:成功缓存 1800 秒,用户点刷新拿到的还是同一份数据,时间戳都不变,按钮看起来完全没反应。而"面板渲染"和"缓存"两段判据当时全绿——每一步单独看都对。修法是把$force一路传到yang_stat_fetch(),并且加了 8 条判据(静态 4 条 + 真调 AJAX 的行为 4 条)专门盯这个参数链路。2. 百度统计的错误格式和文档不一样 —— 我加了真实接口连通性测试(
_stat_api_real.php),实测:{"error":"invalid_client","error_description":"unknown client id"}{"error_code":110,"error_msg":"Access token invalid or no longer valid"}第一版代码只判了
200和error字段,两种情况都会报成"接口返回里找不到 result 节点"——一句完全指向错误方向的话。已改成三种格式都认,token 失效还会额外提示「请重新走一次授权」。3.
yang_stat_num(1234.0)返回 float 不返回 int ——is_float()分支直接 return,跳过了整型归一,下游按类型分支的判断全错。设计上几个值得说的决定
wp-content/uploads/.yang-stat-credentials.php(0600)"--"渲染成灰色破折号,不转 0(int)"--" === 0。不单独判的话,"暂无数据"会显示成"0 次访问"——看着像没人来,其实还没统计出来views计数保留不动验证(五套,全绿)
php -l全量_stat410.php_stat410_falsify.php_stat_api_real.php_mkzip410.py_mkzip410_falsify.py+_publish410_falsify.sh发布流程按红线执行:只写
theme-update/,线上主题目录未被覆盖(脚本有断言:kratos_yang/style.css仍是 4.0.0、目录里没有theme-stat.php)。PUC 已实测能读到 4.1.0(直接调checkForUpdates()拿到的 version=4.1.0、package 指向本版包)。顺带修了发布脚本自己三处判据缺陷:
while read里ssh吃掉 stdin 导致只 lint 了 1 个文件却报"全部通过"(假绿)、本地拿远端 php 路径解析 JSON 失败后空值走了 ok 分支(假绿)、把第三方 vendor 的 Deprecated 当语法错误(假红)。需要你做的两件事
1. 在后台点升级(外观 → 主题 → 检查更新 → 升级到 4.1.0)
升级完告诉我,我要做两件收尾:重设
theme-update目录 ACL(升级会重置权限),以及清 PUC transient 让后台立刻稳定显示 4.1.0。2. 补百度统计凭据(这是面板出真数字的前提)
昨天你问「百度统计是不是停止维护了」——查证了,产品正常在维护。但有个更要紧的发现需要你核对:
我是这么验的(交叉对照):
hm.js响应体96951609…youth.cn96951609…yangyq.net96951609…192a62f2…yangyq.net192a62f2…规律很清楚:有效 hash + 任意 Referer → 30278 字节;无效 hash → 恒 0 字节(无 Referer 时连有效 hash 也返回 0,所以不能用 curl 直接判埋点)。
也就是说,主题注入的代码完全正确(标准片段、
async:true、HTTP 200 全部对),问题在百度后台这个 site_id 没有生效。麻烦你到「管理 → 网站列表」看一下 yangyq.net 那一行:域名是否填对、状态是否在"正常"、是不是建了但没提交校验。这不阻塞代码——凭据和有效站点补齐后,面板立刻能出真数字。
发布后复核发现并已修复:反证脚本污染了线上 PUC 缓存(点升级会 404)
现象
发布反证脚本(
_publish410_falsify.sh)为了测「PUC 读到错包地址时判据会不会红」,临时把线上
update.json改成指向kratos_yang-9.9.9-nonexistent.zip,跑完立刻用
printf还原,并做了字节级复核:两条全绿,看起来干净。但真实状态是:后台点「升级到 4.1.0」会下载 404。
根因
测试那一下调用了
$myUpdateChecker->checkForUpdates(),PUC 把假地址写进了
site_transient('update_themes')。transient 里的response['kratos_yang']['package']是独立于update.json的一份拷贝,还原文件不会让它失效 —— 而前台「检查更新」读的正是这份缓存,默认最长 12 小时。
实测证据(独立 PHP 进程读 transient):
已做的修复
线上:
delete_site_transient('update_themes')+ 强制 PUC 重拉,独立进程复核,当前终态:
且
update.json、主题目录均未被污染(无9.9.9残留,theme-stat.php仍不存在,线上主题仍是 4.0.0 —— 红线守住)。
反证脚本:新增「2c. 清掉 PUC 缓存里残留的错包地址」段,还原文件之后显式清 transient,
并断言缓存里必须是正确地址(不是"没有 nonexistent"就算过 —— 空也是错):
反证现为 23 通过 / 0 失败(原 21 条 + 新增 2 条)。
记忆:记为红线 #496(反证还原了文件却没还原由文件派生的缓存)。
一个值得记住的判据陷阱
delete_site_transient()之后立刻get_site_transient()读到"还在"是正常的 ——PUC 走
site_transient_update_themes过滤器注入(见 #495),删完一读就重新填充。所以不能用
$t === false判"清干净了",要判重新填充出来的内容对不对。这一点让"删除 → 复核"这条最直觉的写法假红,差点让我以为清不掉。
对验收的影响
没有影响。修复后后台检查更新读到的就是正确的
4.1.0包地址,可以直接点升级。这个小插曲只在"反证跑完到发现它"的这几分钟内存在,
且当时并无用户在点升级。
线上真实环境预演抓到 2 处文案 bug(已修并重发)
前面六套判据全绿之后,我做了一件之前没做的事:把发布包解到服务器上,
在真实 WordPress + PHP 8.5 里加载 4.1.0 的
theme-stat.php。本地判据都是桩环境(
_stat410.php自带一套假的kratos_option/get_option),桩能证明逻辑对,证明不了它在真 WP 里不炸、也证明不了它输出给用户的是什么样子。
抓到的 bug:给用户看的文案里漏进了 Markdown 语法
yang_stat_render_shell()渲染出的 HTML:浏览器会原样显示两个星号。同批还有一处,在
stat_track_enable的desc里(
代码本身**不会被删除**),以及 readme 里一处(这十三项**都能单独关掉**)。根因是这个项目的 PHP 注释/文档习惯用
**加粗**写重点,这串文字被搬进 HTML 字符串和
__()文案时,星号就跟着进去了。修复
三处
**…**→<b>…</b>,inc/theme-stat.php、inc/theme-options.php各一行,readme 由
_readme410.py重新生成。新增判据(都做了注入反证)
_mkzip410.py第 11b 段**…**_mkzip410_falsify.py第 16 组<b>还原成**必须变红_readme410.py第 8 段关键细节:判据必须先剥 PHP 注释再判 —— 否则会把所有用
**写重点的技术注释都误报(本项目注释里到处都是)。
顺带修了两个判据脚本自身的缺陷
_stat410.php自己跑不起来。文件头文档写「跑法:php _stat410.php」,但
$GLOBALS['__theme_dir']只有反证脚本会注入,直接跑就Fatal error: Failed opening required '/inc/theme-stat.php'。判据脚本自己跑不起来 = 零判据绿灯,比假绿更难发现。
⇒ 加回落路径;找不到被测文件时
exit 2并明说「没跑任何判据,这不是通过」。_publish410.sh的LOCAL_RD默认值指向上一版遗留文件。默认写的是
/d/tmp/readme410.html,而_readme410.py的真实输出是/d/tmp/_readme_410.html。首跑就把上一版 readme 传上去了,出现 1 条失败;我第二次跑时手工加了
YANG_LOCAL_RD=...又"好了"。「失败一次、重跑就好」这种偶发最容易被当成网络抖动糊过去,
实际是默认值错位 + 手工覆盖掩盖。⇒ 改默认值,且默认路径不存在时直接停。
线上已重发
真实 WP 环境复验:
顺便一个好消息:埋点通了
之前
hm.js?192a62f2…一直返回 0 字节,说明百度侧那个 site_id 没生效。你今天在后台补的统计代码已经存进
seo_statistical,现在实测:埋点已真正生效,访问数据会开始积累。
4.1.1 已发布:修设置页链接无法新窗口打开
你反馈的问题
「数据导出服务」那个链接点下去,在本页跳走了,把正在改的设置页顶掉。
根因:不是链接写错,是被 WordPress 白名单静默剥掉了
源码里
target="_blank"一直在(inc/theme-options.php:853)。真正的原因是框架渲染
desc时会过一遍 HTML 白名单:而 WordPress 的全局
$allowedtags['a']只有href和title。实测:wp_kses剥属性时不报错、不留痕,所以代码上完全看不出来。修法
在
kratos_options()开头给白名单补两个属性(只补这两个,不放宽别的):时机是对的:
_optionsframework_options()在第 47 行就调kratos_options(),早于所有
wp_kses调用。受影响的不止这一个链接
同一个原因,设置页里 5 处链接都点不开新窗口,一并修好了:
为什么版本号要升到 4.1.1
你已经把主题升到 4.1.0 了。PUC 用
version_compare($new, $installed, '>')判严格大于 —— 同一版本号重发多少遍,后台都不会提示更新,你永远拿不到这次修复。
所以升到 4.1.1。
readme 按你选的方案 并入现有 V4.1.0 节,不新增一节(节数仍是 57),
在里面注明「这一条是 4.1.1 补的」以及 4.1.0 当时为什么没生效。
验证
线上真实 WordPress 环境(不是桩):
PUC 实测:
判据
_mkzip410.py(含新增 11c 段 5 条)_mkzip410_falsify.py(含新增 17/18 组)_readme410.py(改造为替换模式)_stat410.php_stat410_falsify.php_publish410.sh反证要点:删掉白名单补充必须变红、把补充挪出
kratos_options()也必须变红 ——两条都验过了,不是恒真。
线上终态
顺带修的两处「脚本自己过期」
_mkzip410_falsify.py的「版本号没改」注入锚点写死Version: 4.1.0。升到 4.1.1 后锚点不存在,反证报「1 组没抓到」—— 看起来像判据没牙齿,
实际是注入脚本自己过期了。改成动态读当前版本号。
_publish410.sh要求 readme 首节 == 本版号,但 4.1.1 并入 V4.1.0 节。改成两头都验:首节是 4.1.x,且本版修复说明真在里面。
百度统计凭据
明白,明天再申请。API Key / Secret / site_id / 授权码齐了告我,
我这边只差这一步就能看到真数据。
用户确认可以关闭,凭据后续由站长自行在后台填写。
交付内容:主题设置页新增「访问统计」面板,调用百度统计 Tongji API 把数据直出后台,commit 见 4.1.0 / 4.1.1(
c058ecc之前的批次)。关键设计三条:① 凭据(API Key / Secret Key / refresh_token)不进 options 表,单独存凭据文件,因此表单永远回显空框,空值语义必须是"不修改"而不是"清空";② 连接超时压到 5 秒 + blocking=false,任何失败路径都返回含 error 字段的数组,渲染层只负责显示不负责判成败,全链路无 wp_die 与异常外抛,后台绝不被外部 API 拖死;③ stat_auth_code 是一次性的,换完 refresh_token 即弃、不落库。
4.1.1 另修了该页链接无法新窗口打开的问题(wp_kses 静默剥 target/rel,在 kratos_options() 开头补白名单)。
线上已升级至 4.2.0 并验证通过。