[审计]thread/show 旧摘要链路扫描报告

👑Lv.11 元老 🌞 骨干会员
2026-10-25 00:27:11

本文由 FlintHub 开发文档归档发布。原始文档日期见标题前缀,来源:暂存20260913/thread_show旧摘要链路扫描报告.md。

thread/show 旧摘要链路扫描报告

扫描时间:2026-09-12

扫描范围:app/、cli/、update/

本报告阶段只做扫描,没有修改 ThreadController.php、thread/show.php、modern.css、thread.js、sw.js 或任何核心运行代码。

一、扫描结论

可以进入方案 B + 方案 A 的实施阶段。

当前运行代码中的旧摘要引用

旧摘要链路只存在于以下两个运行时文件:

  1. app/Controllers/ThreadController.php
  2. app/Views/thread/show.php

cli/ 中没有旧摘要变量引用。

app/Controllers/ApiController.php 不引用:

_threadExcerpt
_threadNeedsExpand
$threadExcerpt
$threadNeedsExpand
Content::excerpt()

Content::excerpt() 函数本身只在当前运行代码的 ThreadController::show() 中被调用。

因此可以:

  • 保留 Content::excerpt() 函数本身;
  • 删除 ThreadController::show() 中详情页摘要链路调用;
  • 删除 thread/show.php 中摘要变量、摘要判断和 htmx 动态正文分支;
  • 保留 /api/post/{id}/body 接口,但标记为 deprecated,暂不删除、不改接口权限逻辑。

二、旧变量逐项引用位置

1. _threadExcerpt

文件行号用途
app/Views/thread/show.php25从视图数据读取 _threadExcerpt,赋给 $threadExcerpt
app/Controllers/ThreadController.php242将摘要 HTML 赋给 $threadExcerpt
app/Controllers/ThreadController.php253reply_to_view 锁定时清空 $threadExcerpt
app/Controllers/ThreadController.php263作为 _threadExcerpt 传入视图

2. _threadNeedsExpand

文件行号用途
app/Views/thread/show.php26从视图数据读取 _threadNeedsExpand
app/Views/thread/show.php120判断是否显示摘要分支
app/Controllers/ThreadController.php235从 Content::excerpt() 结果读取 truncated
app/Controllers/ThreadController.php239判断是否对纯文本摘要补 nl2br
app/Controllers/ThreadController.php242判断是否赋值 $threadExcerpt
app/Controllers/ThreadController.php252reply_to_view 锁定时置为 false
app/Controllers/ThreadController.php263作为 _threadNeedsExpand 传入视图

3. $threadExcerpt

文件行号用途
app/Views/thread/show.php25视图局部变量声明
app/Views/thread/show.php121输出摘要 HTML
app/Controllers/ThreadController.php242详情摘要赋值
app/Controllers/ThreadController.php253锁定帖清空
app/Controllers/ThreadController.php263传入视图

4. $threadNeedsExpand

文件行号用途
app/Views/thread/show.php26视图局部变量声明
app/Views/thread/show.php120控制摘要/全文二选一
app/Controllers/ThreadController.php235读取截断标记
app/Controllers/ThreadController.php239控制纯文本摘要处理
app/Controllers/ThreadController.php242控制摘要变量赋值
app/Controllers/ThreadController.php252锁定帖关闭展开
app/Controllers/ThreadController.php263传入视图

5. thread/show.php 中相关动态分支

文件行号用途
app/Views/thread/show.php120–131摘要/完整正文二选一
app/Views/thread/show.php124hx-get="/api/post/{threadId}/body",按需拉取完整正文
app/Views/thread/show.php125将接口响应替换到主帖正文容器
app/Views/thread/show.php126hx-swap="innerHTML"

当前 update/168/app/Views/thread/show.php 是源文件的旧发布副本,仍包含同一旧链路;实施后需要同步更新。

三、Content::excerpt() 使用情况

当前运行代码

文件行号用途
app/Helpers/Content.php213Content::excerpt() 函数定义:安全 HTML 摘要、截断和 truncated 标记
app/Controllers/ThreadController.php234详情页主帖生成 500 字摘要

其它模块检查结果

在当前 app/ 全量搜索中,除 ThreadController::show() 外没有发现其它 Content::excerpt() 调用:

  • 列表页:没有独立调用;列表摘要使用自己的数据/字段逻辑;
  • 博客:没有独立调用;
  • 搜索:没有独立调用;
  • API:没有独立调用;
  • CLI:没有调用。

结论:

Content::excerpt() 函数本身保留。
本次只删除 ThreadController::show() 的详情页调用。

update/ 中存在若干历史增量包副本,例如:

update/60/app/Controllers/ThreadController.php
update/66/app/Controllers/ThreadController.php
update/125/app/Controllers/ThreadController.php
update/135/app/Controllers/ThreadController.php
update/156/app/Controllers/ThreadController.php
update/160/app/Controllers/ThreadController.php
update/166/app/Controllers/ThreadController.php
update/167/app/Controllers/ThreadController.php

这些是历史发布包记录,不是当前运行代码。当前目标发布目录 update/168/ 需要在实施后同步为新版本。

四、/api/post/{id}/body 接口依赖检查

路由

文件行号用途
index.php272注册 /post/{id}/body → ApiController::postBody

实现

文件行号用途
app/Controllers/ApiController.php526postBody($id) 接口定义
app/Controllers/ApiController.php528–530设置 HTML、nosniff、no-store 响应头
app/Controllers/ApiController.php532–536校验帖子 ID
app/Controllers/ApiController.php540接口级 post_body 限流
app/Controllers/ApiController.php542–545查询主题
app/Controllers/ApiController.php553–556校验版块浏览权限
app/Controllers/ApiController.php559–566校验 reply_to_view 回复可见权限
app/Controllers/ApiController.php569直接 decode + formatPostContent 输出完整正文

接口内部没有引用:

_threadExcerpt
_threadNeedsExpand
$threadExcerpt
$threadNeedsExpand
Content::excerpt()

结论:

  • 接口不依赖详情页摘要变量;
  • 接口保留不会影响新折叠逻辑;
  • thread/show.php 删除旧 hx-get 后,当前页面不再调用接口;
  • 本次不删除接口,因为它可能被外部客户端、旧缓存页面或未来其它页面使用;
  • 仅把接口注释标记为 deprecated,说明详情页已经改为服务端全文直出 + Alpine 本地折叠。

五、reply_to_view 隐私逻辑边界

当前详情控制器在 ThreadController.php 约 248–254 行执行:

  • reply_to_view 且用户未回复时,只替换主帖正文为锁定提示;
  • 回复列表仍然正常展示;
  • 锁定状态关闭旧摘要展开。

实施时必须保留这个逻辑,并改成:

  • 未授权用户:继续输出锁定提示,不输出可展开全文;
  • 已授权用户:输出完整正文,并允许 CSS 折叠 / Alpine 展开;
  • 不能把服务端全文直出误用于绕过 reply_to_view 权限。

六、缓存层检查

PageCache

app/Helpers/PageCache.php 只缓存静态 HTML 列表页:

首页 / 版块列表游客缓存

其缓存内容是完整渲染后的 HTML 字符串,不序列化控制器 $data,没有针对:

_threadExcerpt
_threadNeedsExpand

的特殊处理。

ThreadController

ThreadController::show() 没有调用:

PageCache::serve()
PageCache::render()
serialize()

因此帖子详情页不会经过 PageCache,也没有缓存层序列化这两个变量的问题。

全量符号检查

在 app/、cli/、update/ 搜索两个下划线变量后:

  • 当前运行代码引用仅为 ThreadController.php + thread/show.php;
  • cli/ 无引用;
  • update/ 旧历史包有引用,是历史副本,不是独立运行模块;
  • update/168/ 有旧发布副本引用,实施后必须同步删除。

七、实施前确认清单

扫描结果满足方案 B 的前置条件:

  • [x] Content::excerpt() 没有其它当前运行模块依赖;
  • [x] /api/post/{id}/body 不依赖旧摘要变量;
  • [x] thread/show.php 旧变量只有主帖摘要链路使用;
  • [x] PageCache 不序列化旧变量;
  • [x] reply_to_view 逻辑可独立保留;
  • [x] 列表页摘要不受影响;
  • [x] 可删除详情页 Content::excerpt() 调用及旧变量传参;
  • [x] 可把 API 标记为 deprecated 而不删除;
  • [x] 可继续按方案 A 增加 CSS + Alpine + htmx 局部翻页。

八、下一步允许的修改范围

用户指定的最终修改范围:

app/Controllers/ThreadController.php
app/Views/thread/show.php
assets/css/modern.css
assets/js/thread.js
sw.js
update/168/ 对应同步副本

不修改:

app/Core/
app/Models/
app/Helpers/
SplitDB/
其它插件
数据库结构

扫描报告完成。等待用户确认本报告后,才执行方案 B + 方案 A 的代码修改。

轻量级、高性能、零 MySQL 依赖的PHP社区系统。
| 浏览 1 次 | 回复 0 次

全部回复 (0)

暂无回复

请 登录