默认头像发帖拦截

默认头像发帖拦截

使用默认头像的用户无法发帖/回帖,引导设置头像

插件 v1.0.0 Twelve 安全 内容 付费 20 金币

xnx_need_avatar 默认头像发帖拦截

Xiuno BBS X 插件,对仍使用系统默认头像的用户拦截发帖与回帖操作,引导其先到个人中心设置自定义头像,从而提升社区内容质量与视觉一致性。通过多个 hook 在请求入口与提交前双重拦截,核心代码零硬编码插件名。

功能特性

  • 默认头像判定:基于 user_read_cache($uid) 读出的 avatar_url 字符串与 default_avatar_url() 严格比较,覆盖三种「实际仍是默认头像」的场景:
1. avatar==0(从未设置过头像)

2. avatar<0 且对应预设头像文件已被删除(user_format 回落默认) 3. avatar>0 但上传的物理文件丢失(user_format 回落默认)

  • 双重拦截:GET 请求入口拦截(输出完整提示页)+ POST 提交前兜底拦截(输出 htmx 友好的 HTML 片段),绕过页面直连接口提交同样被拦
  • 全场景覆盖:发新帖、回帖、帖子详情页快速回复表单三处入口均有拦截点
  • 快速回复表单替换:命中拦截时用 CSS 隐藏原表单元素,改为显示「请先设置头像」提示卡 + 「去设置」链接,而非整体跳转
  • 用户组豁免:管理员组(gid=1,2)默认豁免,可后台自定义豁免用户组列表(逗号分隔)
  • 一键开关:后台可整体启用 / 禁用,禁用后所有 hook 调用 shouldBlock() 立即返回 false
  • 多语言:内置简体中文、繁体中文、英文三套语言包

安装说明

  1. 将插件目录放入 plugin/xnx_need_avatar/
  2. 进入后台「插件管理」找到「默认头像发帖拦截」点击安装
  3. 安装时自动写入默认配置:enabled=1exempt_gids='1,2'(即默认启用,管理员组豁免)
  4. 卸载时自动删除 xnx_need_avatar 配置项,不残留数据

插件仅使用 setting 表存储配置,不建任何附加数据表,安装 / 卸载零副作用。

使用指南

后台配置

访问 /admin/plugin-setting-xnx_need_avatar,仅管理员组(gid=1,2)可进入,POST 操作经 CsrfService::check() CSRF 校验。

| 配置项 | 字段名 | 说明 | |---|---|---| | 启用状态 | enabled | 1=启用拦截,0=禁用(默认启用) | | 豁免用户组 | exempt_gids | 逗号分隔的用户组 ID,命中即跳过拦截(默认 1,2) |

保存后通过 NeedAvatarService::saveSettings() 写入 setting 表,下次请求即时生效。

前台行为

  • 普通用户未设置头像时,访问发帖页 / 回帖页会看到完整提示页(含 header/footer),引导跳转个人中心
  • 直接 POST 提交发帖 / 回帖时,返回警告样式的 HTML 片段(含「去设置」链接),htmx 容器友好
  • 帖子详情页的快速回复表单会被 CSS 隐藏,替换为「请先设置头像后再发帖」提示,并附「去设置」链接到 my_url()
  • 豁免用户组成员、已设置头像的用户无任何感知,流程与原生一致

技术细节

拦截点 hook 列表

| Hook 文件 | 触发位置 | 拦截方式 | |---|---|---| | thread_create_get_start.php | 发帖页 GET 入口 | renderBlockPage() 输出完整页并 exit | | thread_create_thread_before.php | 发帖 POST 提交前 | renderBlockHtml() 输出片段并 exit | | post_get_start.php | 回帖页 GET 入口 | renderBlockPage() 输出完整页并 exit | | post_post_start.php | 回帖 POST 提交前 | renderBlockHtml() 输出片段并 exit | | thread_quick_reply_message_before.htm | 帖子详情页快速回复表单渲染前 | CSS 隐藏表单 + 提示卡注入 | | model_inc_file.php | 核心加载模型时 | 将 NeedAvatarService.php 注册进全局 include 列表 | | lang_zh_cn_bbs.php / lang_zh_tw_bbs.php / lang_en_us_bbs.php | 语言包加载 | 注入简中 / 繁中 / 英文文案 |

所有 hook 在 conf.jsonhooks_rank 中均设为 100,与其他插件无优先级冲突。

默认头像判定逻辑

NeedAvatarService::isDefaultAvatar($uid) 实现:

  1. 调用 user_read_cache($uid) 读取用户缓存(含 user_format 处理后的 avatar_url
  2. 若用户不存在直接返回 true(保守拦截)
  3. 严格比较 $user['avatar_url'] === default_avatar_url(),相等即视为默认头像

这种基于「最终渲染 URL 字符串」的判定比直接读 avatar 字段数值更稳健,能覆盖 user_format 在文件缺失时回落默认头像的三种边界场景,避免误判或漏判。

拦截决策流程

NeedAvatarService::shouldBlock($uid, $gid) 按以下顺序判断:

  1. 读取配置,若 enabled 为空 → 返回 false(插件被禁用)
  2. 解析 exempt_gids 字符串为数组,若当前 gid 命中 → 返回 false(豁免)
  3. 否则返回 isDefaultAvatar($uid) 结果

exempt_gids 解析支持任意空白与多余逗号容错(parseGids() 已做 trim 与空值过滤)。

GET vs POST 拦截的差异

  • GET 入口拦截renderBlockPage):输出包含 view/htm/header.inc.htmfooter.inc.htm 的完整页面,居中显示警告图标 + 提示文案 + 「去设置」按钮,调用 exit 终止后续流程
  • POST 提交拦截renderBlockHtml):仅设置 Content-Type: text/html; charset=utf-8 头并输出 alert alert-warning 样式的 HTML 片段,适合 htmx 异步刷新容器直接渲染,同样 exit 终止

两套输出均通过 my_url() 生成跳转链接,指向用户个人中心。

快速回复表单处理

thread_quick_reply_message_before.htm hook 在帖子详情页快速回复表单渲染前执行:

  • 通过 <style>#quick_reply_form > :not(.need-avatar-tip){display:none !important}</style> 隐藏表单原有元素
  • 注入一个 .need-avatar-tip 警告卡片,含「请先设置头像后再发帖」文案与「去设置」链接
  • 不调用 exit,允许页面其余部分正常渲染

配置兜底

NeedAvatarService::getSettings()setting_get 返回空或字段缺失时,会自动补齐 enabled=1exempt_gids='1,2',确保即使 setting 表异常也不会导致 shouldBlock() 报错。

兼容性

  • Xiuno BBS X 1.1+(bbs_version: 1.1
  • PHP 8.x(对 isset 兜底、intval 严格比较、in_array 第三参数 true 严格模式)
  • Bootstrap 5(提示页与卡片使用 x-cardalertbtn 等原生类)
  • Tabler Icons(ti ti-photo 图标,跟随主题自带图标库)
  • 无 jQuery 依赖
  • 依赖核心函数 default_avatar_url()user_read_cache()my_url(),需核心版本提供
  • 通过 hook 注入,核心代码无硬编码插件名,插件禁用后拦截行为自动失效

版本历史

  • 1.0.0:首版发布,包含默认头像判定、发帖 / 回帖 GET+POST 双重拦截、快速回复表单替换、用户组豁免、后台启用开关、简中 / 繁中 / 英文三语言支持

版本 1.0.0 | 兼容 Xiuno 1.1+

v1.0.0 2026-08-03
作者信息
XiunoX 开发者,独立开发者 & 全栈工程师 DiscuzX 插件/模板、WordPress 主题/插件、XiunoX 框架二次开发、APP 与小程序自研项目。
27
应用
0
安装
2026-08
加入
应用详情
应用分类 插件
版本 v1.0.0
适用版本 1.1
开发者 Twelve
下载量 0
浏览 2
更新时间 2026-08-03
发布时间 2026-08-03
最新回复
查看全部
  • 暂无回复

查看全部评论 / 发表评论
完整评论功能在讨论帖中,点击前往