Files
wordpress-kratos-yang/inc/theme-mail-core.php
T

248 lines
10 KiB
PHP
Raw Normal View History

<?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);