哀悼默认值全部改为不勾选 - 九个纪念日的 default 全改成 0。之前法定那三个是 1,导致全新安装的站点 一到日子就自己变黑白,而站主根本没同意过这件事。 - 后台多选组件的 std 全为 0,打开设置页一个都不勾。 - 「从未保存过」与「保存过但全不勾」两条路径都返回空数组, 不能因为结果为空就回退到默认 —— 那等于用户取消勾选无效。 新增彩色说明页(inc/theme-mourning-page.php + pages/page-mourning.php) - 站点变黑白后必须有个地方解释清楚,否则访客只看到一片灰、以为站点坏了。 - 三处入口:顶部提示条(wp_body_open,首屏可见)、页脚常驻链接、 [yang_mourning] 短代码。 - 页面内容由真实配置驱动,不是写死的文案:没勾的日期不会出现, 今天在列表里带「今天」标记,一个都没勾时明说「不会生效」。 - 页面必须保持彩色,否则解释「为什么是灰的」的页面自己也是灰的。 取消灰度做了两层:filter:none 与 grayscale(0%) 都写,且带 !important; 优先级放在 wp_head 的 2,晚于灰度样式的 1。 - 路由走 parse_request 优先级 5 而非 template_redirect: 避免先走一遍 404 判定与 404 模板。带子目录安装时先剥掉前缀再比对。 - 不抢占用户自己建的页面:如果站里已有同名 slug 的页面就放手。 否则用户会觉得「我建的页面坏了」,且没有任何提示。 邮件不受影响,且回复邮件同时给出双方内容 - 邮件是独立 HTML,不走 wp_head,结构上就不可能被灰度,已断言验证。 - theme-mail-template 的单个 quote 改成 quotes 列表,一个模板同时渲染 「被回复的那条」与「新的回复」,最后一块用主色高亮(回复是重点), 前面的用弱化色。只有一块时退化为主色,与旧行为一致。 - 通过 wpdiscuz_email_content 重建整封邮件,不需要改插件。 审核通过通知用 wpdiscuz_comment_approved_email_content 走同一模板, 但它只给 post_id、不给评论对象,能放的内容受此限制。 两个必须记下来的坑 - wpDiscuz 在过滤器之后还会做一次 html_entity_decode 再发信。 esc_html 的输出会被那一步还原成真标签,评论里的 <script> 直接生效。 所以返回前先把 & 编码一次。本地 stub 没有这一步,测试看不出来。 - header.php 从来没有调用 wp_body_open,挂在上面的东西全部静默失效。 不调用不会报错,只会「什么都没发生」。已补在 <body> 之后。 yang_mail_text 保留换行 - 原来用 wp_strip_all_tags($t, true),第二个参数 remove_breaks 会把换行 压成空格;而 strip_tags 遇到 <br> 是直接删掉不补换行的。 结果整条评论被拍成一行,模板里的 nl2br 成了死代码。 - 改为先把块级边界降级成 \n,再去标签(remove_breaks=false)。 收行内空白用 [^\S\n] 而不是 [ \t\f\v]:PCRE 的 \v 是垂直空白类, 会把 \n 一起匹配掉。 说明页对比度修正(WCAG AA) - 金色 #b8860b 在白底只有 3.06:1,当装饰色没问题,当 12-15px 文字偏虚。 拆成 --ym-gold(装饰)与 --ym-gold-text(#946600,4.75:1,仍属金色)。 - 分组小标题 #9aa5b1 只有 2.36:1,改用 #5f6b78(5.12:1)。 - 「今天」标签白字压金底 3.25:1,改用 #8a6100(5.54:1)。
414 lines
19 KiB
PHP
414 lines
19 KiB
PHP
<?php
|
||
/**
|
||
* 哀悼说明页
|
||
*
|
||
* ── 这个页面解决什么问题 ──────────────────────────────────────
|
||
* 站点在纪念日自动变黑白,但访客看到一片灰只会以为网站坏了。
|
||
* 需要在页面上给出一个入口,点进来能看到「为什么变黑白」的完整说明。
|
||
*
|
||
* ── 三条设计约束 ──────────────────────────────────────────────
|
||
* 1. **本页必须不受灰度影响**。全站 `html{filter:grayscale(100%)}` 会
|
||
* 把这一页也变灰,而用户明确要求「界面要做的漂亮,彩色的」。
|
||
* 灰度样式挂在 `wp_head` 优先级 1,本页在 `wp_head` 优先级 2 里
|
||
* 反转回来 —— 见 inc/theme-mourning.php 的 yang_mourning_page_css()。
|
||
*
|
||
* 2. **不依赖主题的 .article 样式**。哀悼页用独立的类名命名空间 `ym-`,
|
||
* 避免和正文排版规则打架(正文的 p/ul 样式会把卡片挤变形)。
|
||
*
|
||
* 3. **静态页 + 短代码**。不写进数据库,用 page 模板 + 主题自带内容,
|
||
* 这样升级主题就自动带上,用户不需要手动建页面。
|
||
*
|
||
* @author Yongquan Yang <yangyq.net>
|
||
* @license MIT License
|
||
*/
|
||
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* 说明页用的配色
|
||
*
|
||
* 哀悼页是**彩色**的,但主色调仍然克制(不用大红大绿),
|
||
* 因为它讲的是一件严肃的事。用「暖金 + 深墨」的组合:
|
||
* 金色呼应纪念的国家仪式感,深墨保证长文可读。
|
||
*/
|
||
function yang_mourning_page_palette()
|
||
{
|
||
return array(
|
||
'gold' => '#b8860b', // 暗金,装饰色(SVG 描边、分隔线、纯装饰的描边)
|
||
/* 金的"可读版本"。
|
||
* #b8860b 在白底上只有 3.06:1,低于 WCAG AA 对正文的 4.5:1 ——
|
||
* 装饰线条用它没问题,但当**文字颜色**就偏虚,尤其 12–15px 小字。
|
||
* #946600 是同色相里仍属金色、且刚好过线(4.75:1)的最亮一档,
|
||
* 再亮一档 #9c7000 只有 4.18:1 不达标,再暗就往棕色走了。
|
||
* 所以装饰归装饰、文字归文字,两个变量分开,不要混用。 */
|
||
'gold_text' => '#946600',
|
||
'gold_soft' => '#fdf6e3', // 金的浅底
|
||
'ink' => '#1f2933', // 正文墨色
|
||
'ink_soft' => '#52606d', // 次要文字
|
||
'paper' => '#ffffff',
|
||
'canvas' => '#f7f8fa',
|
||
'line' => '#e4e7eb',
|
||
'red' => '#a4243b', // 公祭日用的暗红
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 渲染哀悼说明的正文(短代码与模板共用)
|
||
*
|
||
* @return string HTML
|
||
*/
|
||
function yang_mourning_page_content()
|
||
{
|
||
$p = yang_mourning_page_palette();
|
||
$days = yang_mourning_days();
|
||
$presets = yang_mourning_presets();
|
||
|
||
// 今天是否在哀悼
|
||
$is_today = yang_is_mourning_today();
|
||
$today = current_time('m') . '-' . current_time('d');
|
||
|
||
ob_start();
|
||
?>
|
||
|
||
<div class="ym-wrap" style="--ym-gold:<?php echo esc_attr($p['gold']); ?>;--ym-gold-text:<?php echo esc_attr($p['gold_text']); ?>;--ym-gold-soft:<?php echo esc_attr($p['gold_soft']); ?>;--ym-ink:<?php echo esc_attr($p['ink']); ?>;--ym-ink-soft:<?php echo esc_attr($p['ink_soft']); ?>;--ym-line:<?php echo esc_attr($p['line']); ?>;--ym-red:<?php echo esc_attr($p['red']); ?>;">
|
||
|
||
<?php /* ── 顶部:当前状态 ── */ ?>
|
||
<div class="ym-hero">
|
||
<div class="ym-hero-inner">
|
||
<div class="ym-hero-mark" aria-hidden="true">
|
||
<svg viewBox="0 0 64 64" width="56" height="56" role="img">
|
||
<defs>
|
||
<linearGradient id="ymg" x1="0" y1="0" x2="0" y2="1">
|
||
<stop offset="0%" stop-color="#d4a017"/>
|
||
<stop offset="100%" stop-color="#8b6508"/>
|
||
</linearGradient>
|
||
</defs>
|
||
<circle cx="32" cy="32" r="29" fill="none" stroke="url(#ymg)" stroke-width="2" opacity="0.55"/>
|
||
<circle cx="32" cy="32" r="23" fill="none" stroke="url(#ymg)" stroke-width="1" opacity="0.3"/>
|
||
<path d="M32 15 L32 49" stroke="url(#ymg)" stroke-width="3.2" stroke-linecap="round"/>
|
||
<path d="M20 27 L44 27" stroke="url(#ymg)" stroke-width="3.2" stroke-linecap="round"/>
|
||
<path d="M24 38 Q32 45 40 38" stroke="url(#ymg)" stroke-width="2.4" fill="none" stroke-linecap="round"/>
|
||
</svg>
|
||
</div>
|
||
<h1 class="ym-hero-title"><?php echo $is_today ? '今天是纪念日' : '关于本站的纪念日哀悼'; ?></h1>
|
||
<p class="ym-hero-sub">
|
||
<?php if ($is_today): ?>
|
||
本站今日以黑白呈现,以寄哀思。这不是故障,是刻意的。
|
||
<?php else: ?>
|
||
在特定的日子里,本站会转为黑白显示,以示纪念。
|
||
<?php endif; ?>
|
||
</p>
|
||
<div class="ym-hero-status <?php echo $is_today ? 'is-on' : 'is-off'; ?>">
|
||
<span class="ym-dot"></span>
|
||
<?php if ($is_today): ?>
|
||
当前状态:正在哀悼(全站黑白)
|
||
<?php else: ?>
|
||
当前状态:正常显示 · 今天是 <?php echo esc_html($today); ?>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php /* ── 为什么会变黑白 ── */ ?>
|
||
<section class="ym-sec">
|
||
<h2 class="ym-sec-title"><span class="ym-bar"></span>为什么会变成黑白</h2>
|
||
<div class="ym-prose">
|
||
<p>在一些具有特殊意义的日子里,本站会把整站色调转为黑白,暂停一切彩色装饰。这是一种无声的致意 —— 和降半旗、鸣笛、默哀是同一类表达。</p>
|
||
<p>它不改变内容,也不影响你阅读任何文章。只是把颜色暂时收起来。</p>
|
||
</div>
|
||
</section>
|
||
|
||
<?php /* ── 哪几天会变黑白(真实数据,不是写死的文案) ── */ ?>
|
||
<section class="ym-sec">
|
||
<h2 class="ym-sec-title"><span class="ym-bar"></span>哪几天会自动变黑白</h2>
|
||
|
||
<?php
|
||
// 按用户实际勾选分组,勾了才显示。没勾就明说没勾,别让访客以为本站不在乎。
|
||
$legal = array();
|
||
$custom = array();
|
||
foreach ($days as $md) {
|
||
if (!isset($presets[$md])) {
|
||
continue;
|
||
}
|
||
if (isset($presets[$md]['group']) && $presets[$md]['group'] === 'legal') {
|
||
$legal[$md] = $presets[$md];
|
||
} else {
|
||
$custom[$md] = $presets[$md];
|
||
}
|
||
}
|
||
?>
|
||
|
||
<?php if (!empty($legal)): ?>
|
||
<div class="ym-group-label">法定纪念日</div>
|
||
<div class="ym-days">
|
||
<?php foreach ($legal as $md => $info): ?>
|
||
<div class="ym-day <?php echo ($md === $today) ? 'is-today' : ''; ?>">
|
||
<div class="ym-day-date"><?php echo esc_html(str_replace('-', '.', $md)); ?></div>
|
||
<div class="ym-day-body">
|
||
<div class="ym-day-name"><?php echo esc_html($info['name']); ?></div>
|
||
<div class="ym-day-note"><?php echo esc_html($info['note']); ?></div>
|
||
</div>
|
||
<?php if ($md === $today): ?><div class="ym-day-tag">今天</div><?php endif; ?>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($custom)): ?>
|
||
<div class="ym-group-label">本站另外启用的纪念日</div>
|
||
<div class="ym-days">
|
||
<?php foreach ($custom as $md => $info): ?>
|
||
<div class="ym-day <?php echo ($md === $today) ? 'is-today' : ''; ?>">
|
||
<div class="ym-day-date"><?php echo esc_html(str_replace('-', '.', $md)); ?></div>
|
||
<div class="ym-day-body">
|
||
<div class="ym-day-name"><?php echo esc_html($info['name']); ?></div>
|
||
<div class="ym-day-note"><?php echo esc_html($info['note']); ?></div>
|
||
</div>
|
||
<?php if ($md === $today): ?><div class="ym-day-tag">今天</div><?php endif; ?>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php
|
||
// 附加的自定义日期
|
||
$extra = trim((string) kratos_option('g_rip_extra', ''));
|
||
if ($extra !== ''):
|
||
?>
|
||
<div class="ym-group-label">站主另行标注的日期</div>
|
||
<div class="ym-extra">
|
||
<?php
|
||
foreach (preg_split('/[\s,,、;;]+/u', $extra) as $one) {
|
||
$one = trim($one);
|
||
if ($one === '') {
|
||
continue;
|
||
}
|
||
// 这里是用户自由填写的字段,必须转义后再显示
|
||
echo '<span class="ym-extra-chip">' . esc_html($one) . '</span>';
|
||
}
|
||
?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (empty($days) && $extra === ''): ?>
|
||
<div class="ym-empty">
|
||
<p>本站目前没有启用任何纪念日。</p>
|
||
<p class="ym-empty-note">如果哪天你看到这里变成黑白,那说明站主刚刚启用了它。</p>
|
||
</div>
|
||
<?php endif; ?>
|
||
</section>
|
||
|
||
<?php /* ── 常用问答 ── */ ?>
|
||
<section class="ym-sec">
|
||
<h2 class="ym-sec-title"><span class="ym-bar"></span>几个可能想问的问题</h2>
|
||
<div class="ym-faq">
|
||
<details class="ym-qa" open>
|
||
<summary>是我浏览器坏了吗?</summary>
|
||
<div class="ym-qa-body">不是。可以在别的设备上打开对比一下,同样是黑白。整站色调由一段样式统一控制,会在纪念日当天自动生效,次日自动恢复。</div>
|
||
</details>
|
||
<details class="ym-qa">
|
||
<summary>会影响阅读吗?</summary>
|
||
<div class="ym-qa-body">内容、链接、图片都不变,只是颜色被去掉。文字对比度反而更高一些。唯一的变化是图片失去色彩。</div>
|
||
</details>
|
||
<details class="ym-qa">
|
||
<summary>什么时候恢复彩色?</summary>
|
||
<div class="ym-qa-body">当天 24 点过后自动恢复。本站按站点时区判断日期,不是按你所在时区,所以不同地区看到的切换时刻可能略有差别。</div>
|
||
</details>
|
||
<details class="ym-qa">
|
||
<summary>打印出来也是灰的吗?</summary>
|
||
<div class="ym-qa-body">不是。打印时已专门取消灰度,纸上呈现正常颜色。</div>
|
||
</details>
|
||
<details class="ym-qa">
|
||
<summary>这个页面为什么是彩色的?</summary>
|
||
<div class="ym-qa-body">说明性质的内容需要读得清楚。把说明页也做成灰的,反而增加了理解成本 —— 这与「让人明白发生了什么」的目的是相反的。</div>
|
||
</details>
|
||
</div>
|
||
</section>
|
||
|
||
<?php /* ── 底部 ── */ ?>
|
||
<div class="ym-foot">
|
||
<div class="ym-foot-line"></div>
|
||
<p class="ym-foot-text">铭记,是为了更好地前行。</p>
|
||
<p class="ym-foot-link">
|
||
<a href="<?php echo esc_url(home_url('/')); ?>">返回首页</a>
|
||
</p>
|
||
</div>
|
||
|
||
</div>
|
||
<?php
|
||
return ob_get_clean();
|
||
}
|
||
|
||
/**
|
||
* 说明页的样式
|
||
*
|
||
* 独立命名空间 `ym-`,不碰主题的 .article / .content 规则。
|
||
* 用 CSS 变量做配色,方便以后换主题色时只改一处。
|
||
*/
|
||
function yang_mourning_page_css()
|
||
{
|
||
$css = <<<'CSS'
|
||
.ym-wrap{max-width:820px;margin:0 auto;padding:0 4px 40px;color:var(--ym-ink);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;line-height:1.75}
|
||
.ym-wrap *{box-sizing:border-box}
|
||
|
||
/* 顶部 */
|
||
.ym-hero{position:relative;overflow:hidden;border-radius:16px;padding:44px 36px 36px;text-align:center;background:linear-gradient(160deg,#1f2933 0%,#2d3a47 55%,#3a4a58 100%);color:#fff;box-shadow:0 18px 40px -22px rgba(31,41,51,.55)}
|
||
.ym-hero::after{content:"";position:absolute;inset:0;background:radial-gradient(circle at 50% 0%,rgba(212,160,23,.18),transparent 62%);pointer-events:none}
|
||
.ym-hero-inner{position:relative;z-index:1}
|
||
.ym-hero-mark{display:flex;justify-content:center;margin-bottom:16px}
|
||
.ym-hero-title{margin:0 0 10px;font-size:26px;font-weight:600;letter-spacing:.5px;color:#fff}
|
||
.ym-hero-sub{margin:0 auto 20px;max-width:520px;font-size:15px;color:rgba(255,255,255,.78);line-height:1.8}
|
||
.ym-hero-status{display:inline-flex;align-items:center;gap:8px;font-size:13px;padding:7px 16px;border-radius:999px;border:1px solid rgba(255,255,255,.22);background:rgba(255,255,255,.08);color:rgba(255,255,255,.9)}
|
||
.ym-hero-status.is-on{border-color:rgba(212,160,23,.55);background:rgba(212,160,23,.16);color:#f0d08a}
|
||
.ym-dot{width:7px;height:7px;border-radius:50%;background:#7f8b98;flex:0 0 auto}
|
||
.ym-hero-status.is-on .ym-dot{background:#e0b64a;box-shadow:0 0 0 3px rgba(224,182,74,.25);animation:ympulse 2.4s ease-in-out infinite}
|
||
@keyframes ympulse{0%,100%{opacity:1}50%{opacity:.45}}
|
||
|
||
/* 段落区块 */
|
||
.ym-sec{margin-top:34px;padding:0 6px}
|
||
.ym-sec-title{display:flex;align-items:center;gap:11px;margin:0 0 16px;font-size:17px;font-weight:600;color:var(--ym-ink)}
|
||
.ym-bar{display:block;width:3px;height:17px;border-radius:2px;background:linear-gradient(180deg,#d4a017,#8b6508);flex:0 0 auto}
|
||
.ym-prose p{margin:0 0 12px;font-size:15.5px;color:var(--ym-ink-soft)}
|
||
.ym-prose p:last-child{margin-bottom:0}
|
||
|
||
/* 日期列表 */
|
||
.ym-group-label{margin:18px 0 9px;font-size:12px;font-weight:600;letter-spacing:1.2px;color:#5f6b78;text-transform:uppercase}
|
||
.ym-group-label:first-child{margin-top:0}
|
||
.ym-days{display:grid;gap:8px}
|
||
.ym-day{display:flex;align-items:flex-start;gap:14px;padding:14px 16px;border-radius:10px;background:var(--ym-canvas,#f7f8fa);border:1px solid var(--ym-line);transition:border-color .18s ease,transform .18s ease}
|
||
.ym-day:hover{border-color:#cfd6de;transform:translateY(-1px)}
|
||
.ym-day.is-today{background:var(--ym-gold-soft);border-color:rgba(184,134,11,.45);box-shadow:0 6px 18px -12px rgba(184,134,11,.6)}
|
||
.ym-day-date{font-variant-numeric:tabular-nums;font-size:15px;font-weight:600;color:var(--ym-gold-text);flex:0 0 auto;letter-spacing:.4px;min-width:56px}
|
||
.ym-day-body{flex:1 1 auto;min-width:0}
|
||
.ym-day-name{font-size:14.5px;font-weight:600;color:var(--ym-ink);margin-bottom:3px}
|
||
.ym-day-note{font-size:13px;color:var(--ym-ink-soft);line-height:1.6}
|
||
/* 「今天」标签:白字压金底只有 3.25:1,11px 小字更看不清。
|
||
改用深金底 #8a6100(白字 5.54:1),既保住"金"的语义,又读得清。 */
|
||
.ym-day-tag{flex:0 0 auto;font-size:11px;font-weight:600;padding:2px 9px;border-radius:999px;background:#8a6100;color:#fff;letter-spacing:.5px}
|
||
.ym-extra{display:flex;flex-wrap:wrap;gap:8px}
|
||
.ym-extra-chip{font-size:13px;padding:5px 13px;border-radius:999px;background:var(--ym-gold-soft);color:#8b6508;border:1px solid rgba(184,134,11,.28);font-variant-numeric:tabular-nums}
|
||
.ym-empty{padding:18px 16px;border-radius:10px;background:var(--ym-canvas,#f7f8fa);border:1px dashed var(--ym-line)}
|
||
.ym-empty p{margin:0;font-size:14.5px;color:var(--ym-ink-soft)}
|
||
.ym-empty-note{margin-top:6px!important;font-size:13px!important;color:#9aa5b1!important}
|
||
|
||
/* 问答 */
|
||
.ym-faq{display:grid;gap:8px}
|
||
.ym-qa{border:1px solid var(--ym-line);border-radius:10px;background:#fff;overflow:hidden}
|
||
.ym-qa summary{cursor:pointer;padding:14px 16px;font-size:14.5px;font-weight:600;color:var(--ym-ink);list-style:none;display:flex;align-items:center;justify-content:space-between;gap:10px}
|
||
.ym-qa summary::-webkit-details-marker{display:none}
|
||
.ym-qa summary::after{content:"+";font-size:17px;font-weight:400;color:#9aa5b1;transition:transform .2s ease;flex:0 0 auto}
|
||
.ym-qa[open] summary::after{content:"−"}
|
||
.ym-qa-body{padding:0 16px 15px;font-size:14px;color:var(--ym-ink-soft);line-height:1.8}
|
||
|
||
/* 底部 */
|
||
.ym-foot{margin-top:40px;text-align:center}
|
||
.ym-foot-line{width:52px;height:2px;margin:0 auto 18px;border-radius:2px;background:linear-gradient(90deg,transparent,var(--ym-gold),transparent);opacity:.7}
|
||
.ym-foot-text{margin:0 0 10px;font-size:14px;color:#5f6b78;letter-spacing:2px}
|
||
.ym-foot-link{margin:0}
|
||
.ym-foot-link a{display:inline-block;font-size:14px;color:var(--ym-gold-text);text-decoration:none;padding:8px 22px;border:1px solid rgba(184,134,11,.4);border-radius:999px;transition:background-color .18s ease,color .18s ease}
|
||
.ym-foot-link a:hover{background:var(--ym-gold);color:#fff}
|
||
|
||
/* 窄屏 */
|
||
@media (max-width:640px){
|
||
.ym-hero{padding:34px 20px 28px;border-radius:12px}
|
||
.ym-hero-title{font-size:21px}
|
||
.ym-day{flex-wrap:wrap;gap:8px}
|
||
.ym-day-date{min-width:auto}
|
||
.ym-sec{padding:0}
|
||
}
|
||
|
||
/* 用户系统开了深色模式时,说明页也要能读 —— 不能因为皮肤深色就变成黑底黑字 */
|
||
@media (prefers-color-scheme:dark){
|
||
.ym-qa{background:#1f2933;border-color:#3a4a58}
|
||
.ym-qa summary{color:#e8edf2}
|
||
.ym-qa-body{color:#b8c2cc}
|
||
.ym-days .ym-day{background:#232f3a;border-color:#3a4a58}
|
||
.ym-day-name{color:#e8edf2}
|
||
.ym-day-note{color:#a7b2bd}
|
||
.ym-prose p{color:#b8c2cc}
|
||
.ym-sec-title{color:#e8edf2}
|
||
.ym-empty{background:#232f3a;border-color:#3a4a58}
|
||
.ym-empty p{color:#a7b2bd}
|
||
}
|
||
CSS;
|
||
return $css;
|
||
}
|
||
|
||
/**
|
||
* 说明页的固定路径
|
||
*
|
||
* 用固定 slug 而不是新建页面,理由:
|
||
* 新建页面会写进数据库,换主题或删主题后成孤儿;固定路径由主题判定,
|
||
* 升级即生效,卸载即消失,不留垃圾数据。
|
||
*/
|
||
function yang_mourning_page_slug()
|
||
{
|
||
// 允许用户在主题选项里改,默认 /memory
|
||
$slug = trim((string) kratos_option('g_rip_page_slug', 'memory'), '/');
|
||
return $slug === '' ? 'memory' : $slug;
|
||
}
|
||
|
||
/**
|
||
* 说明页的 URL
|
||
*/
|
||
function yang_mourning_page_url()
|
||
{
|
||
return home_url('/' . yang_mourning_page_slug() . '/');
|
||
}
|
||
|
||
/**
|
||
* 接管这个路径的请求
|
||
*
|
||
* 用 `parse_request` 而不是 `template_redirect`:越早判定,越不会先走
|
||
* 一遍「404 判定 → 主题 404 模板」的流程,也省掉多余的查询。
|
||
*/
|
||
function yang_mourning_page_route($wp)
|
||
{
|
||
if (is_admin()) {
|
||
return;
|
||
}
|
||
$slug = yang_mourning_page_slug();
|
||
$path = trim((string) parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH), '/');
|
||
|
||
// 去掉子目录安装的前缀
|
||
$home_path = trim((string) parse_url(home_url('/'), PHP_URL_PATH), '/');
|
||
if ($home_path !== '' && strpos($path, $home_path) === 0) {
|
||
$path = trim(substr($path, strlen($home_path)), '/');
|
||
}
|
||
|
||
// 允许带尾斜杠,也允许纯 slug
|
||
if ($path !== $slug) {
|
||
return;
|
||
}
|
||
|
||
/* 别抢占用户真的建过的页面。
|
||
* 如果站里已经有一个 slug 就叫 memory 的页面,用户点进去期待看到它,
|
||
* 结果被我们静默换成哀悼说明 —— 看起来就是"我的页面坏了",且毫无提示。
|
||
* 这个查询只在路径真的命中 slug 时才执行,正常请求零开销。
|
||
* 不用 function_exists 兜底:get_page_by_path 是 WP 1.5 就有的核心函数,
|
||
* 加兜底只会让"这道保护根本没生效"变得不可测。 */
|
||
if (get_page_by_path($slug)) {
|
||
return;
|
||
}
|
||
|
||
// 组装一个最小可用的 WP 查询环境,让主题的 header/footer 正常工作
|
||
$wp->query_vars = array();
|
||
status_header(200);
|
||
$GLOBALS['wp_query'] = new WP_Query(array('page_id' => 0));
|
||
$GLOBALS['wp_query']->is_404 = false;
|
||
|
||
include get_template_directory() . '/pages/page-mourning.php';
|
||
exit;
|
||
}
|
||
add_action('parse_request', 'yang_mourning_page_route', 5);
|
||
|
||
/**
|
||
* 注册短代码,便于在任意文章里嵌入说明
|
||
*/
|
||
function yang_mourning_shortcode($atts = array())
|
||
{
|
||
return yang_mourning_page_content();
|
||
}
|
||
add_shortcode('yang_mourning', 'yang_mourning_shortcode');
|