feat(frontend): align single related/prevnext/maxheight with Zibll
Honor prevnext/authordesc/yiyan settings, multi-tax related queries with orderby (incl. views), per-post maxheight override, and only expand content when maxheight is enabled.
This commit is contained in:
1 parent
32800ac2fd
commit
69bed0f068
8 files changed
+234
-40
No files matched your search
+174
-33
@@ -288,7 +288,12 @@ if (!function_exists('aksrt_single_render_box_header')) :
|
||||
<h1 class="article-title"><?php the_title(); ?></h1>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($settings['authordesc'])) : ?>
|
||||
<?php
|
||||
$show_author_bar = array_key_exists('authordesc', $settings)
|
||||
? !empty($settings['authordesc'])
|
||||
: !empty($settings['authordesc_s']);
|
||||
if ($show_author_bar) :
|
||||
?>
|
||||
<?php
|
||||
aksrt_single_render_author_bar([
|
||||
'show_actions' => true,
|
||||
@@ -480,79 +485,203 @@ endif;
|
||||
if (!function_exists('aksrt_single_render_prevnext')) :
|
||||
/**
|
||||
* Previous / next navigation.
|
||||
*
|
||||
* @param array<string,mixed> $ctx Single context.
|
||||
*/
|
||||
function aksrt_single_render_prevnext(): void {
|
||||
function aksrt_single_render_prevnext(array $ctx = []): void {
|
||||
$settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
|
||||
// Accept both canonical `prevnext` (Settings DTO) and legacy `prevnext_s`.
|
||||
$enabled = array_key_exists('prevnext', $settings)
|
||||
? !empty($settings['prevnext'])
|
||||
: (!array_key_exists('prevnext_s', $settings) || !empty($settings['prevnext_s']));
|
||||
if (!$enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$prev = get_previous_post();
|
||||
$next = get_next_post();
|
||||
if (!$prev && !$next) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<nav class="post-nav-box">
|
||||
<nav class="post-nav-box theme-box box-body radius8 main-shadow">
|
||||
<?php if ($prev) : ?>
|
||||
<a class="post-nav-box__item post-nav-box__item--prev" href="<?php echo esc_url(get_permalink($prev)); ?>">
|
||||
<span class="post-nav-box__label"><?php esc_html_e('上一篇', 'aksrt'); ?></span>
|
||||
<span class="post-nav-box__title"><?php echo esc_html(get_the_title($prev)); ?></span>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<span class="post-nav-box__item post-nav-box__item--prev is-empty" aria-hidden="true"></span>
|
||||
<?php endif; ?>
|
||||
<?php if ($next) : ?>
|
||||
<a class="post-nav-box__item post-nav-box__item--next" href="<?php echo esc_url(get_permalink($next)); ?>">
|
||||
<span class="post-nav-box__label"><?php esc_html_e('下一篇', 'aksrt'); ?></span>
|
||||
<span class="post-nav-box__title"><?php echo esc_html(get_the_title($next)); ?></span>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<span class="post-nav-box__item post-nav-box__item--next is-empty" aria-hidden="true"></span>
|
||||
<?php endif; ?>
|
||||
</nav>
|
||||
<?php
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_single_related_query_args')) :
|
||||
/**
|
||||
* Build related-posts WP_Query args (Zibll-like multi-tax OR + orderby).
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @param array<string,mixed> $settings Single display settings.
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
function aksrt_single_related_query_args(int $post_id, array $settings): array {
|
||||
$count = max(1, min(12, (int) ($settings['related_count'] ?? 6)));
|
||||
$type = sanitize_key((string) ($settings['related_type'] ?? 'category'));
|
||||
if (!in_array($type, ['category', 'tag', 'random'], true)) {
|
||||
$type = 'category';
|
||||
}
|
||||
$orderby = sanitize_key((string) ($settings['related_orderby'] ?? 'views'));
|
||||
if (!in_array($orderby, ['rand', 'relevance', 'date', 'views', 'modified'], true)) {
|
||||
$orderby = 'views';
|
||||
}
|
||||
|
||||
$args = [
|
||||
'post_type' => get_post_type($post_id) ?: 'post',
|
||||
'post_status' => 'publish',
|
||||
'post__not_in' => [$post_id],
|
||||
'posts_per_page' => $count,
|
||||
'ignore_sticky_posts' => true,
|
||||
'no_found_rows' => true,
|
||||
'order' => 'DESC',
|
||||
];
|
||||
|
||||
if ($type === 'random') {
|
||||
$args['orderby'] = 'rand';
|
||||
return $args;
|
||||
}
|
||||
|
||||
$tax_query = ['relation' => 'OR'];
|
||||
if ($type === 'tag') {
|
||||
$tag_ids = wp_get_post_terms($post_id, 'post_tag', ['fields' => 'ids']);
|
||||
if (!empty($tag_ids) && !is_wp_error($tag_ids)) {
|
||||
$tax_query[] = [
|
||||
'taxonomy' => 'post_tag',
|
||||
'field' => 'term_id',
|
||||
'terms' => array_map('intval', $tag_ids),
|
||||
];
|
||||
}
|
||||
} else {
|
||||
// category (default): OR across category + tags + topics like Zibll.
|
||||
$cat_ids = wp_get_post_terms($post_id, 'category', ['fields' => 'ids']);
|
||||
if (!empty($cat_ids) && !is_wp_error($cat_ids)) {
|
||||
$tax_query[] = [
|
||||
'taxonomy' => 'category',
|
||||
'field' => 'term_id',
|
||||
'terms' => array_map('intval', $cat_ids),
|
||||
];
|
||||
}
|
||||
$tag_ids = wp_get_post_terms($post_id, 'post_tag', ['fields' => 'ids']);
|
||||
if (!empty($tag_ids) && !is_wp_error($tag_ids)) {
|
||||
$tax_query[] = [
|
||||
'taxonomy' => 'post_tag',
|
||||
'field' => 'term_id',
|
||||
'terms' => array_map('intval', $tag_ids),
|
||||
];
|
||||
}
|
||||
if (taxonomy_exists('topics')) {
|
||||
$topic_ids = wp_get_post_terms($post_id, 'topics', ['fields' => 'ids']);
|
||||
if (!empty($topic_ids) && !is_wp_error($topic_ids)) {
|
||||
$tax_query[] = [
|
||||
'taxonomy' => 'topics',
|
||||
'field' => 'term_id',
|
||||
'terms' => array_map('intval', $topic_ids),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($tax_query) > 1) {
|
||||
$args['tax_query'] = $tax_query;
|
||||
}
|
||||
|
||||
switch ($orderby) {
|
||||
case 'rand':
|
||||
$args['orderby'] = 'rand';
|
||||
break;
|
||||
case 'date':
|
||||
$args['orderby'] = 'date';
|
||||
break;
|
||||
case 'modified':
|
||||
$args['orderby'] = 'modified';
|
||||
break;
|
||||
case 'views':
|
||||
$args['meta_key'] = 'aksrt_post_views';
|
||||
$args['orderby'] = 'meta_value_num';
|
||||
break;
|
||||
case 'relevance':
|
||||
default:
|
||||
// Prefer date when no search relevance context.
|
||||
$args['orderby'] = 'date';
|
||||
break;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_single_render_related')) :
|
||||
/**
|
||||
* Related posts via shared renderer.
|
||||
* Related posts — Zibll-like list + optional shared mini renderer.
|
||||
*
|
||||
* @param array<string,mixed> $ctx Single context.
|
||||
*/
|
||||
function aksrt_single_render_related(array $ctx): void {
|
||||
$settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
|
||||
if (empty($settings['related_enabled']) || !function_exists('aksrt_render_post_list')) {
|
||||
if (empty($settings['related_enabled'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post_id = (int) $ctx['post_id'];
|
||||
$count = max(1, min(12, (int) ($settings['related_count'] ?? 6)));
|
||||
$title = (string) ($settings['related_title'] ?? '');
|
||||
$args = [
|
||||
'post_type' => get_post_type($post_id),
|
||||
'post_status' => 'publish',
|
||||
'post__not_in' => [$post_id],
|
||||
'posts_per_page' => $count,
|
||||
'ignore_sticky_posts' => true,
|
||||
];
|
||||
|
||||
if (($settings['related_type'] ?? 'category') === 'tag') {
|
||||
$tag_ids = wp_get_post_terms($post_id, 'post_tag', ['fields' => 'ids']);
|
||||
if (!empty($tag_ids) && !is_wp_error($tag_ids)) {
|
||||
$args['tag__in'] = $tag_ids;
|
||||
}
|
||||
} else {
|
||||
$cat_ids = wp_get_post_terms($post_id, 'category', ['fields' => 'ids']);
|
||||
if (!empty($cat_ids) && !is_wp_error($cat_ids)) {
|
||||
$args['category__in'] = $cat_ids;
|
||||
}
|
||||
if ($title === '') {
|
||||
$title = __('相关文章', 'aksrt');
|
||||
}
|
||||
|
||||
$args = function_exists('aksrt_single_related_query_args')
|
||||
? aksrt_single_related_query_args($post_id, $settings)
|
||||
: [
|
||||
'post_type' => get_post_type($post_id),
|
||||
'post_status' => 'publish',
|
||||
'post__not_in' => [$post_id],
|
||||
'posts_per_page' => max(1, min(12, (int) ($settings['related_count'] ?? 6))),
|
||||
'ignore_sticky_posts' => true,
|
||||
];
|
||||
|
||||
$query = new WP_Query($args);
|
||||
if (!$query->have_posts()) {
|
||||
wp_reset_postdata();
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="related-box theme-box box-body radius8 main-shadow">
|
||||
<div class="related-box__header">
|
||||
<h3 class="related-box__title"><?php echo esc_html($title !== '' ? $title : __('相关文章', 'aksrt')); ?></h3>
|
||||
<div class="theme-box relates related-box">
|
||||
<div class="box-body notop">
|
||||
<div class="title-theme related-box__title"><?php echo esc_html($title); ?></div>
|
||||
</div>
|
||||
<div class="related-box__list">
|
||||
<?php aksrt_render_post_list($query, ['context' => 'related', 'mode' => 'card', 'card_style' => 'standard']); ?>
|
||||
<div class="zib-widget related-box__list">
|
||||
<?php if (function_exists('aksrt_render_post_list')) : ?>
|
||||
<?php aksrt_render_post_list($query, ['context' => 'related', 'mode' => 'mini', 'show_thumb' => true, 'show_meta' => true]); ?>
|
||||
<?php else : ?>
|
||||
<ul class="no-thumb related-list">
|
||||
<?php
|
||||
while ($query->have_posts()) :
|
||||
$query->the_post();
|
||||
?>
|
||||
<li>
|
||||
<a class="icon-circle" href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
|
||||
</li>
|
||||
<?php endwhile; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
@@ -590,10 +719,12 @@ if (!function_exists('aksrt_single_render_article')) :
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="theme-box wp-posts-content entry-content<?php echo $maxheight > 0 ? ' limit-height' : ''; ?>"
|
||||
<?php echo $maxheight > 0 ? ' style="max-height:' . esc_attr((string) $maxheight) . 'px;"' : ''; ?>
|
||||
data-nav="posts"
|
||||
data-maxheight="<?php echo esc_attr((string) $maxheight); ?>"
|
||||
data-aksrt-toc="<?php echo !empty($ctx['show_toc']) ? '1' : '0'; ?>"
|
||||
data-aksrt-toc-depth="<?php echo esc_attr((string) ((int) ($settings['toc_depth'] ?? 3))); ?>">
|
||||
data-aksrt-toc-depth="<?php echo esc_attr((string) ((int) ($settings['toc_depth'] ?? 3))); ?>"
|
||||
<?php echo !empty($settings['lightbox']) ? ' data-aksrt-lightbox="1"' : ''; ?>>
|
||||
<?php the_content(); ?>
|
||||
<?php
|
||||
wp_link_pages([
|
||||
@@ -622,18 +753,28 @@ endif;
|
||||
|
||||
if (!function_exists('aksrt_single_render_after_box')) :
|
||||
/**
|
||||
* After-article stack: author card / prevnext / related.
|
||||
* After-article stack: yiyan box / author card / prevnext / related.
|
||||
*
|
||||
* @param array<string,mixed> $ctx Single context.
|
||||
*/
|
||||
function aksrt_single_render_after_box(array $ctx): void {
|
||||
$settings = is_array($ctx['settings'] ?? null) ? $ctx['settings'] : [];
|
||||
|
||||
if (!empty($settings['authordesc'])) {
|
||||
if (!empty($settings['yiyan_box'])) {
|
||||
?>
|
||||
<div class="yiyan-box main-bg theme-box text-center box-body radius8 main-shadow aksrt-yiyan" data-aksrt-yiyan data-type="hitokoto"></div>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Accept both `authordesc` (Settings DTO) and legacy `authordesc_s`.
|
||||
$show_author = array_key_exists('authordesc', $settings)
|
||||
? !empty($settings['authordesc'])
|
||||
: !empty($settings['authordesc_s']);
|
||||
if ($show_author) {
|
||||
aksrt_single_render_author_card($ctx);
|
||||
}
|
||||
|
||||
aksrt_single_render_prevnext();
|
||||
aksrt_single_render_prevnext($ctx);
|
||||
aksrt_single_render_related($ctx);
|
||||
}
|
||||
endif;
|
||||
|
||||
Reference in new issue
Block a user