评论通知邮件无样式:接管核心通知正文 #39
卸载 wpDiscuz 后,评论通知回落到核心 wp_notify_postauthor / wp_notify_moderator。theme-mail.php 只接管了通道(SMTP、From), 并把 Content-Type 强改成 text/html,而正文仍是核心拼的纯文本, 客户端按 HTML 渲染 ⇒ 换行丢、链接变裸地址。 新增 inc/theme-mail-core.php,挂 comment_notification_text / comment_moderation_text 两个过滤器,把正文换成主题模板。这是核心 自己提供的扩展点,不改核心文件,删掉即回退。 模板新增 links 参数,把 通过/回收站/垃圾 渲染成一行文字链接 (并排三按钮在手机上必然换行、高度不齐)。 版本 4.2.1 -> 4.2.2
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
/**
|
||||
* 接管 WordPress 核心的评论通知正文
|
||||
*
|
||||
* ── 要解决的问题 ──────────────────────────────────────────────
|
||||
* 站点卸载 wpDiscuz 之后,评论通知回落到核心:
|
||||
*
|
||||
* wp_notify_postauthor() 有新评论 → 通知文章作者
|
||||
* wp_notify_moderator() 有待审评论 → 通知管理员
|
||||
*
|
||||
* 主题的 theme-mail.php 只接管了**通道**(SMTP、From、Content-Type),
|
||||
* 但正文仍然是核心拼出来的那一坨纯文本:
|
||||
*
|
||||
* 您的文章《留言本》有新评论
|
||||
* 作者:某某(IP 地址:1.2.3.4)
|
||||
* 评论:……
|
||||
* 移至回收站:https://...
|
||||
* 标记为垃圾评论:https://...
|
||||
*
|
||||
* 而 yang_mail_normalize_headers() 把 Content-Type 强改成了
|
||||
* `text/html; charset=UTF-8`(这一步本身是对的:不改成 HTML 中文会乱码,
|
||||
* 也没法塞模板)。两件事叠加的结果是:**一封被声明成 HTML 的邮件,
|
||||
* 里面装的是没有标签的纯文本**。客户端按 HTML 渲染 ⇒ 换行全丢、
|
||||
* 链接变成裸地址。用户看到的就是「一点样式都没有了」。
|
||||
*
|
||||
* ── 为什么之前没暴露 ──────────────────────────────────────────
|
||||
* theme-mail.php 里有这条规则:
|
||||
*
|
||||
* 「没有插件接管 → 核心通知是唯一的顶层评论通知渠道,必须放行」
|
||||
*
|
||||
* 放行是对的,但只放行了「发不发」,没管「长什么样」。装着 wpDiscuz 时,
|
||||
* 正文由插件的 wpdiscuz_email_content 过滤器重渲染,核心那段根本走不到;
|
||||
* 插件一卸,这条路径才第一次暴露出来。
|
||||
*
|
||||
* ── 怎么修(不动核心)─────────────────────────────────────────
|
||||
* 用核心自己提供的过滤器,在 wp_mail 之前把正文换掉:
|
||||
*
|
||||
* comment_notification_text ($notify_message, $comment_id)
|
||||
* comment_moderation_text ($notify_message, $comment_id)
|
||||
*
|
||||
* 这是**扩展点**,不是改核心文件。wp-includes/pluggable.php 里那两行
|
||||
* apply_filters() 是核心自己写的,我们只是挂上去;删掉本文件立刻回到
|
||||
* 核心原始行为,完全可逆,也不会在升级时留下残留。
|
||||
*
|
||||
* ── 边界 ──────────────────────────────────────────────────────
|
||||
* · 只在主题 SMTP 配置完整时接管。没配 SMTP 说明用户可能用别的邮件
|
||||
* 插件,这时贸然换成 HTML 会和那边的模板打架。
|
||||
* · trackback / pingback 不接管。它们不是评论,字段结构也不同,
|
||||
* 套模板反而会丢信息(比如 trackback 摘要)。
|
||||
*
|
||||
* @author Yongquan Yang <yangyq.net>
|
||||
* @license MIT License
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取评论对应的文章标题
|
||||
*
|
||||
* 文章被删掉时 get_the_title() 返回空串,邮件里就会出现《》,
|
||||
* 比直接说「文章已删除」更难懂。
|
||||
*/
|
||||
function yang_mail_core_post_title($post_id)
|
||||
{
|
||||
$post = get_post($post_id);
|
||||
if (!$post) {
|
||||
return __('(文章已删除)', 'kratos');
|
||||
}
|
||||
$t = get_the_title($post);
|
||||
return $t !== '' ? $t : __('(无标题)', 'kratos');
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台评论操作链接
|
||||
*
|
||||
* 核心给的 approve / spam / trash 是三个裸 URL,这里做成模板里的一行
|
||||
* 文字链接。为什么不做成三个并排按钮:邮件里并排三个按钮在手机上
|
||||
* 必然换行、高度不齐,看起来像渲染出错;而且这些是后台管理动作,
|
||||
* 不该和主按钮抢视觉权重。
|
||||
*
|
||||
* @param int $comment_id
|
||||
* @param bool $with_approve 已发布的评论不需要「通过」
|
||||
* @return array
|
||||
*/
|
||||
function yang_mail_core_action_links($comment_id, $with_approve = false)
|
||||
{
|
||||
$id = (int) $comment_id;
|
||||
$links = array();
|
||||
|
||||
if ($with_approve) {
|
||||
$links[] = array(
|
||||
'text' => __('通过审核', 'kratos'),
|
||||
'url' => admin_url("comment.php?action=approve&c={$id}#wpbody-content"),
|
||||
);
|
||||
}
|
||||
|
||||
if (EMPTY_TRASH_DAYS) {
|
||||
$links[] = array(
|
||||
'text' => __('移至回收站', 'kratos'),
|
||||
'url' => admin_url("comment.php?action=trash&c={$id}#wpbody-content"),
|
||||
);
|
||||
} else {
|
||||
$links[] = array(
|
||||
'text' => __('永久删除', 'kratos'),
|
||||
'url' => admin_url("comment.php?action=delete&c={$id}#wpbody-content"),
|
||||
);
|
||||
}
|
||||
|
||||
$links[] = array(
|
||||
'text' => __('标记为垃圾', 'kratos'),
|
||||
'url' => admin_url("comment.php?action=spam&c={$id}#wpbody-content"),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把评论通知(有新评论 → 文章作者)渲染成主题模板
|
||||
*
|
||||
* @param string $text 核心生成的纯文本(仅在参数非法时原样返回)
|
||||
* @param string|int $comment_id
|
||||
* @return string
|
||||
*/
|
||||
function yang_mail_core_render_comment_notify($text, $comment_id)
|
||||
{
|
||||
if (!yang_mail_smtp_ready()) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
$comment = get_comment($comment_id);
|
||||
if (!($comment instanceof WP_Comment)) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
// 引用 / Pingback 不是评论,字段结构不同,不套模板
|
||||
if ($comment->comment_type === 'trackback' || $comment->comment_type === 'pingback') {
|
||||
return $text;
|
||||
}
|
||||
|
||||
$title = yang_mail_core_post_title($comment->comment_post_ID);
|
||||
$author = $comment->comment_author !== '' ? $comment->comment_author : __('匿名访客', 'kratos');
|
||||
|
||||
$rows = array(
|
||||
array('label' => __('文章', 'kratos'), 'value' => $title),
|
||||
array('label' => __('评论者', 'kratos'), 'value' => $author, 'strong' => true),
|
||||
);
|
||||
|
||||
if ($comment->comment_author_email !== '') {
|
||||
$rows[] = array('label' => __('邮箱', 'kratos'), 'value' => $comment->comment_author_email);
|
||||
}
|
||||
if ($comment->comment_author_url !== '') {
|
||||
$rows[] = array('label' => __('网址', 'kratos'), 'value' => $comment->comment_author_url);
|
||||
}
|
||||
if ($comment->comment_author_IP !== '') {
|
||||
$rows[] = array('label' => __('IP 地址', 'kratos'), 'value' => $comment->comment_author_IP);
|
||||
}
|
||||
$rows[] = array('label' => __('时间', 'kratos'), 'value' => mysql2date('Y-m-d H:i', $comment->comment_date));
|
||||
|
||||
return yang_mail_render(array(
|
||||
'title' => sprintf(__('%s · 新评论', 'kratos'), get_bloginfo('name')),
|
||||
'preheader' => sprintf(__('%s 在《%s》下发表了评论。', 'kratos'), $author, $title),
|
||||
'badge' => __('新评论', 'kratos'),
|
||||
'heading' => __('文章有新评论', 'kratos'),
|
||||
'intro' => sprintf(__('《%s》收到了一条新评论。', 'kratos'), $title),
|
||||
'quotes' => array(
|
||||
array(
|
||||
'label' => sprintf(__('%s 说', 'kratos'), $author),
|
||||
'content' => yang_mail_text($comment->comment_content, 1200),
|
||||
'meta' => mysql2date('Y-m-d H:i', $comment->comment_date),
|
||||
),
|
||||
),
|
||||
'rows' => $rows,
|
||||
'cta_text' => __('查看评论', 'kratos'),
|
||||
'cta_url' => get_comment_link($comment),
|
||||
'links' => yang_mail_core_action_links($comment->comment_ID, false),
|
||||
'note' => __('你收到这封邮件,是因为你是这篇文章的作者。', 'kratos'),
|
||||
));
|
||||
}
|
||||
add_filter('comment_notification_text', 'yang_mail_core_render_comment_notify', 20, 2);
|
||||
|
||||
/**
|
||||
* 把审核通知(有待审评论 → 管理员)渲染成主题模板
|
||||
*
|
||||
* 内容与上面高度重合,差别只有:徽标是「待审核」、主按钮去审核面板、
|
||||
* 操作行多一个「通过审核」。合并成一个函数要靠一堆 if 分叉,
|
||||
* 不如分开写清楚。
|
||||
*
|
||||
* @param string $text
|
||||
* @param string|int $comment_id
|
||||
* @return string
|
||||
*/
|
||||
function yang_mail_core_render_moderation($text, $comment_id)
|
||||
{
|
||||
if (!yang_mail_smtp_ready()) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
$comment = get_comment($comment_id);
|
||||
if (!($comment instanceof WP_Comment)) {
|
||||
return $text;
|
||||
}
|
||||
|
||||
if ($comment->comment_type === 'trackback' || $comment->comment_type === 'pingback') {
|
||||
return $text;
|
||||
}
|
||||
|
||||
$title = yang_mail_core_post_title($comment->comment_post_ID);
|
||||
$author = $comment->comment_author !== '' ? $comment->comment_author : __('匿名访客', 'kratos');
|
||||
|
||||
$rows = array(
|
||||
array('label' => __('文章', 'kratos'), 'value' => $title),
|
||||
array('label' => __('评论者', 'kratos'), 'value' => $author, 'strong' => true),
|
||||
);
|
||||
|
||||
if ($comment->comment_author_email !== '') {
|
||||
$rows[] = array('label' => __('邮箱', 'kratos'), 'value' => $comment->comment_author_email);
|
||||
}
|
||||
if ($comment->comment_author_url !== '') {
|
||||
$rows[] = array('label' => __('网址', 'kratos'), 'value' => $comment->comment_author_url);
|
||||
}
|
||||
if ($comment->comment_author_IP !== '') {
|
||||
$rows[] = array('label' => __('IP 地址', 'kratos'), 'value' => $comment->comment_author_IP);
|
||||
}
|
||||
$rows[] = array('label' => __('时间', 'kratos'), 'value' => mysql2date('Y-m-d H:i', $comment->comment_date));
|
||||
|
||||
return yang_mail_render(array(
|
||||
'title' => sprintf(__('%s · 待审核评论', 'kratos'), get_bloginfo('name')),
|
||||
'preheader' => sprintf(__('%s 在《%s》下的评论等待审核。', 'kratos'), $author, $title),
|
||||
'badge' => __('待审核', 'kratos'),
|
||||
'heading' => __('有一条评论等待审核', 'kratos'),
|
||||
'intro' => sprintf(__('《%s》收到了新评论,需要你确认后才公开显示。', 'kratos'), $title),
|
||||
'quotes' => array(
|
||||
array(
|
||||
'label' => sprintf(__('%s 说', 'kratos'), $author),
|
||||
'content' => yang_mail_text($comment->comment_content, 1200),
|
||||
'meta' => mysql2date('Y-m-d H:i', $comment->comment_date),
|
||||
),
|
||||
),
|
||||
'rows' => $rows,
|
||||
'cta_text' => __('去后台审核', 'kratos'),
|
||||
'cta_url' => admin_url('edit-comments.php?comment_status=moderated#wpbody-content'),
|
||||
'links' => yang_mail_core_action_links($comment->comment_ID, true),
|
||||
'note' => __('这是评论审核提醒,处理完即可忽略。', 'kratos'),
|
||||
));
|
||||
}
|
||||
add_filter('comment_moderation_text', 'yang_mail_core_render_moderation', 20, 2);
|
||||
Reference in New Issue
Block a user