fix(single): align author-bar publish time with the reference
The publish time under the author name diverged from the reference in four ways: it rendered a leading bullet from `.icon-circle`, its tooltip opened above instead of below, its wording was "2 天发布" (WordPress' human_time_diff has no 前 and keeps spaces), and it ignored the 「时间显示数据源」 setting entirely. - markup: drop `.icon-circle` from the time span and the description fallback; add `data-placement="bottom"` so the tooltip opens below like the reference - wording: use jio_time_ago() (which already ends in 前) and append only 发布 / 更新, yielding "2天前发布" - branches: mirror zib_get_post_time_tooltip exactly (date source → publish time; unpublished → modified time; published-with-update → modified time labelled 更新 while the tooltip keeps the publish time; otherwise publish) - the setting is read from post_time_source via get_post_list_style_settings() Tests: new author-bar-time suite drives the real template through a stub harness across all four branches (4/4); widget suite 833/834 with the pre-existing frontend-lifecycle failure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
f14e6bd88d
commit
f6fde18857
3 files changed
+208
-11
No files matched your search
@@ -18,15 +18,51 @@ $meta_html = (string) ($args['meta_html'] ?? '');
|
||||
$author_id = (int) get_the_author_meta('ID');
|
||||
$author_name = get_the_author();
|
||||
$author_url = function_exists('jio_get_user_home_url') ? jio_get_user_home_url($author_id) : get_author_posts_url($author_id);
|
||||
$modified_ts = (int) get_the_modified_time('U');
|
||||
$published_ts = (int) get_the_time('U');
|
||||
$use_modified = $modified_ts > $published_ts;
|
||||
$rel_base = $use_modified ? $modified_ts : $published_ts;
|
||||
$rel_label = $use_modified ? __('更新', 'jio') : __('发布', 'jio');
|
||||
$abs_fmt = $use_modified
|
||||
? sprintf(__('%s更新', 'jio'), get_the_modified_time('Y年m月d日 H:i'))
|
||||
: sprintf(__('%s发布', 'jio'), get_the_time('Y年m月d日 H:i'));
|
||||
$time_text = human_time_diff($rel_base, (int) current_time('timestamp')) . $rel_label;
|
||||
|
||||
// 时间显示:完全按参考主题 zib_get_post_time_tooltip 的分支顺序。
|
||||
// 1) 数据源 date → 发布时间
|
||||
// 2) 非已发布状态 → 更新时间
|
||||
// 3) 更新时间 > 发布时间 → 文案用更新时间+「更新」,tooltip 仍为发布时间+「发布」
|
||||
// 4) 其余 → 发布时间
|
||||
$time_source = '';
|
||||
if (class_exists('\Jio\Settings\Settings')) {
|
||||
$list_settings = \Jio\Settings\Settings::get_post_list_style_settings();
|
||||
$time_source = (string) ($list_settings['post_time_source'] ?? 'modified');
|
||||
}
|
||||
$is_published = (string) get_post_status(get_the_ID()) === 'publish';
|
||||
$published_mysql = (string) get_the_time('Y-m-d H:i:s');
|
||||
$modified_mysql = (string) get_the_modified_time('Y-m-d H:i:s');
|
||||
$has_update = (int) strtotime($modified_mysql) > (int) strtotime($published_mysql);
|
||||
|
||||
$published_title = sprintf(__('%s发布', 'jio'), get_the_time('Y年m月d日 H:i'));
|
||||
$modified_title = sprintf(__('%s更新', 'jio'), get_the_modified_time('Y年m月d日 H:i'));
|
||||
|
||||
if ($time_source === 'date') {
|
||||
// 1) 强制发布时间源。
|
||||
$time_mysql = $published_mysql;
|
||||
$rel_label = __('发布', 'jio');
|
||||
$abs_fmt = $published_title;
|
||||
} elseif (!$is_published) {
|
||||
// 2) 草稿/待审等:参考固定展示更新时间。
|
||||
$time_mysql = $modified_mysql;
|
||||
$rel_label = __('更新', 'jio');
|
||||
$abs_fmt = $modified_title;
|
||||
} elseif ($has_update) {
|
||||
// 3) 已发布且有更新:文案取更新时间,tooltip 仍标注发布时间。
|
||||
$time_mysql = $modified_mysql;
|
||||
$rel_label = __('更新', 'jio');
|
||||
$abs_fmt = $published_title;
|
||||
} else {
|
||||
// 4) 未更新过:发布时间。
|
||||
$time_mysql = $published_mysql;
|
||||
$rel_label = __('发布', 'jio');
|
||||
$abs_fmt = $published_title;
|
||||
}
|
||||
// 相对时间本身已含「前」,只拼接「发布 / 更新」。
|
||||
$time_ago = function_exists('jio_time_ago')
|
||||
? jio_time_ago($time_mysql)
|
||||
: human_time_diff((int) strtotime($time_mysql), (int) current_time('timestamp')) . __('前', 'jio');
|
||||
$time_text = $time_ago . $rel_label;
|
||||
$description = function_exists('jio_get_user_description')
|
||||
? jio_get_user_description($author_id)
|
||||
: trim((string) get_the_author_meta('description'));
|
||||
@@ -62,9 +98,9 @@ $reward_button = get_current_user_id() !== $author_id && function_exists('jio_ge
|
||||
<?php echo $name_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<div class="px12-sm muted-2-color text-ellipsis">
|
||||
<?php if ($show_time) : ?>
|
||||
<span class="icon-circle" title="<?php echo esc_attr($abs_fmt); ?>" data-toggle="tooltip"><?php echo esc_html($time_text); ?></span>
|
||||
<span data-toggle="tooltip" data-placement="bottom" title="<?php echo esc_attr($abs_fmt); ?>"><?php echo esc_html($time_text); ?></span>
|
||||
<?php elseif ($description !== '') : ?>
|
||||
<span class="icon-circle"><?php echo esc_html($description); ?></span>
|
||||
<span><?php echo esc_html($description); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
$post_city = function_exists('jio_get_post_author_city_badge_html')
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
'use strict';
|
||||
/**
|
||||
* 文章页作者栏「发布时间」契约(对齐参考主题 zib_get_post_time_tooltip):
|
||||
* 纯文本相对时间 + data-placement="bottom" 的 tooltip,不渲染列表圆点前缀,
|
||||
* 且按参考的四个分支决定显示发布时间还是更新时间。
|
||||
*/
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const test = require('node:test');
|
||||
const { spawnSync } = require('node:child_process');
|
||||
|
||||
const root = path.resolve(__dirname, '..', '..');
|
||||
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
|
||||
const authorBar = read('templates/parts/single-author-bar.php');
|
||||
|
||||
test('作者栏时间与参考主题同构:tooltip 在下方、无 icon-circle 圆点', () => {
|
||||
assert.match(
|
||||
authorBar,
|
||||
/<span data-toggle="tooltip" data-placement="bottom" title="<\?php echo esc_attr\(\$abs_fmt\); \?>"><\?php echo esc_html\(\$time_text\); \?><\/span>/,
|
||||
'时间必须是无前缀圆点的 <span>,tooltip 置于下方'
|
||||
);
|
||||
assert.doesNotMatch(authorBar, /<span class="icon-circle"[^>]*data-toggle="tooltip"/, '作者栏时间不得再带 icon-circle 圆点');
|
||||
assert.doesNotMatch(authorBar, /<span class="icon-circle">/, '隐藏时间后的作者简介同样不应带圆点');
|
||||
});
|
||||
|
||||
test('相对时间文案不重复「前」,与参考一致', () => {
|
||||
assert.match(authorBar, /\$time_text = \$time_ago \. \$rel_label;/, '时间文案应为「相对时间 + 发布/更新」');
|
||||
assert.match(authorBar, /function_exists\('jio_time_ago'\)[\s\S]{0,160}: human_time_diff\(/, '缺少 jio_time_ago 时才回退 human_time_diff');
|
||||
assert.doesNotMatch(
|
||||
authorBar,
|
||||
/human_time_diff\(\$rel_base, \(int\) current_time\('timestamp'\)\) \. \$rel_label/,
|
||||
'不得再用裸 human_time_diff 拼接,会少「前」字'
|
||||
);
|
||||
});
|
||||
|
||||
test('时间分支复刻参考:数据源 / 非发布 / 有更新 三种判定', () => {
|
||||
assert.match(authorBar, /get_post_list_style_settings\(\)/, '时间源应读取列表风格设置');
|
||||
assert.match(authorBar, /\$has_update = \(int\) strtotime\(\$modified_mysql\) > \(int\) strtotime\(\$published_mysql\);/, '以时间戳比较判断是否更新过');
|
||||
|
||||
const dateBranch = authorBar.match(/if \(\$time_source === 'date'\) \{[\s\S]*?\n\}/);
|
||||
assert.ok(dateBranch, '缺少 date 数据源分支');
|
||||
assert.match(dateBranch[0], /\$time_mysql = \$published_mysql;/, 'date 源固定用发布时间');
|
||||
assert.match(dateBranch[0], /\$abs_fmt = \$published_title;/, 'date 源 tooltip 标注发布');
|
||||
|
||||
const unpublished = authorBar.match(/\} elseif \(!\$is_published\) \{[\s\S]*?\n\}/);
|
||||
assert.ok(unpublished, '缺少非发布状态分支');
|
||||
assert.match(unpublished[0], /\$time_mysql = \$modified_mysql;/, '非发布状态用更新时间');
|
||||
assert.match(unpublished[0], /\$abs_fmt = \$modified_title;/, '非发布状态 tooltip 标注更新');
|
||||
|
||||
const updated = authorBar.match(/\} elseif \(\$has_update\) \{[\s\S]*?\n\}/);
|
||||
assert.ok(updated, '缺少「有更新」分支');
|
||||
assert.match(updated[0], /\$time_mysql = \$modified_mysql;/, '有更新时展示更新时间的相对值');
|
||||
// 参考主题此分支的 tooltip 仍标注发布时间,保持逐字一致。
|
||||
assert.match(updated[0], /\$abs_fmt = \$published_title;/, '有更新的已发布文章 tooltip 仍标注发布时间');
|
||||
assert.doesNotMatch(updated[0], /\$modified_title/, '该分支不应在 tooltip 标注更新');
|
||||
});
|
||||
|
||||
test('作者栏时间渲染:四分支输出与参考组合一致', () => {
|
||||
const harness = path.join(__dirname, 'author-bar-time-harness.php');
|
||||
const result = spawnSync(process.env.PHP_BINARY || 'php', [harness], { cwd: root, encoding: 'utf8' });
|
||||
assert.equal(result.status, 0, result.stderr || result.stdout);
|
||||
const cases = JSON.parse(result.stdout);
|
||||
|
||||
assert.deepEqual(cases['date_updated'], { text: '5天前发布', title: '2026年10月29日 08:00发布' });
|
||||
assert.deepEqual(cases['modified_clean'], { text: '5天前发布', title: '2026年10月29日 08:00发布' });
|
||||
assert.deepEqual(cases['modified_updated'], { text: '1天前更新', title: '2026年10月29日 08:00发布' });
|
||||
assert.deepEqual(cases['draft'], { text: '1天前更新', title: '2026年11月02日 09:00更新' });
|
||||
});
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/**
|
||||
* Render the author bar across the four reference time branches and report the
|
||||
* time `<span>` text/title. Fixed clock so the expectations are deterministic.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
define('ABSPATH', dirname(__DIR__, 2) . DIRECTORY_SEPARATOR);
|
||||
|
||||
// 固定时钟:2026-11-03 12:00:00(站点时区)。
|
||||
$GLOBALS['NOW'] = strtotime('2026-11-03 12:00:00');
|
||||
$GLOBALS['STATUS'] = 'publish';
|
||||
$GLOBALS['SOURCE'] = 'modified';
|
||||
$GLOBALS['PUBLISHED'] = strtotime('2026-10-29 08:00:00');
|
||||
$GLOBALS['MODIFIED'] = strtotime('2026-10-29 08:00:00');
|
||||
$GLOBALS['TIME_AGO'] = false;
|
||||
|
||||
function __($text): string { return (string) $text; }
|
||||
function esc_html($value): string { return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
|
||||
function esc_attr($value): string { return esc_html($value); }
|
||||
function esc_url($value): string { return (string) $value; }
|
||||
function esc_url_raw($value): string { return (string) $value; }
|
||||
function wp_kses_post($value): string { return (string) $value; }
|
||||
|
||||
function get_the_author_meta($key) { return $key === 'ID' ? 7 : '张三'; }
|
||||
function get_the_author(): string { return '张三'; }
|
||||
function jio_get_user_home_url($id): string { return '/u/' . (int) $id; }
|
||||
function get_author_posts_url($id): string { return '/author/' . (int) $id; }
|
||||
function get_post_status($post = null): string { return $GLOBALS['STATUS']; }
|
||||
function get_the_time($format) { return format_time((int) $GLOBALS['PUBLISHED'], $format); }
|
||||
function get_the_modified_time($format) { return format_time((int) $GLOBALS['MODIFIED'], $format); }
|
||||
function current_time($type) { return $type === 'timestamp' ? (int) $GLOBALS['NOW'] : date('Y-m-d H:i:s', (int) $GLOBALS['NOW']); }
|
||||
function format_time(int $timestamp, $format) {
|
||||
return $format === 'U' ? (string) $timestamp : date((string) $format, $timestamp);
|
||||
}
|
||||
|
||||
/** 与生产同一套相对时间规则,但以固定 NOW 为基准。 */
|
||||
function jio_time_ago(string $date): string {
|
||||
$time = (int) strtotime($date);
|
||||
$diff = (int) $GLOBALS['NOW'] - $time;
|
||||
$days = (int) floor($diff / 86400);
|
||||
return $days > 0 ? $days . '天前' : '刚刚';
|
||||
}
|
||||
|
||||
function human_time_diff($from, $to = 0): string { return 'x'; }
|
||||
function get_the_ID(): int { return 42; }
|
||||
function get_current_user_id(): int { return 0; }
|
||||
function jio_get_user_description($id): string { return '作者简介'; }
|
||||
function jio_get_user_name(array $args): string { return '<a class="display-name">张三</a>'; }
|
||||
function jio_get_user_follow($class, $id): string { return ''; }
|
||||
function jio_get_rewards_button($id, $class, $post_id): string { return ''; }
|
||||
function jio_get_avatar_html($id, $size, array $args): string { return '<img>'; }
|
||||
function get_avatar($id, $size, $default, $alt, array $args): string { return '<img>'; }
|
||||
function jio_render_rewards_template_for_user($author_id, $post_id): void {}
|
||||
function jio_get_post_author_city_badge_html($author_id, $class): string { return ''; }
|
||||
|
||||
class JioSettingsStub {
|
||||
public static function get_post_list_style_settings(): array {
|
||||
return ['post_time_source' => (string) $GLOBALS['SOURCE']];
|
||||
}
|
||||
}
|
||||
class_alias('JioSettingsStub', 'Jio\\Settings\\Settings');
|
||||
|
||||
$cases = [
|
||||
'date_updated' => ['publish', 'date', '2026-10-29 08:00:00', '2026-11-02 09:00:00'],
|
||||
'modified_clean' => ['publish', 'modified', '2026-10-29 08:00:00', '2026-10-29 08:00:00'],
|
||||
'modified_updated' => ['publish', 'modified', '2026-10-29 08:00:00', '2026-11-02 09:00:00'],
|
||||
'draft' => ['draft', 'modified', '2026-10-29 08:00:00', '2026-11-02 09:00:00'],
|
||||
];
|
||||
|
||||
$out = [];
|
||||
foreach ($cases as $name => [$status, $source, $published, $modified]) {
|
||||
$GLOBALS['STATUS'] = $status;
|
||||
$GLOBALS['SOURCE'] = $source;
|
||||
$GLOBALS['PUBLISHED'] = strtotime($published);
|
||||
$GLOBALS['MODIFIED'] = strtotime($modified);
|
||||
|
||||
ob_start();
|
||||
$args = ['show_time' => true, 'meta_html' => ''];
|
||||
include ABSPATH . 'templates/parts/single-author-bar.php';
|
||||
$html = (string) ob_get_clean();
|
||||
|
||||
$text = '';
|
||||
$title = '';
|
||||
if (preg_match('/<span data-toggle="tooltip" data-placement="bottom" title="([^"]*)">([^<]*)<\/span>/', $html, $m)) {
|
||||
$title = html_entity_decode($m[1], ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
$text = html_entity_decode($m[2], ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
}
|
||||
$out[$name] = ['text' => $text, 'title' => $title];
|
||||
}
|
||||
|
||||
echo json_encode($out, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
|
||||
Reference in new issue
Block a user