feat(frontend): replace article system with Zibll 9.0
This commit is contained in:
@@ -130,8 +130,6 @@ if (!function_exists('aksrt_archive_render_filter_bar')) :
|
||||
'ajax' => false,
|
||||
'ajax_archive' => '',
|
||||
'term_id' => 0,
|
||||
'layout_mode' => 'card',
|
||||
'card_style' => 'standard',
|
||||
'aria_label' => '',
|
||||
'meta_text' => '',
|
||||
'groups' => [],
|
||||
@@ -157,8 +155,6 @@ if (!function_exists('aksrt_archive_render_filter_bar')) :
|
||||
data-ajax-archive="<?php echo esc_attr((string) $args['ajax_archive']); ?>"
|
||||
data-term-id="<?php echo (int) $args['term_id']; ?>"
|
||||
data-query-context="archive"
|
||||
data-render-mode="<?php echo esc_attr((string) $args['layout_mode']); ?>"
|
||||
data-card-style="<?php echo esc_attr((string) $args['card_style']); ?>"
|
||||
<?php endif; ?>
|
||||
>
|
||||
<?php foreach ($groups as $group) : ?>
|
||||
|
||||
+21
-176
@@ -16,45 +16,15 @@ if (!function_exists('aksrt_archive_get_list_style_settings')) :
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
function aksrt_archive_get_list_style_settings(): array {
|
||||
$settings = class_exists('\AKSRT\Settings\Settings')
|
||||
return class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::get_post_list_style_settings()
|
||||
: [];
|
||||
|
||||
return [
|
||||
'list_type' => (string) ($settings['list_type'] ?? 'thumb'),
|
||||
'render_mode' => (string) ($settings['render_mode'] ?? 'list'),
|
||||
'list_type_token' => (string) ($settings['list_type_token'] ?? ($settings['list_type'] ?? 'thumb')),
|
||||
'list_style' => (string) ($settings['list_style'] ?? ''),
|
||||
'card_variant' => (string) ($settings['card_variant'] ?? ''),
|
||||
// Back-compat: older callers expected card_style as list_type token.
|
||||
'card_style' => (string) ($settings['list_type'] ?? ($settings['card_style'] ?? 'thumb')),
|
||||
'card_cat_ids' => is_array($settings['card_cat_ids'] ?? null) ? array_map('intval', $settings['card_cat_ids']) : [],
|
||||
'card_home' => !empty($settings['card_home']),
|
||||
'card_tag' => !empty($settings['card_tag']),
|
||||
'card_author' => !empty($settings['card_author']),
|
||||
'list_show_type' => (string) ($settings['list_show_type'] ?? 'separate'),
|
||||
'list_img_position'=> (string) ($settings['list_img_position'] ?? 'left'),
|
||||
'show_author' => !isset($settings['show_author']) || !empty($settings['show_author']),
|
||||
'show_date' => !isset($settings['show_date']) || !empty($settings['show_date']),
|
||||
'show_views' => !isset($settings['show_views']) || !empty($settings['show_views']),
|
||||
'show_comments' => !empty($settings['show_comments']),
|
||||
'show_likes' => !empty($settings['show_likes']),
|
||||
'target_blank' => !empty($settings['target_blank']),
|
||||
'heading_bold' => !empty($settings['heading_bold']),
|
||||
'badge_show' => !isset($settings['badge_show']) || !empty($settings['badge_show']),
|
||||
'excerpt_length' => (int) ($settings['excerpt_length'] ?? 120),
|
||||
];
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_resolve_post_list_render_config')) :
|
||||
/**
|
||||
* Zibll-aligned list/card resolver for all surfaces.
|
||||
*
|
||||
* Decision order mirrors zib_mian_posts_while():
|
||||
* 1) explicit override mode/type
|
||||
* 2) global list_type (post_card_style): only "card" is card grid; thumb/text/thumb_if_has are list
|
||||
* 3) surface card switches (home/tag/author/cat IDs)
|
||||
* Build the Zibll-shaped arguments used by every list surface.
|
||||
*
|
||||
* @param array<string,mixed> $args {
|
||||
* @type string $context home|category|tag|author|search|archive
|
||||
@@ -66,16 +36,10 @@ if (!function_exists('aksrt_resolve_post_list_render_config')) :
|
||||
function aksrt_resolve_post_list_render_config(array $args = []): array {
|
||||
$args = wp_parse_args($args, [
|
||||
'context' => '',
|
||||
'term_id' => 0,
|
||||
'overrides' => [],
|
||||
]);
|
||||
|
||||
$overrides = is_array($args['overrides']) ? $args['overrides'] : [];
|
||||
if (!empty($args['context']) && empty($overrides['context'])) {
|
||||
// keep context on root for merge below
|
||||
}
|
||||
|
||||
$context = sanitize_key((string) ($args['context'] !== '' ? $args['context'] : ($overrides['context'] ?? '')));
|
||||
$context = sanitize_key((string) ($args['context'] ?: ($overrides['context'] ?? '')));
|
||||
if ($context === '') {
|
||||
if (function_exists('is_front_page') && (is_front_page() || is_home())) {
|
||||
$context = 'home';
|
||||
@@ -91,125 +55,20 @@ if (!function_exists('aksrt_resolve_post_list_render_config')) :
|
||||
$context = 'archive';
|
||||
}
|
||||
}
|
||||
|
||||
$term_id = (int) ($args['term_id'] ?? 0);
|
||||
if ($term_id <= 0) {
|
||||
$term_id = (int) get_queried_object_id();
|
||||
}
|
||||
|
||||
$list = aksrt_archive_get_list_style_settings();
|
||||
$list_type = sanitize_key((string) ($list['list_type'] ?? 'thumb'));
|
||||
if ($list_type === '' || $list_type === 'standard') {
|
||||
$list_type = 'thumb';
|
||||
}
|
||||
|
||||
// Explicit caller mode wins (term meta, AJAX view toggle, etc.).
|
||||
$forced_mode = '';
|
||||
if (isset($overrides['mode']) && is_string($overrides['mode']) && $overrides['mode'] !== '') {
|
||||
$forced_mode = sanitize_key($overrides['mode']);
|
||||
} elseif (isset($overrides['type']) && sanitize_key((string) $overrides['type']) === 'card') {
|
||||
$forced_mode = 'card';
|
||||
} elseif (!empty($overrides['is_card'])) {
|
||||
$forced_mode = 'card';
|
||||
}
|
||||
|
||||
$mode = $forced_mode !== ''
|
||||
? $forced_mode
|
||||
: (($list_type === 'card') ? 'card' : 'list');
|
||||
|
||||
// Surface card overrides (only when not already card from list_type / force).
|
||||
if ($mode !== 'card' && $forced_mode === '') {
|
||||
if ($context === 'home' && !empty($list['card_home'])) {
|
||||
$mode = 'card';
|
||||
} elseif ($context === 'tag' && !empty($list['card_tag'])) {
|
||||
$mode = 'card';
|
||||
} elseif ($context === 'author' && !empty($list['card_author'])) {
|
||||
$mode = 'card';
|
||||
} elseif ($term_id > 0 && !empty($list['card_cat_ids']) && in_array($term_id, array_map('intval', (array) $list['card_cat_ids']), true)) {
|
||||
$mode = 'card';
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array($mode, ['list', 'card', 'mini', 'grid-cms'], true)) {
|
||||
$mode = 'list';
|
||||
}
|
||||
|
||||
// Visual variant: list → style2; card → style3 (Zibll fieldsets).
|
||||
$style = '';
|
||||
if ($mode === 'card') {
|
||||
$style = sanitize_key((string) ($list['card_variant'] ?? ''));
|
||||
if (!in_array($style, ['', 'style3'], true)) {
|
||||
$style = '';
|
||||
}
|
||||
} else {
|
||||
$style = sanitize_key((string) ($list['list_style'] ?? ''));
|
||||
if (!in_array($style, ['', 'style2'], true)) {
|
||||
$style = '';
|
||||
}
|
||||
}
|
||||
if (isset($overrides['style']) && is_string($overrides['style'])) {
|
||||
$style = sanitize_key($overrides['style']);
|
||||
if (in_array($style, ['default', 'null'], true)) {
|
||||
$style = '';
|
||||
}
|
||||
}
|
||||
|
||||
$excerpt_words = max(8, (int) round(((int) ($list['excerpt_length'] ?? 120)) / 4));
|
||||
|
||||
$config = [
|
||||
'context' => $context,
|
||||
'mode' => $mode,
|
||||
// list_type token for text / thumb_if_has hooks (renderer card_style key).
|
||||
'card_style' => $list_type,
|
||||
'style' => $style === 'default' ? '' : $style,
|
||||
'list_show_type' => (string) ($list['list_show_type'] ?? 'separate'),
|
||||
'list_img_position' => (string) ($list['list_img_position'] ?? 'left'),
|
||||
'thumb_if_has' => ($list_type === 'thumb_if_has'),
|
||||
'show_thumb' => ($list_type !== 'text'),
|
||||
'show_author' => !empty($list['show_author']),
|
||||
'show_date' => !empty($list['show_date']),
|
||||
'show_views' => !empty($list['show_views']),
|
||||
'show_comments' => !empty($list['show_comments']),
|
||||
'show_likes' => !empty($list['show_likes']),
|
||||
'target_blank' => !empty($list['target_blank']),
|
||||
'heading_bold' => !empty($list['heading_bold']),
|
||||
'badge_show' => !empty($list['badge_show']),
|
||||
'show_excerpt' => $mode !== 'card',
|
||||
'excerpt_words' => $excerpt_words,
|
||||
'context' => $context,
|
||||
'is_home' => $context === 'home',
|
||||
'is_category' => $context === 'category',
|
||||
'is_tag' => $context === 'tag',
|
||||
'is_author' => $context === 'author',
|
||||
'is_search' => $context === 'search',
|
||||
];
|
||||
|
||||
// Multi-thumb from global thumb settings + category allowlist.
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
$thumb_settings = \AKSRT\Settings\Settings::get_post_thumb_settings();
|
||||
if (!empty($thumb_settings['multi_enabled'])) {
|
||||
$config['multi_thumb_enabled'] = true;
|
||||
$config['multi_thumb_limit'] = (int) ($thumb_settings['multi_count'] ?? 4);
|
||||
$config['multi_thumb_min'] = 3;
|
||||
}
|
||||
if ($context === 'category' && !empty($thumb_settings['mult_thumb_cat_ids']) && $term_id > 0) {
|
||||
if (in_array($term_id, array_map('intval', (array) $thumb_settings['mult_thumb_cat_ids']), true)) {
|
||||
$config['multi_thumb_enabled'] = true;
|
||||
$config['multi_thumb_limit'] = (int) ($thumb_settings['multi_count'] ?? 4);
|
||||
$config['multi_thumb_min'] = 3;
|
||||
}
|
||||
foreach (['type', 'no_author', 'no_margin', 'is_mult_thumb', 'is_no_thumb', 'is_card', 'highlight_query', 'wrapper_class', 'skip_wrapper'] as $key) {
|
||||
if (array_key_exists($key, $overrides)) {
|
||||
$config[$key] = $overrides[$key];
|
||||
}
|
||||
}
|
||||
|
||||
// Merge remaining overrides last (except mode/style already handled carefully).
|
||||
foreach ($overrides as $key => $value) {
|
||||
if (in_array($key, ['mode', 'type', 'is_card', 'style', 'context'], true)) {
|
||||
continue;
|
||||
}
|
||||
$config[$key] = $value;
|
||||
}
|
||||
// Re-apply forced mode after merge if present.
|
||||
if ($forced_mode !== '' && in_array($forced_mode, ['list', 'card', 'mini', 'grid-cms'], true)) {
|
||||
$config['mode'] = $forced_mode;
|
||||
}
|
||||
$config['context'] = $context;
|
||||
$config['style'] = $style === 'default' ? '' : $style;
|
||||
|
||||
return $config;
|
||||
return aksrt_renderer_config($config);
|
||||
}
|
||||
endif;
|
||||
|
||||
@@ -222,18 +81,9 @@ if (!function_exists('aksrt_archive_get_render_config')) :
|
||||
*/
|
||||
function aksrt_archive_get_render_config(array $overrides = []): array {
|
||||
$context = sanitize_key((string) ($overrides['context'] ?? ''));
|
||||
$term_id = isset($overrides['term_id']) ? (int) $overrides['term_id'] : 0;
|
||||
|
||||
// Only treat explicit mode as override; empty string means follow global resolver.
|
||||
$resolver_overrides = $overrides;
|
||||
if (isset($resolver_overrides['mode']) && $resolver_overrides['mode'] === '') {
|
||||
unset($resolver_overrides['mode']);
|
||||
}
|
||||
|
||||
return aksrt_resolve_post_list_render_config([
|
||||
'context' => $context,
|
||||
'term_id' => $term_id,
|
||||
'overrides' => $resolver_overrides,
|
||||
'overrides' => $overrides,
|
||||
]);
|
||||
}
|
||||
endif;
|
||||
@@ -351,15 +201,14 @@ if (!function_exists('aksrt_archive_render_stream')) :
|
||||
$classes[] = 'is-ajax-enabled';
|
||||
}
|
||||
|
||||
$mode = (string) ($render_config['mode'] ?? 'card');
|
||||
$card_style = (string) ($render_config['card_style'] ?? 'standard');
|
||||
$mode = (string) ($render_config['mode'] ?? 'list');
|
||||
$has_posts = $query instanceof WP_Query ? $query->have_posts() : have_posts();
|
||||
?>
|
||||
<div
|
||||
class="<?php echo esc_attr(implode(' ', array_unique($classes))); ?>"
|
||||
data-page-kind="<?php echo esc_attr((string) $args['page_kind']); ?>"
|
||||
data-render-mode="<?php echo esc_attr($mode); ?>"
|
||||
data-card-style="<?php echo esc_attr($card_style); ?>"
|
||||
data-list-type="<?php echo esc_attr((string) ($render_config['list_type'] ?? 'thumb')); ?>"
|
||||
<?php if (!empty($args['ajax_enabled'])) : ?>
|
||||
data-ajax-wrap
|
||||
data-query-context="<?php echo esc_attr((string) $args['query_context']); ?>"
|
||||
@@ -372,18 +221,14 @@ if (!function_exists('aksrt_archive_render_stream')) :
|
||||
|
||||
<?php if ($has_posts) : ?>
|
||||
<?php
|
||||
if (function_exists('aksrt_render_post_list')) {
|
||||
aksrt_render_post_list($query, array_merge($render_config, ['wrapper_class' => 'content-stream__list']));
|
||||
}
|
||||
aksrt_render_post_list(array_merge($render_config, ['wrapper_class' => 'content-stream__list']), $query);
|
||||
?>
|
||||
<div class="content-stream__footer">
|
||||
<?php
|
||||
if (function_exists('aksrt_render_pagination')) {
|
||||
aksrt_render_pagination($query, [
|
||||
'query_context' => (string) $args['query_context'],
|
||||
'render_config' => $render_config,
|
||||
]);
|
||||
}
|
||||
aksrt_render_pagination($query, [
|
||||
'query_context' => (string) $args['query_context'],
|
||||
'render_config' => $render_config,
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
|
||||
@@ -1,44 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* AKSRT Flow Helper
|
||||
*
|
||||
* v4 起主题统一为 CMS / 资源站形态,不再提供 blog 形态分流。
|
||||
* 历史 helper 全部保留签名以保证兼容,但实际行为已收敛:
|
||||
*
|
||||
* aksrt_get_site_profile() 始终返回 'cms'
|
||||
* aksrt_get_term_flow() 始终返回 'inherit'(不再读取 term meta)
|
||||
* aksrt_is_resource_post() 仍按 _aksrt_is_resource meta 判定
|
||||
* aksrt_get_post_flow() 始终返回 'cms'
|
||||
* aksrt_is_cms_mode() 始终返回 true
|
||||
* aksrt_flow_layout_for() 始终返回 'grid-cms'
|
||||
* Resource-post predicate.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_get_site_profile')) {
|
||||
/**
|
||||
* @deprecated v4 起恒为 'cms',保留仅为向后兼容。
|
||||
* @return string 'cms'
|
||||
*/
|
||||
function aksrt_get_site_profile(): string {
|
||||
return 'cms';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_get_term_flow')) {
|
||||
/**
|
||||
* @deprecated v4 起恒为 'inherit',term meta 不再生效。
|
||||
* @param int $term_id
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_get_term_flow(int $term_id): string {
|
||||
unset($term_id);
|
||||
return 'inherit';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_is_resource_post')) {
|
||||
/**
|
||||
* 是否为资源帖:普通 post + _aksrt_is_resource meta。
|
||||
@@ -52,42 +20,5 @@ if (!function_exists('aksrt_is_resource_post')) {
|
||||
return false;
|
||||
}
|
||||
return (bool) get_post_meta($p->ID, '_aksrt_is_resource', true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_get_post_flow')) {
|
||||
/**
|
||||
* @deprecated v4 起恒为 'cms'。
|
||||
*
|
||||
* @param int|WP_Post|null $post
|
||||
* @return string 'cms'
|
||||
*/
|
||||
function aksrt_get_post_flow($post = null): string {
|
||||
unset($post);
|
||||
return 'cms';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_is_cms_mode')) {
|
||||
/**
|
||||
* 当前请求是否处在 CMS 形态。v4 起全站统一 CMS。
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function aksrt_is_cms_mode(): bool {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_flow_layout_for')) {
|
||||
/**
|
||||
* @deprecated v4 起恒为 'grid-cms'。
|
||||
*
|
||||
* @param string $flow
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_flow_layout_for(string $flow): string {
|
||||
unset($flow);
|
||||
return 'grid-cms';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,8 +77,6 @@ if (!function_exists('aksrt_resolve_single_post_display_settings')) :
|
||||
'related_enabled' => true,
|
||||
'related_count' => 6,
|
||||
'related_style' => 'img',
|
||||
'related_source' => 'category',
|
||||
'related_type' => 'category',
|
||||
'related_orderby' => 'views',
|
||||
'related_title' => '',
|
||||
'breadcrumbs_single_text' => true,
|
||||
@@ -130,17 +128,6 @@ if (!function_exists('aksrt_resolve_single_post_display_settings')) :
|
||||
if (!array_key_exists('authordesc', $settings) && array_key_exists('authordesc_s', $settings)) {
|
||||
$settings['authordesc'] = !empty($settings['authordesc_s']);
|
||||
}
|
||||
// related_style / related_source (legacy related_type held either).
|
||||
if (!array_key_exists('related_style', $settings) || !in_array((string) $settings['related_style'], ['img', 'list', 'text'], true)) {
|
||||
$legacy = sanitize_key((string) ($settings['related_type'] ?? ''));
|
||||
$settings['related_style'] = in_array($legacy, ['img', 'list', 'text'], true) ? $legacy : 'img';
|
||||
}
|
||||
if (!array_key_exists('related_source', $settings) || !in_array((string) $settings['related_source'], ['category', 'tag', 'random'], true)) {
|
||||
$legacy = sanitize_key((string) ($settings['related_type'] ?? ''));
|
||||
$settings['related_source'] = in_array($legacy, ['category', 'tag', 'random'], true) ? $legacy : 'category';
|
||||
}
|
||||
// Keep related_type as source alias for older callers.
|
||||
$settings['related_type'] = (string) $settings['related_source'];
|
||||
$meta = class_exists('\AKSRT\Core\PostMetaBox') ? \AKSRT\Core\PostMetaBox::get_meta($post->ID) : [];
|
||||
// show_toc new route: '' follow | '1' on | '0' off
|
||||
if (array_key_exists('show_toc', $meta) && $meta['show_toc'] !== '' && $meta['show_toc'] !== null) {
|
||||
@@ -398,7 +385,7 @@ if (!function_exists('aksrt_render_mini_post_item')) :
|
||||
/**
|
||||
* Render a compact sidebar post item for homepage widgets.
|
||||
*
|
||||
* Thin wrapper over the unified shared renderer (mode=mini).
|
||||
* Render the dedicated Zibll mini-list item.
|
||||
*
|
||||
* @param int|WP_Post|null $post
|
||||
* @param array<string, mixed> $args
|
||||
@@ -408,72 +395,15 @@ if (!function_exists('aksrt_render_mini_post_item')) :
|
||||
if (!($post instanceof WP_Post)) {
|
||||
return;
|
||||
}
|
||||
// Set up the global post so the shared renderer works
|
||||
global $wp_query;
|
||||
$original_post = isset($wp_query->post) ? $wp_query->post : null;
|
||||
$wp_query->post = $post;
|
||||
setup_postdata($post);
|
||||
if (function_exists('aksrt_render_post')) {
|
||||
$config = [
|
||||
'mode' => 'mini',
|
||||
'context' => 'sidebar',
|
||||
'show_thumb' => true,
|
||||
'show_meta' => !isset($args['show_views']) || !empty($args['show_views']),
|
||||
];
|
||||
if (!empty($args['class']) && is_string($args['class'])) {
|
||||
$config['extra_class'] = $args['class'];
|
||||
}
|
||||
echo aksrt_render_post($config); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
} else {
|
||||
// Fallback: self-contained mini rendering
|
||||
$post_id = (int) $post->ID;
|
||||
$title = get_the_title($post_id);
|
||||
$permalink = get_permalink($post_id);
|
||||
$thumb_url = has_post_thumbnail($post_id)
|
||||
? (string) get_the_post_thumbnail_url($post_id, 'medium')
|
||||
: '';
|
||||
if ($thumb_url === '' && function_exists('aksrt_get_first_content_image_url')) {
|
||||
$thumb_url = (string) aksrt_get_first_content_image_url($post_id);
|
||||
}
|
||||
$placeholder_url = get_template_directory_uri() . '/assets/img/placeholder.svg';
|
||||
$view_count = function_exists('aksrt_get_post_views') ? (int) aksrt_get_post_views($post_id) : 0;
|
||||
$show_views = !isset($args['show_views']) || !empty($args['show_views']);
|
||||
$date_text = function_exists('aksrt_time_ago')
|
||||
? aksrt_time_ago((string) $post->post_date)
|
||||
: get_the_date('Y-m-d', $post_id);
|
||||
$classes = ['posts-mini'];
|
||||
if (!empty($args['class']) && is_string($args['class'])) {
|
||||
foreach (preg_split('/\s+/', trim($args['class'])) as $extra_class) {
|
||||
$extra_class = sanitize_html_class($extra_class);
|
||||
if ($extra_class !== '') {
|
||||
$classes[] = $extra_class;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<article class="<?php echo esc_attr(implode(' ', array_unique($classes))); ?>">
|
||||
<a href="<?php echo esc_url($permalink); ?>" class="item-thumbnail" aria-label="<?php echo esc_attr($title); ?>">
|
||||
<img<?php echo aksrt_get_lazy_attr('lazy_posts_thumb', (string) ($thumb_url !== '' ? $thumb_url : $placeholder_url), 'fit-cover'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> alt="<?php echo esc_attr($title); ?>">
|
||||
</a>
|
||||
<div class="posts-mini-con">
|
||||
<h4 class="item-heading">
|
||||
<a href="<?php echo esc_url($permalink); ?>"><?php echo esc_html($title); ?></a>
|
||||
</h4>
|
||||
<div class="item-meta">
|
||||
<span class="meta-item"><?php echo esc_html($date_text); ?></span>
|
||||
<?php if ($show_views) : ?>
|
||||
<span class="meta-dot" aria-hidden="true"></span>
|
||||
<span class="meta-item">
|
||||
<i class="fas fa-eye" aria-hidden="true"></i>
|
||||
<?php echo esc_html(function_exists('aksrt_format_number') ? aksrt_format_number($view_count) : (string) $view_count); ?>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<?php
|
||||
$config = aksrt_renderer_config([]);
|
||||
$data = aksrt_renderer_collect_post_data($config);
|
||||
if ($data) {
|
||||
echo aksrt_renderer_mini($data, $config); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
// Restore original post
|
||||
if ($original_post instanceof WP_Post) {
|
||||
$wp_query->post = $original_post;
|
||||
setup_postdata($original_post);
|
||||
|
||||
@@ -130,19 +130,6 @@ if (!function_exists('aksrt_homepage_get_tab_posts_per_page')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_homepage_get_default_view_mode')) {
|
||||
/**
|
||||
* Default homepage view mode.
|
||||
*/
|
||||
function aksrt_homepage_get_default_view_mode(): string {
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
return \AKSRT\Settings\Settings::homepage_default_view();
|
||||
}
|
||||
|
||||
return 'list';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_homepage_sticky_tabs_enabled')) {
|
||||
/**
|
||||
* Whether homepage tabs should stick below the primary nav.
|
||||
@@ -373,21 +360,6 @@ if (!function_exists('aksrt_homepage_render_sortbar')) {
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
$view_mode = 'list';
|
||||
if (function_exists('aksrt_resolve_post_list_render_config')) {
|
||||
$home_view_cfg = aksrt_resolve_post_list_render_config(['context' => 'home']);
|
||||
$view_mode = (($home_view_cfg['mode'] ?? 'list') === 'card') ? 'card' : 'list';
|
||||
}
|
||||
?>
|
||||
<div class="aksrt-homepage__view-toggle" data-aksrt-view-toggle>
|
||||
<button type="button" class="aksrt-homepage__view-btn<?php echo $view_mode === 'list' ? ' is-active' : ''; ?>" data-view-mode="list" aria-label="<?php esc_attr_e('列表视图', 'aksrt'); ?>">
|
||||
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M1 3h14v2H1V3zm0 4h14v2H1V7zm0 4h14v2H1v-2z"/></svg>
|
||||
</button>
|
||||
<button type="button" class="aksrt-homepage__view-btn<?php echo $view_mode === 'card' ? ' is-active' : ''; ?>" data-view-mode="card" aria-label="<?php esc_attr_e('卡片视图', 'aksrt'); ?>">
|
||||
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M1 1h4v4H1V1zm5 0h4v4H6V1zm5 0h4v4h-4V1zM1 6h4v4H1V6zm5 0h4v4H6V6zm5 0h4v4h-4V6zM1 11h4v4H1v-4zm5 0h4v4H6v-4zm5 0h4v4h-4v-4z"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
@@ -127,8 +127,8 @@ if (!function_exists('aksrt_get_win_runtime_config')) :
|
||||
'signup_url' => $signup,
|
||||
'ajax_url' => admin_url('admin-ajax.php'),
|
||||
'ajaxpager' => '1',
|
||||
'ajax_trigger' => (string) ($list_style['ajax_trigger_text'] ?? __('加载更多', 'aksrt')),
|
||||
'ajax_nomore' => (string) ($list_style['ajax_nomore_text'] ?? __('没有更多了', 'aksrt')),
|
||||
'ajax_trigger' => (string) ($list_style['ajax_trigger'] ?? '<i class="fa fa-angle-right"></i>加载更多'),
|
||||
'ajax_nomore' => (string) ($list_style['ajax_nomore'] ?? __('没有更多内容了', 'aksrt')),
|
||||
'qj_loading' => __('加载中...', 'aksrt'),
|
||||
'is_mobile' => $is_mobile ? '1' : '',
|
||||
'is_logged_in' => is_user_logged_in() ? '1' : '',
|
||||
|
||||
@@ -481,15 +481,13 @@ if (!function_exists('aksrt_render_related_graphic_card')) :
|
||||
* Minimal Zibll style-3 related thumb card.
|
||||
*/
|
||||
function aksrt_render_related_graphic_card(WP_Post $post): string {
|
||||
$title = get_the_title($post);
|
||||
$subtitle = class_exists('\AKSRT\Core\PostMetaBox')
|
||||
? (string) \AKSRT\Core\PostMetaBox::get_meta_value($post->ID, 'subtitle', '')
|
||||
: '';
|
||||
$title = get_the_title($post) . $subtitle;
|
||||
$url = get_permalink($post);
|
||||
$thumb = get_the_post_thumbnail_url($post, 'medium_large');
|
||||
if (!$thumb) {
|
||||
$thumb = get_theme_file_uri('assets/img/thumbnail-lg.svg');
|
||||
if (!file_exists(get_theme_file_path('assets/img/thumbnail-lg.svg'))) {
|
||||
$thumb = includes_url('images/media/default.png');
|
||||
}
|
||||
}
|
||||
$media = aksrt_renderer_resolve_images($post->ID, aksrt_renderer_config(['type' => 'card']));
|
||||
$thumb = (string) $media['primary'];
|
||||
$time = human_time_diff((int) get_the_time('U', $post), (int) current_time('timestamp'));
|
||||
$views = function_exists('aksrt_get_post_views') ? (int) aksrt_get_post_views($post->ID) : 0;
|
||||
$views_label = function_exists('aksrt_format_number') ? aksrt_format_number($views) : number_format_i18n($views);
|
||||
|
||||
@@ -568,12 +568,8 @@ if (!function_exists('aksrt_single_related_query_args')) :
|
||||
*/
|
||||
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_source'] ?? ($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)) {
|
||||
if (!in_array($orderby, ['modified', 'date', 'views', 'like', 'comment_count', 'favorite', 'rand'], true)) {
|
||||
$orderby = 'views';
|
||||
}
|
||||
|
||||
@@ -587,39 +583,22 @@ if (!function_exists('aksrt_single_related_query_args')) :
|
||||
'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.
|
||||
$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),
|
||||
];
|
||||
}
|
||||
$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 (count($tax_query) > 1) {
|
||||
@@ -636,6 +615,17 @@ if (!function_exists('aksrt_single_related_query_args')) :
|
||||
case 'modified':
|
||||
$args['orderby'] = 'modified';
|
||||
break;
|
||||
case 'like':
|
||||
$args['meta_key'] = '_aksrt_like_count';
|
||||
$args['orderby'] = ['meta_value_num' => 'DESC', 'date' => 'DESC'];
|
||||
break;
|
||||
case 'favorite':
|
||||
$args['meta_key'] = '_aksrt_favorite_count';
|
||||
$args['orderby'] = ['meta_value_num' => 'DESC', 'date' => 'DESC'];
|
||||
break;
|
||||
case 'comment_count':
|
||||
$args['orderby'] = 'comment_count';
|
||||
break;
|
||||
case 'views':
|
||||
$args['meta_query'] = [
|
||||
'relation' => 'OR',
|
||||
@@ -651,10 +641,8 @@ if (!function_exists('aksrt_single_related_query_args')) :
|
||||
];
|
||||
$args['orderby'] = ['views_value' => 'DESC', 'date' => 'DESC'];
|
||||
break;
|
||||
case 'relevance':
|
||||
default:
|
||||
// Prefer date when no search relevance context.
|
||||
$args['orderby'] = 'date';
|
||||
$args['orderby'] = 'modified';
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -695,74 +683,54 @@ if (!function_exists('aksrt_single_render_related')) :
|
||||
];
|
||||
|
||||
$query = new WP_Query($args);
|
||||
if (!$query->have_posts()) {
|
||||
wp_reset_postdata();
|
||||
$empty_wrap = 'theme-box relates' . ($style === 'img' ? ' relates-thumb' : '');
|
||||
?>
|
||||
<div class="<?php echo esc_attr($empty_wrap); ?>">
|
||||
<div class="box-body notop">
|
||||
<div class="title-theme"><?php echo esc_html($title); ?></div>
|
||||
</div>
|
||||
<div class="zib-widget">
|
||||
<?php echo function_exists('aksrt_get_null') ? aksrt_get_null(__('暂无相关文章', 'aksrt'), 40, 'null.svg', 'related-null', 220) : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
return;
|
||||
}
|
||||
|
||||
$wrap_class = 'theme-box relates' . ($style === 'img' ? ' relates-thumb' : '');
|
||||
$posts_html = '';
|
||||
$mini_cfg = aksrt_renderer_config([
|
||||
'type' => 'list',
|
||||
'show_number' => false,
|
||||
]);
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
$post = get_post();
|
||||
if (!($post instanceof WP_Post)) {
|
||||
continue;
|
||||
}
|
||||
if ($style === 'list') {
|
||||
$data = aksrt_renderer_collect_post_data($mini_cfg);
|
||||
if ($data) {
|
||||
$posts_html .= aksrt_renderer_mini($data, $mini_cfg);
|
||||
}
|
||||
} elseif ($style === 'img' && function_exists('aksrt_render_related_graphic_card')) {
|
||||
$posts_html .= aksrt_render_related_graphic_card($post);
|
||||
} else {
|
||||
$subtitle = class_exists('\AKSRT\Core\PostMetaBox')
|
||||
? (string) \AKSRT\Core\PostMetaBox::get_meta_value($post->ID, 'subtitle', '')
|
||||
: '';
|
||||
$posts_html .= '<li><a class="icon-circle" href="' . esc_url(get_permalink($post)) . '">' . esc_html(get_the_title($post) . $subtitle) . '</a></li>';
|
||||
}
|
||||
}
|
||||
wp_reset_postdata();
|
||||
if ($posts_html === '') {
|
||||
$posts_html = '<li>' . esc_html__('暂无相关文章', 'aksrt') . '</li>';
|
||||
}
|
||||
?>
|
||||
<div class="<?php echo esc_attr($wrap_class); ?>">
|
||||
<div class="box-body notop">
|
||||
<div class="title-theme"><?php echo esc_html($title); ?></div>
|
||||
</div>
|
||||
<div class="zib-widget">
|
||||
<?php if ($style === 'list' && function_exists('aksrt_render_post_list')) : ?>
|
||||
<?php
|
||||
// New route: single query only.
|
||||
aksrt_render_post_list($query, [
|
||||
'context' => 'related',
|
||||
'mode' => 'mini',
|
||||
'show_thumb' => true,
|
||||
'show_meta' => true,
|
||||
'show_number' => false,
|
||||
]);
|
||||
?>
|
||||
<?php if ($style === 'img') : ?>
|
||||
<div class="swiper-container swiper-scroll">
|
||||
<div class="swiper-wrapper"><?php echo $posts_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
|
||||
<div class="swiper-button-prev"></div>
|
||||
<div class="swiper-button-next"></div>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<?php
|
||||
$posts_html = '';
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
$p = get_post();
|
||||
if (!($p instanceof WP_Post)) {
|
||||
continue;
|
||||
}
|
||||
if ($style === 'img' && function_exists('aksrt_render_related_graphic_card')) {
|
||||
$posts_html .= aksrt_render_related_graphic_card($p);
|
||||
} else {
|
||||
$posts_html .= '<li><a class="icon-circle" href="' . esc_url(get_permalink($p)) . '">' . esc_html(get_the_title($p)) . '</a></li>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
<?php if ($style === 'img') : ?>
|
||||
<div class="swiper-container swiper-scroll">
|
||||
<div class="swiper-wrapper">
|
||||
<?php echo $posts_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</div>
|
||||
<div class="swiper-button-prev"></div>
|
||||
<div class="swiper-button-next"></div>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<ul class="no-thumb">
|
||||
<?php echo $posts_html !== '' ? $posts_html : '<li>' . esc_html__('暂无相关文章', 'aksrt') . '</li>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
<ul class="no-thumb"><?php echo $posts_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
wp_reset_postdata();
|
||||
}
|
||||
endif;
|
||||
|
||||
|
||||
@@ -206,12 +206,7 @@ if (!function_exists('aksrt_homepage_get_latest_panel_contract')) {
|
||||
|
||||
unset($query_vars['paged'], $query_vars['page']);
|
||||
|
||||
$render_config = function_exists('aksrt_resolve_post_list_render_config')
|
||||
? aksrt_resolve_post_list_render_config(['context' => 'home'])
|
||||
: [
|
||||
'mode' => 'list',
|
||||
'context' => 'home',
|
||||
];
|
||||
$render_config = aksrt_resolve_post_list_render_config(['context' => 'home']);
|
||||
$render_config['skip_wrapper'] = true;
|
||||
|
||||
return [
|
||||
@@ -364,57 +359,17 @@ if (!function_exists('aksrt_get_post_gallery_images')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_homepage_render_post_card')) {
|
||||
/**
|
||||
* Render a homepage post card inline.
|
||||
*/
|
||||
function aksrt_homepage_render_post_card(): void {
|
||||
if (!function_exists('aksrt_render_post')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$config = function_exists('aksrt_resolve_post_list_render_config')
|
||||
? aksrt_resolve_post_list_render_config(['context' => 'home'])
|
||||
: [
|
||||
'mode' => 'list',
|
||||
'context' => 'home',
|
||||
];
|
||||
|
||||
echo aksrt_render_post($config); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_homepage_render_posts_grid')) {
|
||||
/**
|
||||
* Render a list block for the fixed homepage.
|
||||
*/
|
||||
function aksrt_homepage_render_posts_grid(?WP_Query $query = null, bool $with_pagination = false): void {
|
||||
$query = $query instanceof WP_Query ? $query : aksrt_homepage_get_latest_query();
|
||||
$config = function_exists('aksrt_resolve_post_list_render_config')
|
||||
? aksrt_resolve_post_list_render_config(['context' => 'home'])
|
||||
: [
|
||||
'mode' => 'list',
|
||||
'context' => 'home',
|
||||
];
|
||||
$config = aksrt_resolve_post_list_render_config(['context' => 'home']);
|
||||
$config['skip_wrapper'] = true;
|
||||
$view = (($config['mode'] ?? 'list') === 'card') ? 'card' : 'list';
|
||||
|
||||
if (function_exists('aksrt_render_post_list')) {
|
||||
// Panel already provides posts-row.ajaxpager; avoid nested wrapper.
|
||||
aksrt_render_post_list($query, $config, true);
|
||||
} else {
|
||||
if (!$query->have_posts()) {
|
||||
echo '<div class="no-results"><p>' . esc_html__('暂无文章', 'aksrt') . '</p></div>';
|
||||
} else {
|
||||
echo '<div class="posts-row aksrt-homepage__posts" data-view="' . esc_attr($view) . '">';
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
aksrt_homepage_render_post_card();
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
wp_reset_postdata();
|
||||
}
|
||||
// Panel already provides posts-row.ajaxpager; avoid nested wrapper.
|
||||
aksrt_render_post_list($config, $query, true);
|
||||
|
||||
if ($with_pagination) {
|
||||
aksrt_homepage_render_pagination($query);
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Shared post renderer helpers for archive, widget, and related lists.
|
||||
*
|
||||
* Centralizes card/list/mini rendering to avoid duplicating DOM contracts
|
||||
* across category.php, search.php, widgets, and home modules.
|
||||
* Zibll 9.0 article-list configuration and image resolution.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -11,355 +8,249 @@
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_renderer_defaults')) {
|
||||
/**
|
||||
* Base renderer config defaults.
|
||||
*
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
/** @return array<string,mixed> */
|
||||
function aksrt_renderer_defaults(): array {
|
||||
return [
|
||||
'context' => 'archive',
|
||||
'mode' => 'list',
|
||||
'columns' => 1,
|
||||
'style' => 'default',
|
||||
'card_style' => 'standard',
|
||||
'heading_bold' => true,
|
||||
'show_excerpt' => true,
|
||||
'excerpt_words' => 36,
|
||||
'show_meta' => true,
|
||||
'show_author' => true,
|
||||
'show_date' => true,
|
||||
'show_views' => true,
|
||||
'show_comments' => true,
|
||||
'show_likes' => false,
|
||||
'show_badges' => true,
|
||||
'show_tags' => true,
|
||||
'tag_limit' => 3,
|
||||
'category_limit' => 1,
|
||||
'show_thumb' => true,
|
||||
'thumb_ratio' => '4:3',
|
||||
'thumb_fit' => 'cover',
|
||||
'thumb_if_has' => false,
|
||||
'target_blank' => false,
|
||||
'title_html' => '',
|
||||
'excerpt_html' => '',
|
||||
'badge_show' => true,
|
||||
'show_resource_badge' => true,
|
||||
'multi_thumb_enabled' => true,
|
||||
'multi_thumb_limit' => 4,
|
||||
'multi_thumb_min' => 2,
|
||||
'list_show_type' => 'separate',
|
||||
'list_img_position' => 'left',
|
||||
'number_offset' => 0,
|
||||
'show_number' => false,
|
||||
'extra_class' => '',
|
||||
'highlight_query' => '',
|
||||
'type' => 'auto',
|
||||
'no_author' => false,
|
||||
'no_margin' => false,
|
||||
'is_mult_thumb' => false,
|
||||
'is_no_thumb' => false,
|
||||
'is_card' => false,
|
||||
'is_category' => is_category(),
|
||||
'is_search' => is_search(),
|
||||
'is_home' => is_home() || is_front_page(),
|
||||
'is_author' => is_author(),
|
||||
'is_tag' => is_tag(),
|
||||
'highlight_query' => '',
|
||||
'wrapper_class' => '',
|
||||
'skip_wrapper' => false,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_config')) {
|
||||
/**
|
||||
* Merge renderer config with context-aware defaults.
|
||||
* Resolve the one canonical Zibll list/card decision matrix.
|
||||
*
|
||||
* @param array<string,mixed> $config User config.
|
||||
* @param array<string,mixed> $args Caller arguments.
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
function aksrt_renderer_config(array $config = []): array {
|
||||
$cfg = wp_parse_args($config, aksrt_renderer_defaults());
|
||||
function aksrt_renderer_config(array $args = []): array {
|
||||
$args = wp_parse_args($args, aksrt_renderer_defaults());
|
||||
$list = class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::get_post_list_style_settings()
|
||||
: [];
|
||||
$thumb = class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::get_post_thumb_settings()
|
||||
: [];
|
||||
|
||||
$cfg['mode'] = in_array($cfg['mode'], ['list', 'card', 'mini', 'grid-cms'], true)
|
||||
? $cfg['mode']
|
||||
: 'list';
|
||||
|
||||
$cfg['columns'] = max(1, min(6, (int) $cfg['columns']));
|
||||
$cfg['excerpt_words'] = max(0, (int) $cfg['excerpt_words']);
|
||||
$cfg['tag_limit'] = max(0, (int) $cfg['tag_limit']);
|
||||
$cfg['category_limit'] = max(0, (int) $cfg['category_limit']);
|
||||
$cfg['multi_thumb_limit'] = max(1, min(6, (int) $cfg['multi_thumb_limit']));
|
||||
$cfg['multi_thumb_min'] = max(1, min(6, (int) $cfg['multi_thumb_min']));
|
||||
|
||||
if ($cfg['mode'] === 'mini') {
|
||||
$cfg['show_excerpt'] = false;
|
||||
$cfg['show_badges'] = false;
|
||||
$cfg['show_tags'] = false;
|
||||
$cfg['show_author'] = false;
|
||||
$cfg['show_comments'] = false;
|
||||
$list_type = sanitize_key((string) ($list['list_type'] ?? 'thumb'));
|
||||
$forced_type = sanitize_key((string) $args['type']);
|
||||
$is_forced = in_array($forced_type, ['list', 'card'], true);
|
||||
$is_card = $forced_type === 'card' || (!$is_forced && !empty($args['is_card']));
|
||||
if (!$is_forced && !$is_card && $list_type === 'card') {
|
||||
$is_card = true;
|
||||
}
|
||||
if (!$is_forced && !$is_card) {
|
||||
$is_card = (!empty($args['is_tag']) && !empty($list['list_card_tag']))
|
||||
|| (!empty($args['is_home']) && !empty($list['list_card_home']))
|
||||
|| (!empty($args['is_author']) && !empty($list['list_card_author']));
|
||||
}
|
||||
if (!$is_forced && !$is_card) {
|
||||
$term_id = (int) get_queried_object_id();
|
||||
$is_card = $term_id > 0 && in_array($term_id, (array) ($list['list_card_cat'] ?? []), true);
|
||||
}
|
||||
|
||||
if (in_array((string) $cfg['style'], ['default', 'null'], true)) {
|
||||
$cfg['style'] = '';
|
||||
$list_option = (array) ($list['list_list_option'] ?? []);
|
||||
$card_option = (array) ($list['list_card_option'] ?? []);
|
||||
$style = sanitize_key((string) (($is_card ? $card_option : $list_option)['style'] ?? 'null'));
|
||||
if (!in_array($style, ['style2', 'style3'], true)) {
|
||||
$style = '';
|
||||
}
|
||||
$cfg['list_img_position'] = in_array(sanitize_key((string) ($cfg['list_img_position'] ?? 'left')), ['left', 'right'], true)
|
||||
? sanitize_key((string) ($cfg['list_img_position'] ?? 'left'))
|
||||
: 'left';
|
||||
$cfg['list_show_type'] = in_array(sanitize_key((string) ($cfg['list_show_type'] ?? 'separate')), ['separate', 'no_margin'], true)
|
||||
? sanitize_key((string) ($cfg['list_show_type'] ?? 'separate'))
|
||||
: 'separate';
|
||||
|
||||
return $cfg;
|
||||
}
|
||||
}
|
||||
$args['mode'] = $is_card ? 'card' : 'list';
|
||||
$args['list_type'] = $list_type;
|
||||
$args['style'] = $style;
|
||||
$args['img_position'] = sanitize_key((string) ($list_option['img_position'] ?? 'left')) === 'right' ? 'right' : 'left';
|
||||
$args['list_scale'] = max(50, min(200, (int) ($list_option['scale'] ?? 70)));
|
||||
$args['card_scale'] = max(20, min(200, (int) ($card_option['scale'] ?? 70)));
|
||||
$args['no_margin'] = !empty($args['no_margin']) || (($list['list_show_type'] ?? 'separate') === 'no_margin');
|
||||
$args['no_author'] = !empty($args['no_author']) || !empty($args['is_author']);
|
||||
$args['target_blank'] = !empty($list['target_blank']);
|
||||
$args['heading_bold'] = !empty($list['item_heading_bold']);
|
||||
$args['show_author'] = !empty($list['post_list_author']);
|
||||
$args['show_time'] = !empty($list['post_list_time']);
|
||||
$args['time_source'] = (string) ($list['post_time_source'] ?? 'modified');
|
||||
$args['list_orderby'] = (string) ($list['list_orderby'] ?? 'modified');
|
||||
$args['mobile_meta'] = (string) ($list['list_meta_show'] ?? 'like');
|
||||
$args['badge_types'] = (array) ($list['list_badge_show'] ?? ['pay', 'cat', 'tag']);
|
||||
$args['mult_thumb_cat'] = (array) ($list['mult_thumb_cat'] ?? []);
|
||||
$args['thumb'] = $thumb;
|
||||
$args['allow_conditional_layout'] = aksrt_is_show_sidebar() || wp_is_mobile();
|
||||
$page = class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::get_post_page_settings()
|
||||
: [];
|
||||
$comments = class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::get_comment_display_settings()
|
||||
: [];
|
||||
$args['show_like'] = !array_key_exists('like_enabled', $page) || !empty($page['like_enabled']);
|
||||
$args['close_comments'] = !empty($comments['close_comments']);
|
||||
|
||||
if (!function_exists('aksrt_renderer_sanitize_inline_html')) {
|
||||
/**
|
||||
* Sanitize small inline HTML snippets used by render config overrides.
|
||||
*
|
||||
* @param string $html Raw HTML.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_sanitize_inline_html(string $html): string {
|
||||
return wp_kses($html, [
|
||||
'span' => ['class' => true, 'aria-hidden' => true],
|
||||
'em' => ['class' => true],
|
||||
'strong' => ['class' => true],
|
||||
'i' => ['class' => true, 'aria-hidden' => true],
|
||||
'small'=> ['class' => true],
|
||||
]);
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_highlight_text')) {
|
||||
/**
|
||||
* Highlight plain text query matches using a safe span wrapper.
|
||||
*
|
||||
* @param string $text Plain text.
|
||||
* @param string $query Highlight query.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_highlight_text(string $text, string $query): string {
|
||||
$text = wp_strip_all_tags($text);
|
||||
$query = trim($query);
|
||||
|
||||
if ($query === '' || $text === '') {
|
||||
return esc_html($text);
|
||||
}
|
||||
|
||||
$words = preg_split('/\s+/u', $query) ?: [];
|
||||
$words = array_values(array_unique(array_filter(array_map('trim', $words), static function ($word) {
|
||||
return $word !== '' && mb_strlen($word) >= 2;
|
||||
})));
|
||||
|
||||
if (empty($words)) {
|
||||
$words = array_values(array_unique(array_filter(preg_split('/\s+/u', $query) ?: [])));
|
||||
if (!$words) {
|
||||
return esc_html($text);
|
||||
}
|
||||
|
||||
$pattern = '/' . implode('|', array_map(static function ($word) {
|
||||
return preg_quote($word, '/');
|
||||
}, $words)) . '/iu';
|
||||
|
||||
$escaped = esc_html($text);
|
||||
return (string) preg_replace($pattern, '<span class="focus-color">$0</span>', $escaped);
|
||||
$pattern = '/' . implode('|', array_map(static fn(string $word): string => preg_quote($word, '/'), $words)) . '/iu';
|
||||
return (string) preg_replace($pattern, '<span class="focus-color">$0</span>', esc_html($text));
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_title_markup')) {
|
||||
/**
|
||||
* Resolve title markup, supporting highlighted search terms.
|
||||
*
|
||||
* @param array<string,mixed> $data Collected post data.
|
||||
* @param array<string,mixed> $cfg Renderer config.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_title_markup(array $data, array $cfg): string {
|
||||
if (!empty($cfg['title_html'])) {
|
||||
return aksrt_renderer_sanitize_inline_html((string) $cfg['title_html']);
|
||||
$title = aksrt_renderer_highlight_text((string) $data['title'], (string) ($cfg['highlight_query'] ?? ''));
|
||||
if ((string) ($data['subtitle'] ?? '') !== '') {
|
||||
$title .= '<span class="focus-color"> ' . esc_html((string) $data['subtitle']) . '</span>';
|
||||
}
|
||||
|
||||
$title = aksrt_renderer_highlight_text((string) $data['title'], (string) $cfg['highlight_query']);
|
||||
$subtitle = trim((string) ($data['subtitle'] ?? ''));
|
||||
if ($subtitle !== '') {
|
||||
$title .= '<span class="focus-color"> ' . esc_html($subtitle) . '</span>';
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_excerpt_markup')) {
|
||||
/**
|
||||
* Resolve excerpt markup, supporting highlighted search terms.
|
||||
*
|
||||
* @param array<string,mixed> $data Collected post data.
|
||||
* @param array<string,mixed> $cfg Renderer config.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_excerpt_markup(array $data, array $cfg): string {
|
||||
if (!empty($cfg['excerpt_html'])) {
|
||||
return aksrt_renderer_sanitize_inline_html((string) $cfg['excerpt_html']);
|
||||
}
|
||||
|
||||
return aksrt_renderer_highlight_text((string) $data['excerpt'], (string) $cfg['highlight_query']);
|
||||
return aksrt_renderer_highlight_text((string) $data['excerpt'], (string) ($cfg['highlight_query'] ?? ''));
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_curated_images')) {
|
||||
/**
|
||||
* Resolve curated cover images from post meta.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @param int $limit Maximum items.
|
||||
* @return string[]
|
||||
*/
|
||||
function aksrt_renderer_curated_images(int $post_id, int $limit = 6): array {
|
||||
/** @return string[] */
|
||||
function aksrt_renderer_curated_images(int $post_id, string $size, int $limit = 8): array {
|
||||
$raw = class_exists('\AKSRT\Core\PostMetaBox')
|
||||
? (string) \AKSRT\Core\PostMetaBox::get_meta_value($post_id, 'featured_slide', '')
|
||||
: '';
|
||||
$images = [];
|
||||
$limit = max(1, min(8, $limit));
|
||||
|
||||
if (!class_exists('\AKSRT\Core\PostMetaBox')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$cover_images = (string) \AKSRT\Core\PostMetaBox::get_meta_value($post_id, 'cover_images', '');
|
||||
if ($cover_images === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$cover_ids = array_filter(array_map('absint', preg_split('/[\s,]+/', $cover_images) ?: []));
|
||||
foreach ($cover_ids as $attachment_id) {
|
||||
$url = (string) wp_get_attachment_image_url($attachment_id, 'medium_large');
|
||||
if ($url !== '') {
|
||||
$images[] = esc_url_raw($url);
|
||||
foreach (array_filter(preg_split('/[\s,]+/', $raw) ?: []) as $token) {
|
||||
$image = aksrt_renderer_sized_image((string) $token, $size);
|
||||
if ($image !== '') {
|
||||
$images[] = $image;
|
||||
}
|
||||
}
|
||||
|
||||
return array_slice(array_values(array_unique($images)), 0, $limit);
|
||||
return array_slice($images, 0, $limit);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_attachment_images')) {
|
||||
/**
|
||||
* Resolve gallery/content images for list cards.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @param int $limit Maximum items.
|
||||
* @return string[]
|
||||
*/
|
||||
function aksrt_renderer_attachment_images(int $post_id, int $limit = 6): array {
|
||||
$images = [];
|
||||
$limit = max(1, min(8, $limit));
|
||||
|
||||
if (function_exists('aksrt_get_post_gallery_images')) {
|
||||
$images = aksrt_get_post_gallery_images($post_id, $limit);
|
||||
}
|
||||
|
||||
if (function_exists('aksrt_get_first_content_image_url')) {
|
||||
$first_content_image = (string) aksrt_get_first_content_image_url($post_id);
|
||||
if ($first_content_image !== '') {
|
||||
$images[] = esc_url_raw($first_content_image);
|
||||
}
|
||||
}
|
||||
|
||||
return array_slice(array_values(array_unique(array_filter($images))), 0, $limit);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_random_fallback_image')) {
|
||||
/**
|
||||
* Pick a deterministic fallback image when "random cover" is enabled.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_random_fallback_image(int $post_id): string {
|
||||
$candidates = [
|
||||
get_template_directory_uri() . '/assets/img/person_background.png',
|
||||
get_template_directory_uri() . '/assets/img/placeholder.svg',
|
||||
];
|
||||
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
$thumb = \AKSRT\Settings\Settings::get_post_thumb_settings();
|
||||
$spare = $thumb['spare_images'] ?? [];
|
||||
if (is_array($spare) && !empty($spare)) {
|
||||
foreach ($spare as $url) {
|
||||
if (is_string($url) && $url !== '') {
|
||||
array_unshift($candidates, $url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$candidates = array_values(array_unique(array_filter(array_map('esc_url_raw', $candidates))));
|
||||
if (empty($candidates)) {
|
||||
if (!function_exists('aksrt_renderer_sized_image')) {
|
||||
function aksrt_renderer_sized_image(string $image, string $size): string {
|
||||
$image = trim($image);
|
||||
if ($image === '') {
|
||||
return '';
|
||||
}
|
||||
$attachment_id = ctype_digit($image) ? (int) $image : 0;
|
||||
if ($attachment_id === 0) {
|
||||
$lookup_url = (string) preg_replace('/\?.*$/', '', $image);
|
||||
$attachment_id = attachment_url_to_postid($lookup_url);
|
||||
if ($attachment_id === 0) {
|
||||
$full_url = (string) preg_replace('/-\d+x\d+(?=\.[^.]+$)/', '', $lookup_url);
|
||||
$attachment_id = attachment_url_to_postid($full_url);
|
||||
}
|
||||
}
|
||||
if ($attachment_id > 0) {
|
||||
$sized = wp_get_attachment_image_url($attachment_id, $size);
|
||||
if (is_string($sized) && $sized !== '') {
|
||||
return esc_url_raw($sized);
|
||||
}
|
||||
}
|
||||
return esc_url_raw($image);
|
||||
}
|
||||
}
|
||||
|
||||
$index = $post_id % count($candidates);
|
||||
return $candidates[$index] ?? $candidates[0];
|
||||
if (!function_exists('aksrt_renderer_content_images')) {
|
||||
/** @return string[] */
|
||||
function aksrt_renderer_content_images(int $post_id, string $size): array {
|
||||
$content = strip_shortcodes((string) get_post_field('post_content', $post_id, 'raw'));
|
||||
if ($content === '' || !preg_match_all('/<img.*?(?: |\t|\r|\n)?src=[\'\"]?(.+?)[\'\"]?(?:(?: |\t|\r|\n)+.*?)?>/sim', $content, $matches)) {
|
||||
return [];
|
||||
}
|
||||
$images = [];
|
||||
foreach ((array) ($matches[1] ?? []) as $image) {
|
||||
$sized = aksrt_renderer_sized_image((string) $image, $size);
|
||||
if ($sized !== '') {
|
||||
$images[] = $sized;
|
||||
}
|
||||
}
|
||||
return $images;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_category_image')) {
|
||||
function aksrt_renderer_category_image(int $post_id, string $size): string {
|
||||
foreach ((array) get_the_category($post_id) as $category) {
|
||||
$attachment_id = (int) get_term_meta((int) $category->term_id, 'aksrt_category_cover_id', true);
|
||||
if ($attachment_id > 0) {
|
||||
return aksrt_renderer_sized_image((string) $attachment_id, $size);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_spare_image')) {
|
||||
function aksrt_renderer_spare_image(array $thumb): string {
|
||||
$images = array_values(array_filter((array) ($thumb['spare_thumbnail'] ?? [])));
|
||||
return $images ? (string) $images[array_rand($images)] : '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_resolve_images')) {
|
||||
/**
|
||||
* Resolve primary + gallery images for a post based on card settings.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @param array<string,mixed> $cfg Renderer config.
|
||||
* @return array{primary:string,gallery:string[],has_thumb:bool,has_real:bool}
|
||||
*/
|
||||
/** @return array{primary:string,gallery:string[],slides:string[],has_real:bool,is_slide:bool,video_url:string} */
|
||||
function aksrt_renderer_resolve_images(int $post_id, array $cfg): array {
|
||||
$thumb_url = get_the_post_thumbnail_url($post_id, 'medium_large');
|
||||
$curated_images = !empty($cfg['thumb_if_has']) || !empty($cfg['multi_thumb_enabled'])
|
||||
? aksrt_renderer_curated_images($post_id, max(4, (int) $cfg['multi_thumb_limit']))
|
||||
: [];
|
||||
$content_images = !empty($cfg['multi_thumb_enabled'])
|
||||
? aksrt_renderer_attachment_images($post_id, max(4, (int) $cfg['multi_thumb_limit']))
|
||||
: [];
|
||||
$thumb = (array) ($cfg['thumb'] ?? []);
|
||||
$size = (string) ($thumb['thumb_postfirstimg_size'] ?? 'medium');
|
||||
$slides = aksrt_renderer_curated_images($post_id, $size);
|
||||
$gallery = aksrt_renderer_content_images($post_id, $size);
|
||||
$video_url = class_exists('\AKSRT\Core\PostMetaBox')
|
||||
? esc_url_raw((string) \AKSRT\Core\PostMetaBox::get_meta_value($post_id, 'featured_video', ''))
|
||||
: '';
|
||||
|
||||
$gallery = [];
|
||||
if (!empty($curated_images)) {
|
||||
$gallery = array_merge($gallery, $curated_images);
|
||||
$thumbnail_id = (int) get_post_thumbnail_id($post_id);
|
||||
$primary = $thumbnail_id > 0 ? aksrt_renderer_sized_image((string) $thumbnail_id, $size) : '';
|
||||
if ($primary === '') {
|
||||
$primary = class_exists('\AKSRT\Core\PostMetaBox')
|
||||
? esc_url_raw((string) \AKSRT\Core\PostMetaBox::get_meta_value($post_id, 'thumbnail_url', ''))
|
||||
: '';
|
||||
}
|
||||
if (!empty($content_images)) {
|
||||
$gallery = array_merge($gallery, $content_images);
|
||||
if ($primary === '' && !empty($thumb['thumb_postfirstimg_s']) && !empty($gallery[0])) {
|
||||
$primary = (string) $gallery[0];
|
||||
}
|
||||
if ($primary === '' && !empty($thumb['thumb_catimg_s'])) {
|
||||
$primary = aksrt_renderer_category_image($post_id, $size);
|
||||
}
|
||||
$gallery = array_values(array_unique(array_filter($gallery)));
|
||||
|
||||
$primary = is_string($thumb_url) && $thumb_url !== '' ? esc_url_raw($thumb_url) : '';
|
||||
$has_real = $primary !== '';
|
||||
|
||||
if ($primary === '' && !empty($curated_images[0])) {
|
||||
$primary = $curated_images[0];
|
||||
$has_real = true;
|
||||
if ($primary === '') {
|
||||
$primary = aksrt_renderer_spare_image($thumb);
|
||||
}
|
||||
if ($primary === '' && !empty($content_images[0])) {
|
||||
$primary = $content_images[0];
|
||||
$has_real = true;
|
||||
}
|
||||
|
||||
$thumb_settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_post_thumb_settings() : [];
|
||||
$fallback = sanitize_key((string) ($thumb_settings['fallback'] ?? 'placeholder'));
|
||||
if ($primary === '' && empty($cfg['thumb_if_has'])) {
|
||||
if ($fallback === 'random') {
|
||||
$primary = aksrt_renderer_random_fallback_image($post_id);
|
||||
} elseif ($fallback === 'placeholder') {
|
||||
$primary = aksrt_get_lazy_thumb();
|
||||
}
|
||||
if ($primary === '') {
|
||||
$primary = (string) aksrt_get_lazy_thumb();
|
||||
}
|
||||
|
||||
return [
|
||||
'primary' => $primary,
|
||||
'gallery' => $gallery,
|
||||
'has_thumb' => $primary !== '',
|
||||
'has_real' => $has_real,
|
||||
'primary' => esc_url_raw($primary),
|
||||
'gallery' => $gallery,
|
||||
'slides' => $slides,
|
||||
'has_real' => $has_real,
|
||||
'is_slide' => !empty($thumb['list_thumb_slides_s']) && count($slides) > 0,
|
||||
'video_url' => $video_url,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_thumb_ratio_value')) {
|
||||
/**
|
||||
* Convert ratio tokens like 4:3 to CSS aspect ratio values.
|
||||
*
|
||||
* @param string $ratio Ratio token.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_thumb_ratio_value(string $ratio): string {
|
||||
$ratio = trim($ratio);
|
||||
if (preg_match('/^(\d+)\s*:\s*(\d+)$/', $ratio, $matches)) {
|
||||
$w = max(1, (int) $matches[1]);
|
||||
$h = max(1, (int) $matches[2]);
|
||||
return $w . ' / ' . $h;
|
||||
}
|
||||
|
||||
return '4 / 3';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Shared post renderer helpers.
|
||||
* Zibll 9.0 article-list DOM contract.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -8,351 +8,206 @@
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_renderer_list')) {
|
||||
/**
|
||||
* Render a horizontal list card.
|
||||
*
|
||||
* @param array<string,mixed> $data Collected post data.
|
||||
* @param array<string,mixed> $cfg Renderer config.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_list(array $data, array $cfg): string {
|
||||
$classes = ['posts-item', 'list', 'ajax-item', 'flex', 'posts-item--' . ($cfg['card_style'] ?: 'standard')];
|
||||
|
||||
if ($cfg['style'] !== '' && $cfg['style'] !== 'default') {
|
||||
$classes[] = $cfg['style'];
|
||||
}
|
||||
if ($cfg['style'] === 'style2') {
|
||||
$classes[] = 'xx';
|
||||
$classes = ['posts-item', 'list', 'ajax-item'];
|
||||
if ((string) ($cfg['style'] ?? '') !== '') {
|
||||
$classes[] = (string) $cfg['style'];
|
||||
}
|
||||
if (!empty($data['is_mult_thumb'])) {
|
||||
$classes[] = 'mult-thumb';
|
||||
}
|
||||
if ($cfg['context'] === 'home') {
|
||||
$classes[] = 'posts-item--home-list';
|
||||
}
|
||||
if (empty($data['has_img'])) {
|
||||
if (!empty($data['is_no_thumb'])) {
|
||||
$classes[] = 'no-thumb';
|
||||
}
|
||||
if (($cfg['list_show_type'] ?? 'separate') === 'no_margin') {
|
||||
$classes[] = 'no-margin';
|
||||
if (!empty($cfg['no_margin'])) {
|
||||
$classes[] = 'no_margin';
|
||||
}
|
||||
$classes[] = ($cfg['style'] ?? '') === 'style2' ? 'flex xx' : 'flex';
|
||||
|
||||
$title = '<h2 class="item-heading' . (!empty($cfg['heading_bold']) ? ' font-bold' : '') . '"><a' . (!empty($cfg['target_blank']) ? ' target="_blank"' : '') . ' href="' . esc_url((string) $data['permalink']) . '">' . aksrt_renderer_title_markup($data, $cfg) . '</a></h2>';
|
||||
$excerpt_class = ($cfg['style'] ?? '') === 'style2' ? 'text-ellipsis-2' : 'text-ellipsis';
|
||||
$excerpt = '<div class="item-excerpt muted-color ' . $excerpt_class . ' mb6">' . aksrt_renderer_excerpt_markup($data, $cfg) . '</div>';
|
||||
$thumb = aksrt_renderer_thumb($data, $cfg);
|
||||
$mult = aksrt_renderer_mult_thumb($data);
|
||||
if (!empty($data['is_mult_thumb'])) {
|
||||
// Zibll's multi-image mode replaces the primary graphic; both must
|
||||
// never be emitted for the same list item.
|
||||
$thumb = '';
|
||||
$mult = aksrt_renderer_mult_thumb($data, $cfg);
|
||||
$graphic = '';
|
||||
if ($thumb !== '' && empty($data['is_mult_thumb'])) {
|
||||
$graphic = '<div class="post-graphic' . (($cfg['img_position'] ?? 'left') === 'right' ? ' order1' : '') . '">' . $thumb . '</div>';
|
||||
}
|
||||
|
||||
if ($cfg['card_style'] === 'text' || ($cfg['card_style'] === 'thumb_if_has' && empty($data['has_img']))) {
|
||||
$thumb = '';
|
||||
$mult = '';
|
||||
$classes[] = 'no-thumb';
|
||||
$classes[] = 'posts-item--text';
|
||||
}
|
||||
$title_markup = aksrt_renderer_title_markup($data, $cfg);
|
||||
$excerpt_markup = aksrt_renderer_excerpt_markup($data, $cfg);
|
||||
$badges = aksrt_renderer_badges($data, $cfg);
|
||||
$meta = aksrt_renderer_meta($data, $cfg);
|
||||
|
||||
$target_attr = !empty($cfg['target_blank']) ? ' target="_blank"' : '';
|
||||
$heading_cls = !empty($cfg['heading_bold']) ? 'item-heading item-heading--bold' : 'item-heading';
|
||||
$title_html = '<h2 class="' . $heading_cls . '"><a href="' . esc_url($data['permalink']) . '" rel="bookmark"' . $target_attr . '>' . $title_markup . '</a></h2>';
|
||||
$excerpt_html = $cfg['show_excerpt'] && $excerpt_markup !== ''
|
||||
? '<p class="item-excerpt">' . $excerpt_markup . '</p>'
|
||||
: '';
|
||||
|
||||
$html = '<article ' . aksrt_renderer_article_attrs($classes, $data) . '>';
|
||||
|
||||
if ($cfg['style'] === 'style2') {
|
||||
$html .= $title_html;
|
||||
$html .= '<div class="flex">';
|
||||
$html .= $thumb;
|
||||
$html .= '<div class="item-body flex xx flex1 jsb">';
|
||||
$html .= $mult ?: $excerpt_html;
|
||||
$html .= $badges;
|
||||
$html .= $meta;
|
||||
$html .= '</div></div>';
|
||||
$meta = aksrt_renderer_meta($data, $cfg, false);
|
||||
$html = '<posts class="' . esc_attr(implode(' ', $classes)) . '">';
|
||||
if (($cfg['style'] ?? '') === 'style2') {
|
||||
$html .= $title . '<div class="flex">' . $graphic . '<div class="item-body flex xx flex1 jsb">';
|
||||
$html .= $mult !== '' ? $mult : $excerpt;
|
||||
$html .= $badges . $meta . '</div></div>';
|
||||
} else {
|
||||
$html .= $thumb;
|
||||
$html .= '<div class="item-body flex xx flex1 jsb">';
|
||||
$html .= $title_html;
|
||||
$html .= $mult ?: $excerpt_html;
|
||||
$html .= '<div>' . $badges . $meta . '</div>';
|
||||
$html .= '</div>';
|
||||
$html .= $graphic . '<div class="item-body flex xx flex1 jsb">' . $title;
|
||||
$html .= $mult !== '' ? $mult : $excerpt;
|
||||
$html .= '<div>' . $badges . $meta . '</div></div>';
|
||||
}
|
||||
|
||||
$html .= '</article>';
|
||||
return $html;
|
||||
return $html . '</posts>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_card')) {
|
||||
/**
|
||||
* Render a vertical card or CMS resource card.
|
||||
*
|
||||
* @param array<string,mixed> $data Collected post data.
|
||||
* @param array<string,mixed> $cfg Renderer config.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_card(array $data, array $cfg): string {
|
||||
$classes = ['posts-item', 'card', 'ajax-item', 'posts-item--' . ($cfg['card_style'] ?: 'standard')];
|
||||
|
||||
if ($cfg['style'] !== '' && $cfg['style'] !== 'default') {
|
||||
$classes[] = $cfg['style'];
|
||||
}
|
||||
if ($cfg['context'] === 'home') {
|
||||
$classes[] = 'posts-item--home';
|
||||
}
|
||||
if ($cfg['mode'] === 'grid-cms') {
|
||||
$classes[] = 'posts-item--cms';
|
||||
}
|
||||
if (!empty($data['is_mult_thumb'])) {
|
||||
$classes[] = 'mult-thumb';
|
||||
}
|
||||
if (empty($data['has_img'])) {
|
||||
$classes[] = 'no-thumb';
|
||||
$classes = ['posts-item', 'card', 'ajax-item'];
|
||||
if ((string) ($cfg['style'] ?? '') !== '') {
|
||||
$classes[] = (string) $cfg['style'];
|
||||
}
|
||||
$title = '<h2 class="item-heading' . (!empty($cfg['heading_bold']) ? ' font-bold' : '') . '"><a' . (!empty($cfg['target_blank']) ? ' target="_blank"' : '') . ' href="' . esc_url((string) $data['permalink']) . '">' . aksrt_renderer_title_markup($data, $cfg) . '</a></h2>';
|
||||
|
||||
$thumb = aksrt_renderer_thumb($data, $cfg);
|
||||
$badges = aksrt_renderer_badges($data, $cfg);
|
||||
$resource_strip = aksrt_renderer_resource_strip($data);
|
||||
$meta = aksrt_renderer_meta($data, $cfg);
|
||||
$title_markup = aksrt_renderer_title_markup($data, $cfg);
|
||||
$html = '<article ' . aksrt_renderer_article_attrs($classes, $data) . '>';
|
||||
$html .= $thumb;
|
||||
$html .= '<div class="item-body">';
|
||||
$target_attr = !empty($cfg['target_blank']) ? ' target="_blank"' : '';
|
||||
$heading_cls = !empty($cfg['heading_bold']) ? 'item-heading item-heading--bold' : 'item-heading';
|
||||
$html .= '<h2 class="' . $heading_cls . '"><a href="' . esc_url($data['permalink']) . '" rel="bookmark"' . $target_attr . '>' . $title_markup . '</a></h2>';
|
||||
|
||||
$html .= $badges;
|
||||
|
||||
if ($cfg['mode'] === 'grid-cms') {
|
||||
$html .= $resource_strip;
|
||||
}
|
||||
|
||||
$html .= $meta;
|
||||
$html .= '</div></article>';
|
||||
|
||||
return $html;
|
||||
$html = '<posts class="' . esc_attr(implode(' ', $classes)) . '">';
|
||||
$html .= aksrt_renderer_thumb($data, $cfg);
|
||||
$html .= '<div class="item-body">' . $title;
|
||||
$html .= aksrt_renderer_badges($data, $cfg);
|
||||
$html .= aksrt_renderer_meta($data, $cfg, true);
|
||||
return $html . '</div></posts>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_mini')) {
|
||||
/**
|
||||
* Render a compact mini card.
|
||||
*
|
||||
* @param array<string,mixed> $data Collected post data.
|
||||
* @param array<string,mixed> $cfg Renderer config.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_mini(array $data, array $cfg): string {
|
||||
$classes = ['posts-mini'];
|
||||
if (!empty($cfg['extra_class'])) {
|
||||
$classes[] = $cfg['extra_class'];
|
||||
function aksrt_renderer_mini(array $data, array $cfg = []): string {
|
||||
$target = !empty($cfg['target_blank']) ? ' target="_blank"' : '';
|
||||
$thumb = '';
|
||||
$show_thumb = !array_key_exists('show_thumb', $cfg) || !empty($cfg['show_thumb']);
|
||||
$show_meta = !array_key_exists('show_meta', $cfg) || !empty($cfg['show_meta']);
|
||||
if ($show_thumb && (string) $data['primary'] !== '') {
|
||||
$default_attr = empty($data['has_real']) ? ' data-thumb="default"' : '';
|
||||
$thumb = '<div class="mr10"><div class="item-thumbnail"><a' . $target . ' href="' . esc_url((string) $data['permalink']) . '"><img' . $default_attr . aksrt_get_lazy_attr('lazy_posts_thumb', (string) $data['primary'], 'fit-cover radius8') . ' alt="' . esc_attr((string) $data['title']) . '"></a></div></div>';
|
||||
}
|
||||
if (empty($data['has_img'])) {
|
||||
$classes[] = 'posts-mini--no-thumb';
|
||||
$number = '';
|
||||
if (!empty($cfg['show_number'])) {
|
||||
$number_value = max(1, (int) ($cfg['number_offset'] ?? 1));
|
||||
$colors = ['c-red', 'c-yellow', 'c-purple', 'c-blue', 'c-green'];
|
||||
$number_class = $colors[$number_value - 1] ?? '';
|
||||
$number = '<span class="badg badg-sm mr3 ' . esc_attr($number_class) . '">' . $number_value . '</span>';
|
||||
}
|
||||
|
||||
$number_html = '';
|
||||
if ($cfg['show_number'] && $cfg['number_offset'] > 0) {
|
||||
$badge_colors = ['c-red', 'c-yellow', 'c-orange', 'c-blue', 'c-green'];
|
||||
$index = $cfg['number_offset'] - 1;
|
||||
$color = $badge_colors[$index] ?? '';
|
||||
$number_html = '<span class="badg badg-sm mr3 ' . esc_attr($color) . '">' . (int) $cfg['number_offset'] . '</span>';
|
||||
$title_class = $show_thumb ? ' text-ellipsis-2' : ' text-ellipsis' . (!$show_meta && empty($cfg['show_number']) ? ' icon-circle' : '');
|
||||
$title = esc_html((string) $data['title']);
|
||||
if ((string) ($data['subtitle'] ?? '') !== '') {
|
||||
$title .= '<span class="focus-color">' . esc_html((string) $data['subtitle']) . '</span>';
|
||||
}
|
||||
|
||||
$thumb_html = '';
|
||||
$target_attr = !empty($cfg['target_blank']) ? ' target="_blank"' : '';
|
||||
if ($cfg['show_thumb'] && !empty($data['has_img'])) {
|
||||
$fit_class = !empty($cfg['thumb_fit']) && $cfg['thumb_fit'] === 'contain' ? 'fit-contain' : 'fit-cover';
|
||||
$thumb_attr = aksrt_get_lazy_attr('lazy_posts_thumb', (string) $data['img_url'], $fit_class);
|
||||
$thumb_img = '<img' . $thumb_attr . ' alt="' . esc_attr($data['title']) . '">';
|
||||
|
||||
$thumb_html = '<a href="' . esc_url($data['permalink']) . '" class="item-thumbnail" aria-label="' . esc_attr($data['title']) . '"' . $target_attr . '>' . $thumb_img . '</a>';
|
||||
$meta = '';
|
||||
if ($show_meta) {
|
||||
$show_time = !empty($cfg['show_time']);
|
||||
if (!empty($cfg['show_author'])) {
|
||||
$author_value = $show_time ? (string) $data['time_ago'] : (string) $data['author_name'];
|
||||
$meta_left = '<item class="meta-author flex ac"><img class="avatar-mini" src="' . esc_url((string) $data['avatar_url']) . '" alt="" width="20" height="20"><span class="ml6">' . esc_html($author_value) . '</span></item>';
|
||||
} else {
|
||||
$meta_left = $show_time ? '<item title="' . esc_attr((string) $data['time_title']) . '" class="icon-circle mln3">' . esc_html((string) $data['time_ago']) . '</item>' : '';
|
||||
}
|
||||
$pay = aksrt_renderer_pay_badge($data, true);
|
||||
if ($meta_left === '') {
|
||||
$meta_left = $pay;
|
||||
$pay = '';
|
||||
}
|
||||
if ($meta_left === '') {
|
||||
$meta_left = '<item></item>';
|
||||
}
|
||||
$meta_right = $pay . '<item class="meta-view">' . aksrt_renderer_svg_icon('view') . esc_html(aksrt_renderer_meta_number((int) $data['views'])) . '</item>';
|
||||
$meta = '<div class="item-meta muted-2-color flex jsb ac' . (!$show_thumb ? ' mt6' : '') . '">' . $meta_left . '<div class="meta-right">' . $meta_right . '</div></div>';
|
||||
}
|
||||
|
||||
$heading_class = 'item-heading' . (!empty($cfg['heading_bold']) ? ' item-heading--bold' : '') . (!empty($data['has_img']) ? ' text-ellipsis-2' : ' text-ellipsis');
|
||||
$title_html = '<h2 class="' . esc_attr($heading_class) . '">' . $number_html . '<a href="' . esc_url($data['permalink']) . '"' . $target_attr . '>' . aksrt_renderer_title_markup($data, $cfg) . '</a></h2>';
|
||||
|
||||
$html = '<div class="' . esc_attr(implode(' ', array_unique($classes))) . '">';
|
||||
$html .= $thumb_html;
|
||||
$html .= '<div class="posts-mini-con flex xx flex1 jsb">';
|
||||
$html .= $title_html;
|
||||
$html .= aksrt_renderer_meta($data, $cfg);
|
||||
$html .= '</div></div>';
|
||||
|
||||
return $html;
|
||||
$class = trim('posts-mini ' . (string) ($cfg['class'] ?? ''));
|
||||
return '<div class="' . esc_attr($class) . '">' . $thumb . '<div class="posts-mini-con flex xx flex1 jsb"><h2 class="item-heading' . esc_attr($title_class) . '">' . $number . '<a' . $target . ' href="' . esc_url((string) $data['permalink']) . '">' . $title . '</a></h2>' . $meta . '</div></div>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_render_post')) {
|
||||
/**
|
||||
* Render one post item inside a loop.
|
||||
*
|
||||
* @param array<string,mixed> $config Renderer config overrides.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_render_post(array $config = []): string {
|
||||
$cfg = aksrt_renderer_config($config);
|
||||
function aksrt_render_post(array $args = []): string {
|
||||
$cfg = aksrt_renderer_config($args);
|
||||
$data = aksrt_renderer_collect_post_data($cfg);
|
||||
|
||||
if (empty($data)) {
|
||||
if (!$data) {
|
||||
return '';
|
||||
}
|
||||
|
||||
switch ($cfg['mode']) {
|
||||
case 'card':
|
||||
case 'grid-cms':
|
||||
return aksrt_renderer_card($data, $cfg);
|
||||
case 'mini':
|
||||
return aksrt_renderer_mini($data, $cfg);
|
||||
case 'list':
|
||||
default:
|
||||
return aksrt_renderer_list($data, $cfg);
|
||||
}
|
||||
return ($cfg['mode'] ?? 'list') === 'card'
|
||||
? aksrt_renderer_card($data, $cfg)
|
||||
: aksrt_renderer_list($data, $cfg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_render_post_list')) {
|
||||
/**
|
||||
* Render a query loop with the unified renderer.
|
||||
* Render the canonical article stream.
|
||||
*
|
||||
* @param WP_Query|null $query Posts query. Falls back to global loop.
|
||||
* @param array<string,mixed> $config Renderer config overrides.
|
||||
* @param bool $echo Whether to echo output.
|
||||
* @return string
|
||||
* @param array<string,mixed> $args Zibll-shaped list arguments.
|
||||
* @param WP_Query|null $query Optional custom query.
|
||||
*/
|
||||
function aksrt_render_post_list(?WP_Query $query = null, array $config = [], bool $echo = true): string {
|
||||
$cfg = aksrt_renderer_config($config);
|
||||
$wrapper_classes = ['posts-row', 'ajaxpager'];
|
||||
|
||||
if ($cfg['context'] === 'home') {
|
||||
$wrapper_classes[] = 'aksrt-homepage__posts';
|
||||
$wrapper_classes[] = 'post-grid';
|
||||
$wrapper_classes[] = 'post-grid--home';
|
||||
} elseif ($cfg['mode'] !== 'mini') {
|
||||
$wrapper_classes[] = 'post-grid';
|
||||
$wrapper_classes[] = 'post-grid--' . $cfg['mode'];
|
||||
function aksrt_render_post_list(array $args = [], ?WP_Query $query = null, bool $echo = true): string {
|
||||
$cfg = aksrt_renderer_config($args);
|
||||
$has_posts = $query instanceof WP_Query ? $query->have_posts() : have_posts();
|
||||
if (!$has_posts) {
|
||||
$html = aksrt_get_null(__('暂无内容', 'aksrt'), 100, 'null-post.svg');
|
||||
if ($echo) {
|
||||
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
return '';
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
if (!empty($config['wrapper_class']) && is_string($config['wrapper_class'])) {
|
||||
foreach (preg_split('/\s+/', trim($config['wrapper_class'])) as $extra_class) {
|
||||
$extra_class = sanitize_html_class($extra_class);
|
||||
if ($extra_class !== '') {
|
||||
$wrapper_classes[] = $extra_class;
|
||||
}
|
||||
$classes = ['posts-row', 'ajaxpager'];
|
||||
foreach (preg_split('/\s+/', trim((string) ($cfg['wrapper_class'] ?? ''))) ?: [] as $class) {
|
||||
$class = sanitize_html_class($class);
|
||||
if ($class !== '') {
|
||||
$classes[] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
$wrapper_attr = 'class="' . esc_attr(implode(' ', array_unique($wrapper_classes))) . '"';
|
||||
if ($cfg['columns'] > 1) {
|
||||
$wrapper_attr .= ' style="--aksrt-widget-columns:' . (int) $cfg['columns'] . '"';
|
||||
}
|
||||
|
||||
$data_view = in_array($cfg['mode'], ['card', 'grid-cms'], true) ? 'card' : $cfg['mode'];
|
||||
// Homepage panel already provides .posts-row.ajaxpager — allow callers to skip nesting.
|
||||
$skip_wrapper = !empty($config['skip_wrapper']);
|
||||
$html = '';
|
||||
$html = empty($cfg['skip_wrapper'])
|
||||
? '<div class="' . esc_attr(implode(' ', array_unique($classes))) . '" data-view="' . esc_attr((string) $cfg['mode']) . '">'
|
||||
: '';
|
||||
|
||||
if ($query instanceof WP_Query) {
|
||||
if (!$query->have_posts()) {
|
||||
$html = '<div class="no-results"><p>' . esc_html__('暂无文章', 'aksrt') . '</p></div>';
|
||||
} else {
|
||||
if (!$skip_wrapper) {
|
||||
$html .= '<div ' . $wrapper_attr . ' data-view="' . esc_attr($data_view) . '">';
|
||||
}
|
||||
$number = $cfg['number_offset'];
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
if ($cfg['mode'] === 'mini' && $cfg['show_number']) {
|
||||
$number++;
|
||||
$config['number_offset'] = $number;
|
||||
$cfg = aksrt_renderer_config($config);
|
||||
}
|
||||
$html .= aksrt_render_post($cfg);
|
||||
}
|
||||
if (!$skip_wrapper) {
|
||||
$html .= '</div>';
|
||||
}
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
$html .= aksrt_render_post($cfg);
|
||||
}
|
||||
wp_reset_postdata();
|
||||
} else {
|
||||
if (!have_posts()) {
|
||||
$html = '<div class="no-results"><p>' . esc_html__('暂无文章', 'aksrt') . '</p></div>';
|
||||
} else {
|
||||
if (!$skip_wrapper) {
|
||||
$html .= '<div ' . $wrapper_attr . ' data-view="' . esc_attr($data_view) . '">';
|
||||
}
|
||||
while (have_posts()) {
|
||||
the_post();
|
||||
$html .= aksrt_render_post($cfg);
|
||||
}
|
||||
if (!$skip_wrapper) {
|
||||
$html .= '</div>';
|
||||
}
|
||||
while (have_posts()) {
|
||||
the_post();
|
||||
$html .= aksrt_render_post($cfg);
|
||||
}
|
||||
}
|
||||
if (empty($cfg['skip_wrapper'])) {
|
||||
$html .= '</div>';
|
||||
}
|
||||
|
||||
if ($echo) {
|
||||
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
return '';
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_render_mini_list')) {
|
||||
/**
|
||||
* Convenience wrapper for mini lists.
|
||||
*
|
||||
* @param WP_Query $query Posts query.
|
||||
* @param array<string,mixed> $config Renderer config overrides.
|
||||
* @param bool $echo Whether to echo output.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_render_mini_list(WP_Query $query, array $config = [], bool $echo = true): string {
|
||||
$config['mode'] = 'mini';
|
||||
return aksrt_render_post_list($query, $config, $echo);
|
||||
function aksrt_render_mini_list(WP_Query $query, array $args = [], bool $echo = true): string {
|
||||
$cfg = aksrt_renderer_config($args);
|
||||
$html = '';
|
||||
$number = max(0, (int) ($args['number_offset'] ?? 0));
|
||||
while ($query->have_posts()) {
|
||||
$query->the_post();
|
||||
$data = aksrt_renderer_collect_post_data($cfg);
|
||||
if (!$data) {
|
||||
continue;
|
||||
}
|
||||
$number++;
|
||||
$html .= aksrt_renderer_mini($data, array_merge($cfg, ['number_offset' => $number]));
|
||||
}
|
||||
wp_reset_postdata();
|
||||
if ($echo) {
|
||||
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
return '';
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_render_placeholder')) {
|
||||
/**
|
||||
* Render skeleton placeholders for loading states.
|
||||
*
|
||||
* @param string $mode list|card|mini.
|
||||
* @param int $count Number of placeholders.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_render_placeholder(string $mode = 'list', int $count = 3): string {
|
||||
$count = max(1, min(12, $count));
|
||||
$html = '';
|
||||
|
||||
if ($mode === 'card') {
|
||||
$item = '<div class="posts-item card"><div class="item-thumbnail"><div class="radius8 item-thumbnail placeholder"></div></div>'
|
||||
. '<div class="item-body"><h2 class="item-excerpt placeholder t1 item-heading"></h2>'
|
||||
. '<p class="mt10 placeholder k2"></p>'
|
||||
. '<i class="flex jsb"><i class="placeholder s1"></i><i class="placeholder s1 ml10"></i></i></div></div>';
|
||||
$html = str_repeat($item, $count);
|
||||
} elseif ($mode === 'mini') {
|
||||
$item = '<div class="posts-mini"><div class="item-thumbnail"><div class="radius8 placeholder"></div></div>'
|
||||
. '<div class="posts-mini-con"><div class="placeholder t1"></div>'
|
||||
. '<div class="placeholder k2 mt6"></div></div></div>';
|
||||
$html = str_repeat($item, $count);
|
||||
} else {
|
||||
$item = '<div class="posts-item list flex"><div class="post-graphic"><div class="radius8 item-thumbnail placeholder"></div></div>'
|
||||
. '<div class="item-body flex xx flex1 jsb"><p class="placeholder t1"></p>'
|
||||
. '<h4 class="item-excerpt placeholder k1"></h4><p class="placeholder k2"></p>'
|
||||
. '<i><i class="placeholder s1"></i><i class="placeholder s1 ml10"></i></i></div></div>';
|
||||
$html = str_repeat($item, $count);
|
||||
}
|
||||
|
||||
return $html;
|
||||
$class = $mode === 'card' ? 'posts-item card' : 'posts-item list flex';
|
||||
$item = '<posts class="' . esc_attr($class) . '"><div class="post-graphic"><div class="item-thumbnail placeholder"></div></div><div class="item-body flex xx flex1 jsb"><div class="placeholder t1"></div><div class="placeholder k2"></div><div class="placeholder s1"></div></div></posts>';
|
||||
return str_repeat($item, $count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Shared post renderer helpers.
|
||||
* Zibll 9.0 article-list data and markup fragments.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -8,12 +8,7 @@
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_renderer_collect_post_data')) {
|
||||
/**
|
||||
* Aggregate the runtime data needed by all renderer modes.
|
||||
*
|
||||
* @param array<string,mixed> $cfg Renderer config.
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
/** @return array<string,mixed> */
|
||||
function aksrt_renderer_collect_post_data(array $cfg): array {
|
||||
$post_id = (int) get_the_ID();
|
||||
if ($post_id <= 0) {
|
||||
@@ -21,278 +16,264 @@ if (!function_exists('aksrt_renderer_collect_post_data')) {
|
||||
}
|
||||
|
||||
$images = aksrt_renderer_resolve_images($post_id, $cfg);
|
||||
$gallery_images = array_slice($images['gallery'], 0, $cfg['multi_thumb_limit']);
|
||||
$is_mult_thumb = !empty($cfg['multi_thumb_enabled'])
|
||||
&& count($gallery_images) >= (int) $cfg['multi_thumb_min']
|
||||
&& $cfg['mode'] === 'list';
|
||||
|
||||
$author_id = (int) get_post_field('post_author', $post_id);
|
||||
$categories = get_the_category($post_id) ?: [];
|
||||
$tags = get_the_tags($post_id) ?: [];
|
||||
$content_images = (array) $images['gallery'];
|
||||
$gallery = array_slice($content_images, 0, 4);
|
||||
$allow_conditional = !empty($cfg['allow_conditional_layout']) && ($cfg['mode'] ?? 'list') === 'list';
|
||||
$is_mult_thumb = false;
|
||||
$is_no_thumb = false;
|
||||
|
||||
if ($allow_conditional) {
|
||||
if (($cfg['is_no_thumb'] ?? false) !== 'disable'
|
||||
&& (($cfg['list_type'] ?? 'thumb') === 'text'
|
||||
|| (($cfg['list_type'] ?? 'thumb') === 'thumb_if_has' && empty($images['has_real'])))) {
|
||||
$is_no_thumb = true;
|
||||
} elseif (($cfg['is_mult_thumb'] ?? false) !== 'disable' && count($gallery) > 2) {
|
||||
$is_mult_thumb = has_post_format(['image', 'gallery'], $post_id);
|
||||
if (!$is_mult_thumb) {
|
||||
foreach ($categories as $category) {
|
||||
if (in_array((int) $category->term_id, array_map('intval', (array) ($cfg['mult_thumb_cat'] ?? [])), true)) {
|
||||
$is_mult_thumb = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (($cfg['is_no_thumb'] ?? false) === true) {
|
||||
$is_no_thumb = true;
|
||||
$is_mult_thumb = false;
|
||||
}
|
||||
if (($cfg['is_mult_thumb'] ?? false) === true && count($gallery) > 2 && !$is_no_thumb) {
|
||||
$is_mult_thumb = true;
|
||||
}
|
||||
|
||||
$custom_excerpt = class_exists('\AKSRT\Core\PostMetaBox')
|
||||
? (string) \AKSRT\Core\PostMetaBox::get_meta_value($post_id, 'custom_excerpt', '')
|
||||
: '';
|
||||
$custom_subtitle = (string) get_post_meta($post_id, '_subtitle', true);
|
||||
$excerpt_source = $custom_excerpt !== '' ? $custom_excerpt : (string) get_the_excerpt($post_id);
|
||||
if ($excerpt_source === '') {
|
||||
$excerpt_source = (string) get_post_field('post_content', $post_id, 'raw');
|
||||
$excerpt = $custom_excerpt !== '' ? $custom_excerpt : (string) get_the_excerpt($post_id);
|
||||
if ($excerpt === '') {
|
||||
$excerpt = (string) get_post_field('post_content', $post_id, 'raw');
|
||||
}
|
||||
$excerpt = wp_trim_words(wp_strip_all_tags($excerpt_source), $cfg['excerpt_words'], '...');
|
||||
$author_id = (int) get_post_field('post_author', $post_id);
|
||||
$author = get_userdata($author_id);
|
||||
$time_value = ($cfg['time_source'] ?? 'modified') === 'date'
|
||||
? (string) get_the_time('Y-m-d H:i:s', $post_id)
|
||||
: (string) get_the_modified_time('Y-m-d H:i:s', $post_id);
|
||||
$time_timestamp = strtotime($time_value) ?: (int) get_the_time('U', $post_id);
|
||||
|
||||
$resource_meta = function_exists('aksrt_get_resource_meta') ? aksrt_get_resource_meta($post_id) : [];
|
||||
$resource_strip = function_exists('aksrt_resource_meta_strip') ? aksrt_resource_meta_strip($resource_meta) : [];
|
||||
$subtitle = class_exists('\AKSRT\Core\PostMetaBox')
|
||||
? (string) \AKSRT\Core\PostMetaBox::get_meta_value($post_id, 'subtitle', '')
|
||||
: '';
|
||||
$pay_meta = aksrt_get_pay_meta($post_id);
|
||||
if (!is_array($pay_meta)) {
|
||||
$pay_meta = [];
|
||||
}
|
||||
|
||||
return [
|
||||
'post_id' => $post_id,
|
||||
'permalink' => get_permalink($post_id),
|
||||
'title' => get_the_title($post_id),
|
||||
'subtitle' => $custom_subtitle,
|
||||
'excerpt' => $excerpt,
|
||||
'img_url' => $images['primary'],
|
||||
'has_img' => !empty($images['has_thumb']),
|
||||
'has_real_img' => !empty($images['has_real']),
|
||||
'gallery_images' => $gallery_images,
|
||||
'is_mult_thumb' => $is_mult_thumb,
|
||||
'is_video_cover' => !empty(get_post_meta($post_id, '_aksrt_featured_video', true)) || !empty(get_post_meta($post_id, '_video_url', true)),
|
||||
'author_id' => $author_id,
|
||||
'avatar_url' => get_avatar_url($author_id, ['size' => 40]),
|
||||
'author_name' => get_the_author(),
|
||||
'categories' => $categories,
|
||||
'tags' => $tags,
|
||||
'comment_count' => (int) get_comments_number($post_id),
|
||||
'views' => function_exists('aksrt_get_post_views') ? (int) aksrt_get_post_views($post_id) : 0,
|
||||
'likes' => function_exists('aksrt_get_post_likes') ? (int) aksrt_get_post_likes($post_id) : 0,
|
||||
'time_ago' => human_time_diff((int) get_the_time('U', $post_id), current_time('timestamp')),
|
||||
'resource_badge' => function_exists('aksrt_resource_card_badge_text') ? (string) aksrt_resource_card_badge_text($post_id) : '',
|
||||
'resource_strip' => $resource_strip,
|
||||
'is_resource' => function_exists('aksrt_is_resource_post') ? aksrt_is_resource_post($post_id) : false,
|
||||
'is_sticky' => is_sticky($post_id),
|
||||
'thumb_ratio_css' => aksrt_renderer_thumb_ratio_value((string) $cfg['thumb_ratio']),
|
||||
'thumb_ratio_key' => (string) $cfg['thumb_ratio'],
|
||||
'post_id' => $post_id,
|
||||
'permalink' => get_permalink($post_id),
|
||||
'title' => get_the_title($post_id),
|
||||
'subtitle' => $subtitle,
|
||||
'excerpt' => wp_trim_words(wp_strip_all_tags($excerpt), 30, '...'),
|
||||
'primary' => (string) $images['primary'],
|
||||
'has_real' => !empty($images['has_real']),
|
||||
'gallery' => $gallery,
|
||||
'gallery_count' => count($content_images),
|
||||
'slides' => array_slice((array) $images['slides'], 0, 8),
|
||||
'is_slide' => !empty($images['is_slide']),
|
||||
'video_url' => (string) $images['video_url'],
|
||||
'is_mult_thumb' => $is_mult_thumb,
|
||||
'is_no_thumb' => $is_no_thumb,
|
||||
'categories' => $categories,
|
||||
'tags' => $tags,
|
||||
'author_id' => $author_id,
|
||||
'author_name' => $author instanceof WP_User ? $author->display_name : '',
|
||||
'avatar_url' => get_avatar_url($author_id, ['size' => 40]),
|
||||
'time_title' => $time_value,
|
||||
'time_ago' => human_time_diff($time_timestamp, current_time('timestamp')) . __('前', 'aksrt'),
|
||||
'views' => (int) aksrt_get_post_views($post_id),
|
||||
'likes' => (int) aksrt_get_post_likes($post_id),
|
||||
'comments' => (int) get_comments_number($post_id),
|
||||
'comments_open' => comments_open($post_id),
|
||||
'comments_link' => get_comments_link($post_id),
|
||||
'post_type' => (string) get_post_type($post_id),
|
||||
'is_sticky' => is_sticky($post_id),
|
||||
'resource_badge' => (string) aksrt_resource_card_badge_text($post_id),
|
||||
'pay_type' => sanitize_key((string) ($pay_meta['pay_type'] ?? 'no')),
|
||||
'pay_limit' => (int) ($pay_meta['pay_limit'] ?? 0),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_article_attrs')) {
|
||||
/**
|
||||
* Build the article wrapper attributes.
|
||||
*
|
||||
* @param string[] $classes CSS classes.
|
||||
* @param array<string,mixed> $data Collected post data.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_article_attrs(array $classes, array $data): string {
|
||||
$classes[] = 'thumb-ratio--' . str_replace(':', '-', (string) $data['thumb_ratio_key']);
|
||||
|
||||
return sprintf(
|
||||
'class="%s" style="%s"',
|
||||
esc_attr(implode(' ', array_unique(array_filter($classes)))),
|
||||
esc_attr('--aksrt-thumb-ratio:' . $data['thumb_ratio_css'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_thumb')) {
|
||||
/**
|
||||
* Render the primary thumbnail.
|
||||
*
|
||||
* @param array<string,mixed> $data Collected post data.
|
||||
* @param array<string,mixed> $cfg Renderer config.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_thumb(array $data, array $cfg): string {
|
||||
if (!$cfg['show_thumb'] || empty($data['has_img'])) {
|
||||
if (!empty($data['is_no_thumb']) || (string) $data['primary'] === '') {
|
||||
return '';
|
||||
}
|
||||
$is_contain = (($cfg['thumb']['list_thumb_fit'] ?? '') === 'contain');
|
||||
$target = !empty($cfg['target_blank']) ? ' target="_blank"' : '';
|
||||
$content = '';
|
||||
$format_icon = '';
|
||||
$default_attr = empty($data['has_real']) ? ' data-thumb="default"' : '';
|
||||
$has_video_thumb = (string) $data['video_url'] !== '' && !empty($cfg['thumb']['list_thumb_video_s']);
|
||||
$has_slides = !$has_video_thumb && !empty($data['is_slide']) && count((array) $data['slides']) > 0;
|
||||
|
||||
$img = (string) $data['img_url'];
|
||||
$title = (string) $data['title'];
|
||||
$href = (string) $data['permalink'];
|
||||
$is_sticky = !empty($data['is_sticky']);
|
||||
$has_real_img = !empty($data['has_real_img']);
|
||||
|
||||
$fit_class = !empty($cfg['thumb_fit']) && $cfg['thumb_fit'] === 'contain' ? 'fit-contain' : 'fit-cover';
|
||||
$img_attr = aksrt_get_lazy_attr('lazy_posts_thumb', $img, $fit_class);
|
||||
$img_html = '<img' . $img_attr . ' alt="' . esc_attr($title) . '">';
|
||||
|
||||
$sticky_html = ($is_sticky && !empty($cfg['badge_show']))
|
||||
? '<badge class="img-badge left jb-red">' . esc_html__('置顶', 'aksrt') . '</badge>'
|
||||
: '';
|
||||
|
||||
$format_badge = '';
|
||||
if (!empty($data['is_mult_thumb']) && !empty($data['gallery_images'])) {
|
||||
$format_badge = '<badge class="b-black opacity8 abs-right">' . esc_html(count($data['gallery_images'])) . '</badge>';
|
||||
} elseif (!empty($data['is_video_cover'])) {
|
||||
$format_badge = '<badge class="b-black opacity8 abs-right"><i class="fas fa-play-circle" aria-hidden="true"></i></badge>';
|
||||
}
|
||||
|
||||
$empty_class = $has_real_img ? '' : ' item-thumbnail--fallback';
|
||||
$target_attr = !empty($cfg['target_blank']) ? ' target="_blank"' : '';
|
||||
|
||||
if ($cfg['mode'] === 'list') {
|
||||
$graphic_class = 'post-graphic';
|
||||
if (($cfg['list_img_position'] ?? 'left') === 'right') {
|
||||
$graphic_class .= ' order1';
|
||||
if ($has_video_thumb) {
|
||||
$muted = !empty($cfg['thumb']['list_thumb_video_mute_s']);
|
||||
$content .= '<div class="video-thumb-box" video-url="' . esc_url((string) $data['video_url']) . '" data-volume="' . ($muted ? 'none' : '100') . '" data-post-thumb-video>';
|
||||
$content .= '<div class="img-thumb"><img' . $default_attr . aksrt_get_lazy_attr('lazy_posts_thumb', (string) $data['primary'], 'fit-cover radius8') . ' alt="' . esc_attr((string) $data['title']) . '"></div>';
|
||||
$content .= '<div class="video-thumb"><div class="dplayer dplayer-thumb"><video playsinline loop preload="none"' . ($muted ? ' muted' : '') . ' data-src="' . esc_url((string) $data['video_url']) . '"></video></div></div></div>';
|
||||
$format_icon = '<i class="fa fa-play-circle em12 mt6 c-white opacity8" aria-hidden="true"></i>';
|
||||
} elseif ($has_slides) {
|
||||
$content .= '<div class="relative zib-slider"><div class="new-swiper item-thumbnail' . ($is_contain ? ' gradient-background' : '') . '" data-loop="true" data-effect="slide" data-autoplay="1" data-post-thumb-slider><div class="swiper-wrapper">';
|
||||
foreach ((array) $data['slides'] as $image) {
|
||||
$content .= '<div class="swiper-slide' . ($is_contain ? ' gradient-bg' : '') . '"' . ($is_contain ? ' data-opacity="0.2"' : '') . '><a' . $target . ' href="' . esc_url((string) $data['permalink']) . '"><img' . aksrt_get_lazy_attr('lazy_posts_thumb', (string) $image, 'radius8') . ' alt="' . esc_attr((string) $data['title']) . '"></a></div>';
|
||||
}
|
||||
$content .= '</div><div class="swiper-pagination kaoyou"></div></div></div>';
|
||||
$format_icon = '<badge class="b-black opacity8 mt6"><i class="fa fa-image mr3" aria-hidden="true"></i>' . count((array) $data['slides']) . '</badge>';
|
||||
} else {
|
||||
$content .= '<a' . $target . ' href="' . esc_url((string) $data['permalink']) . '"><img' . $default_attr . aksrt_get_lazy_attr('lazy_posts_thumb', (string) $data['primary'], 'fit-cover radius8') . ' alt="' . esc_attr((string) $data['title']) . '"></a>';
|
||||
$format = get_post_format((int) $data['post_id']);
|
||||
if ((string) $data['video_url'] !== '') {
|
||||
$format_icon = '<i class="fa fa-play-circle em12 mt6 c-white opacity8" aria-hidden="true"></i>';
|
||||
} elseif (in_array($format, ['image', 'gallery'], true) && (int) $data['gallery_count'] > 0) {
|
||||
$format_icon = '<badge class="b-black opacity8 mr6 mt6"><i class="fa fa-image mr3" aria-hidden="true"></i>' . (int) $data['gallery_count'] . '</badge>';
|
||||
} elseif ($format === 'video') {
|
||||
$format_icon = '<i class="fa fa-play-circle em12 mr6 mt6 c-white opacity8" aria-hidden="true"></i>';
|
||||
}
|
||||
return '<div class="' . esc_attr($graphic_class) . '"><div class="item-thumbnail' . esc_attr($empty_class) . '"><a href="' . esc_url($href) . '" rel="bookmark"' . $target_attr . '>'
|
||||
. $img_html . '</a>' . $sticky_html . $format_badge . '</div></div>';
|
||||
}
|
||||
|
||||
return '<div class="item-thumbnail' . esc_attr($empty_class) . '"><a href="' . esc_url($href) . '" rel="bookmark"' . $target_attr . '>'
|
||||
. $img_html . '</a>' . $sticky_html . $format_badge . '</div>';
|
||||
if ($format_icon !== '') {
|
||||
$content .= '<div class="abs-center right-top">' . $format_icon . '</div>';
|
||||
}
|
||||
if (!empty($data['is_sticky'])) {
|
||||
$content .= '<badge class="img-badge left jb-red">' . esc_html__('置顶', 'aksrt') . '</badge>';
|
||||
}
|
||||
|
||||
$fit = $is_contain && !$has_slides ? ' contain gradient-bg' : '';
|
||||
$opacity = $is_contain && !$has_slides ? ' data-opacity="0.2"' : '';
|
||||
return '<div class="item-thumbnail' . $fit . '"' . $opacity . '>' . $content . '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_mult_thumb')) {
|
||||
/**
|
||||
* Render the multi-image strip used by list cards.
|
||||
*
|
||||
* @param array<string,mixed> $data Collected post data.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_mult_thumb(array $data): string {
|
||||
if (empty($data['is_mult_thumb']) || empty($data['gallery_images'])) {
|
||||
function aksrt_renderer_mult_thumb(array $data, array $cfg): string {
|
||||
if (empty($data['is_mult_thumb'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$html = '<a class="thumb-items contain" href="' . esc_url($data['permalink']) . '" aria-label="' . esc_attr($data['title']) . '">';
|
||||
|
||||
foreach (array_slice($data['gallery_images'], 0, 4) as $image) {
|
||||
$html .= '<span>';
|
||||
$html .= '<img' . aksrt_get_lazy_attr('lazy_posts_thumb', (string) $image, 'fit-cover') . ' alt="">';
|
||||
$html .= '</span>';
|
||||
$fit = (($cfg['thumb']['list_thumb_fit'] ?? '') === 'contain') ? ' contain' : '';
|
||||
$target = !empty($cfg['target_blank']) ? ' target="_blank"' : '';
|
||||
$html = '<a' . $target . ' class="thumb-items' . $fit . '" href="' . esc_url((string) $data['permalink']) . '">';
|
||||
foreach (array_slice((array) $data['gallery'], 0, 4) as $index => $image) {
|
||||
$badge = '';
|
||||
if ($index === 3 && (int) ($data['gallery_count'] ?? 0) > 4) {
|
||||
$badge = '<div class="abs-center right-top"><badge class="b-black mr6 mt6 em09"><i class="fa fa-image mr3" aria-hidden="true"></i>+' . ((int) $data['gallery_count'] - 4) . '</badge></div>';
|
||||
}
|
||||
$html .= '<span>' . $badge . '<img' . aksrt_get_lazy_attr('lazy_posts_thumb', (string) $image, 'fit-cover radius8') . ' alt=""></span>';
|
||||
}
|
||||
return $html . '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
$html .= '</a>';
|
||||
return $html;
|
||||
if (!function_exists('aksrt_renderer_pay_badge')) {
|
||||
function aksrt_renderer_pay_badge(array $data, bool $compact = false): string {
|
||||
if ((string) $data['resource_badge'] === '') {
|
||||
return '';
|
||||
}
|
||||
$is_vip = (int) ($data['pay_limit'] ?? 0) > 0 || (string) ($data['pay_type'] ?? '') === 'vip';
|
||||
$vip_level = max(1, min(2, (int) ($data['pay_limit'] ?? 1)));
|
||||
$class = $is_vip ? 'jb-vip' . $vip_level : 'c-yellow';
|
||||
$type_labels = function_exists('aksrt_get_pay_types') ? aksrt_get_pay_types() : [];
|
||||
$title = (string) ($type_labels[(string) ($data['pay_type'] ?? '')] ?? __('付费内容', 'aksrt'));
|
||||
$icon = $is_vip ? aksrt_renderer_vip_icon($vip_level) : '';
|
||||
if ($compact) {
|
||||
return '<item class="meta-pay badg badg-sm mr6 ' . esc_attr($class) . '" data-toggle="tooltip" title="' . esc_attr($title) . '">' . $icon . esc_html((string) $data['resource_badge']) . '</item>';
|
||||
}
|
||||
$tooltip = $is_vip ? ' data-toggle="tooltip" title="' . esc_attr($title) . '"' : '';
|
||||
return '<a rel="nofollow" href="' . esc_url((string) $data['permalink']) . '#posts-pay"' . $tooltip . ' class="meta-pay but ' . esc_attr($is_vip ? $class : 'jb-yellow') . '">' . $icon . esc_html((string) $data['resource_badge']) . '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_vip_icon')) {
|
||||
function aksrt_renderer_vip_icon(int $level): string {
|
||||
if (!class_exists('\AKSRT\Settings\Settings')) {
|
||||
return '<i class="fas fa-crown mr3" aria-hidden="true"></i>';
|
||||
}
|
||||
$settings = \AKSRT\Settings\Settings::get_payment_vip_settings();
|
||||
$url = esc_url((string) ($settings['levels'][$level]['img_icon'] ?? ''));
|
||||
return $url !== ''
|
||||
? '<img class="mr3" src="' . $url . '" alt="" aria-hidden="true">'
|
||||
: '<i class="fas fa-crown mr3" aria-hidden="true"></i>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_badges')) {
|
||||
/**
|
||||
* Render taxonomy and resource badges.
|
||||
*
|
||||
* @param array<string,mixed> $data Collected post data.
|
||||
* @param array<string,mixed> $cfg Renderer config.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_badges(array $data, array $cfg): string {
|
||||
$items = [];
|
||||
|
||||
if (!empty($cfg['show_resource_badge']) && $data['resource_badge'] !== '') {
|
||||
$items[] = '<a href="' . esc_url($data['permalink']) . '#posts-pay" class="meta-pay but jb-yellow">' . esc_html($data['resource_badge']) . '</a>';
|
||||
}
|
||||
|
||||
if (!empty($cfg['show_badges']) && !empty($cfg['badge_show']) && $cfg['category_limit'] > 0) {
|
||||
foreach (array_slice($data['categories'], 0, $cfg['category_limit']) as $category) {
|
||||
$items[] = '<a href="' . esc_url(get_category_link($category->term_id)) . '" class="but"><i class="far fa-folder-open" aria-hidden="true"></i> ' . esc_html($category->name) . '</a>';
|
||||
$types = (array) ($cfg['badge_types'] ?? []);
|
||||
if (in_array('pay', $types, true)) {
|
||||
$pay = aksrt_renderer_pay_badge($data);
|
||||
if ($pay !== '') {
|
||||
$items[] = $pay;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($cfg['show_tags']) && $cfg['tag_limit'] > 0) {
|
||||
foreach (array_slice($data['tags'], 0, $cfg['tag_limit']) as $tag) {
|
||||
$items[] = '<a href="' . esc_url(get_tag_link($tag->term_id)) . '" class="but">#' . esc_html($tag->name) . '</a>';
|
||||
if (empty($cfg['is_category']) && in_array('cat', $types, true)) {
|
||||
$colors = ['c-blue', 'c-yellow', 'c-green', 'c-purple', 'c-red'];
|
||||
foreach (array_slice((array) $data['categories'], 0, 3) as $index => $category) {
|
||||
$items[] = '<a class="but ' . esc_attr($colors[$index % count($colors)]) . '" title="' . esc_attr__('查看更多分类文章', 'aksrt') . '" href="' . esc_url(get_category_link($category->term_id)) . '"><i class="fa fa-folder-open-o" aria-hidden="true"></i>' . esc_html($category->name) . '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['is_resource'])) {
|
||||
$items[] = '<span class="but jb-vip">VIP</span>';
|
||||
if (empty($cfg['is_tag']) && in_array('tag', $types, true)) {
|
||||
$tags = (array) $data['tags'];
|
||||
usort($tags, static fn($left, $right): int => (int) $right->count <=> (int) $left->count);
|
||||
foreach (array_slice($tags, 0, 3) as $tag) {
|
||||
$items[] = '<a class="but" title="' . esc_attr__('查看此标签更多文章', 'aksrt') . '" href="' . esc_url(get_tag_link($tag->term_id)) . '"># ' . esc_html($tag->name) . '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($items)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return '<div class="item-tags scroll-x no-scrollbar">' . implode('', $items) . '</div>';
|
||||
return $items ? '<div class="item-tags scroll-x no-scrollbar mb6">' . implode('', $items) . '</div>' : '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_resource_strip')) {
|
||||
/**
|
||||
* Render compact resource meta chips.
|
||||
*
|
||||
* @param array<string,mixed> $data Collected post data.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_resource_strip(array $data): string {
|
||||
if (empty($data['resource_strip']) || !is_array($data['resource_strip'])) {
|
||||
return '';
|
||||
}
|
||||
if (!function_exists('aksrt_renderer_meta_number')) {
|
||||
function aksrt_renderer_meta_number(int $number): string {
|
||||
return (string) aksrt_format_number($number);
|
||||
}
|
||||
}
|
||||
|
||||
$html = '<ul class="item-cms-strip">';
|
||||
foreach ($data['resource_strip'] as $item) {
|
||||
$html .= '<li>' . esc_html((string) $item) . '</li>';
|
||||
}
|
||||
$html .= '</ul>';
|
||||
|
||||
return $html;
|
||||
if (!function_exists('aksrt_renderer_svg_icon')) {
|
||||
function aksrt_renderer_svg_icon(string $name): string {
|
||||
return '<svg class="icon" aria-hidden="true"><use xlink:href="#icon-' . esc_attr($name) . '"></use></svg>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_renderer_meta')) {
|
||||
/**
|
||||
* Render the meta bar.
|
||||
*
|
||||
* @param array<string,mixed> $data Collected post data.
|
||||
* @param array<string,mixed> $cfg Renderer config.
|
||||
* @return string
|
||||
*/
|
||||
function aksrt_renderer_meta(array $data, array $cfg): string {
|
||||
if (!$cfg['show_meta']) {
|
||||
return '';
|
||||
function aksrt_renderer_meta(array $data, array $cfg, bool $is_card = false): string {
|
||||
$show_time = !empty($cfg['show_time']);
|
||||
$meta_left = '';
|
||||
if (empty($cfg['no_author']) && !empty($cfg['show_author'])) {
|
||||
$name = (!$is_card || !$show_time) && (string) $data['author_name'] !== ''
|
||||
? '<span class="' . ($show_time ? 'hide-sm ' : '') . 'ml6">' . esc_html((string) $data['author_name']) . '</span>'
|
||||
: '';
|
||||
$time = $show_time
|
||||
? '<span title="' . esc_attr((string) $data['time_title']) . '" class="' . ($is_card ? 'ml6' : 'icon-circle') . '">' . esc_html((string) $data['time_ago']) . '</span>'
|
||||
: '';
|
||||
$avatar = '<img class="avatar-mini" src="' . esc_url((string) $data['avatar_url']) . '" alt="" width="20" height="20">';
|
||||
$meta_left = '<item class="meta-author flex ac">' . $avatar . $name . $time . '</item>';
|
||||
} elseif ($show_time) {
|
||||
$meta_left = '<item title="' . esc_attr((string) $data['time_title']) . '" class="icon-circle mln3">' . esc_html((string) $data['time_ago']) . '</item>';
|
||||
}
|
||||
|
||||
$format_number = function_exists('aksrt_format_number') ? 'aksrt_format_number' : 'strval';
|
||||
|
||||
if ($cfg['mode'] === 'mini') {
|
||||
$items = [];
|
||||
if (!empty($cfg['show_date'])) {
|
||||
$items[] = '<span class="meta-item">' . esc_html($data['time_ago']) . '</span>';
|
||||
}
|
||||
if (!empty($cfg['show_views'])) {
|
||||
$items[] = '<span class="meta-item"><i class="fas fa-eye" aria-hidden="true"></i> ' . esc_html($format_number($data['views'])) . '</span>';
|
||||
}
|
||||
|
||||
if (empty($items)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return '<div class="item-meta">' . implode('<span class="meta-dot" aria-hidden="true"></span>', $items) . '</div>';
|
||||
$right = '';
|
||||
if (!empty($data['comments_open']) && empty($cfg['close_comments'])) {
|
||||
$right .= '<item class="meta-comm"><a rel="nofollow" data-toggle="tooltip" title="' . esc_attr__('去评论', 'aksrt') . '" href="' . esc_url((string) $data['comments_link']) . '">' . aksrt_renderer_svg_icon('comment') . esc_html((string) $data['comments']) . '</a></item>';
|
||||
}
|
||||
$right .= '<item class="meta-view">' . aksrt_renderer_svg_icon('view') . esc_html(aksrt_renderer_meta_number((int) $data['views'])) . '</item>';
|
||||
if (!empty($cfg['show_like']) && (string) ($data['post_type'] ?? '') === 'post') {
|
||||
$right .= '<item class="meta-like">' . aksrt_renderer_svg_icon('like') . esc_html(aksrt_renderer_meta_number((int) $data['likes'])) . '</item>';
|
||||
}
|
||||
|
||||
$left = [];
|
||||
if (!empty($cfg['show_author'])) {
|
||||
$left[] = '<item class="meta-author flex ac"><img' . aksrt_get_lazy_attr('lazy_avatar', (string) $data['avatar_url'], 'avatar-mini', aksrt_get_lazy_thumb('sm')) . ' alt="" width="20" height="20"><name class="meta-name">' . esc_html($data['author_name']) . '</name></item>';
|
||||
}
|
||||
if (!empty($cfg['show_date'])) {
|
||||
$left[] = '<item class="meta-time">' . esc_html($data['time_ago']) . '</item>';
|
||||
}
|
||||
|
||||
$right = [];
|
||||
if (!empty($cfg['show_comments'])) {
|
||||
$right[] = '<item class="meta-view"><i class="fas fa-comment" aria-hidden="true"></i> ' . esc_html((string) $data['comment_count']) . '</item>';
|
||||
}
|
||||
if (!empty($cfg['show_views'])) {
|
||||
$right[] = '<item class="meta-view"><i class="fas fa-eye" aria-hidden="true"></i> ' . esc_html($format_number($data['views'])) . '</item>';
|
||||
}
|
||||
if (!empty($cfg['show_likes'])) {
|
||||
$right[] = '<item class="meta-view"><i class="fas fa-thumbs-up" aria-hidden="true"></i> ' . esc_html($format_number($data['likes'])) . '</item>';
|
||||
}
|
||||
|
||||
if (empty($left) && empty($right)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$html = '<div class="item-meta muted-2-color flex jsb ac">';
|
||||
if (!empty($left)) {
|
||||
$html .= '<div class="meta-author-group flex ac">' . implode('<span class="meta-dot" aria-hidden="true"></span>', $left) . '</div>';
|
||||
}
|
||||
if (!empty($right)) {
|
||||
$html .= '<div class="meta-right">' . implode('', $right) . '</div>';
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
return '<div class="item-meta muted-2-color flex jsb ac">' . $meta_left . '<div class="meta-right">' . $right . '</div></div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,38 +24,51 @@ if (!function_exists('aksrt_render_pagination')) {
|
||||
* }
|
||||
*/
|
||||
function aksrt_render_pagination(?WP_Query $query = null, array $args = []): void {
|
||||
global $wp_query;
|
||||
$q = $query ?? $wp_query;
|
||||
if (!($q instanceof WP_Query)) {
|
||||
return;
|
||||
}
|
||||
$page_var = sanitize_key((string) ($args['page_var'] ?? 'paged')) ?: 'paged';
|
||||
$current_page = isset($args['current_page'])
|
||||
? max(1, (int) $args['current_page'])
|
||||
: max(1, (int) $q->get('paged'), (int) get_query_var('paged'), (int) get_query_var('page'));
|
||||
$max_pages = (int) $q->max_num_pages;
|
||||
|
||||
$pagination_mode = class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::get_post_pagination_mode()
|
||||
: 'numbered';
|
||||
|
||||
if ($pagination_mode === 'numbered') {
|
||||
global $wp_query;
|
||||
$q = $query ?? $wp_query;
|
||||
if (!($q instanceof WP_Query) || $q->max_num_pages <= 1) {
|
||||
if ($max_pages <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current_page = max(1, (int) $q->get('paged'), (int) get_query_var('paged'), (int) get_query_var('page'));
|
||||
$max_pages = (int) $q->max_num_pages;
|
||||
$links = paginate_links([
|
||||
$paginate_args = [
|
||||
'total' => $max_pages,
|
||||
'current' => $current_page,
|
||||
'mid_size' => 2,
|
||||
'prev_text' => '<span aria-hidden="true">‹</span>',
|
||||
'next_text' => '<span aria-hidden="true">›</span>',
|
||||
'type' => 'plain',
|
||||
]);
|
||||
];
|
||||
if ($page_var !== 'paged') {
|
||||
$big = 999999999;
|
||||
$paginate_args['base'] = str_replace((string) $big, '%#%', esc_url_raw(add_query_arg($page_var, $big)));
|
||||
$paginate_args['format'] = '';
|
||||
}
|
||||
$links = paginate_links($paginate_args);
|
||||
|
||||
if (empty($links)) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<div class="pagenav ajax-pag aksrt-pagination content-stream__footer-nav">';
|
||||
echo '<div class="pagenav ajax-pag" data-aksrt-pagination data-mode="numbered" data-page-var="' . esc_attr($page_var) . '" data-max-pages="' . esc_attr((string) $max_pages) . '">';
|
||||
echo wp_kses_post($links);
|
||||
if ($max_pages > 8) {
|
||||
echo '<span class="pag-jump">';
|
||||
echo '<input type="number" class="jump-input" min="1" max="' . esc_attr((string) $max_pages) . '" value="' . esc_attr((string) $current_page) . '" data-max-pages="' . esc_attr((string) $max_pages) . '" />';
|
||||
echo '<button type="button" class="ajax-next order-ajax-next" data-jump-archive="1">' . esc_html__('跳转', 'aksrt') . '</button>';
|
||||
echo '<button type="button" class="ajax-next order-ajax-next" data-jump-archive="1" data-page-var="' . esc_attr($page_var) . '">' . esc_html__('跳转', 'aksrt') . '</button>';
|
||||
echo '</span>';
|
||||
}
|
||||
echo '</div>';
|
||||
@@ -63,14 +76,6 @@ if (!function_exists('aksrt_render_pagination')) {
|
||||
}
|
||||
|
||||
// load_more / infinite 模式
|
||||
global $wp_query;
|
||||
$q = $query ?? $wp_query;
|
||||
if (!($q instanceof WP_Query)) {
|
||||
return;
|
||||
}
|
||||
$max_pages = (int) $q->max_num_pages;
|
||||
$current_page = max(1, (int) $q->get('paged'), (int) get_query_var('paged'), (int) get_query_var('page'));
|
||||
|
||||
if ($current_page >= $max_pages) {
|
||||
return;
|
||||
}
|
||||
@@ -95,29 +100,31 @@ if (!function_exists('aksrt_render_pagination')) {
|
||||
? $args['render_config']
|
||||
: [];
|
||||
|
||||
$trigger_text = __('加载更多', 'aksrt');
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
$list_settings = \AKSRT\Settings\Settings::get_post_list_style_settings();
|
||||
if (!empty($list_settings['ajax_trigger_text'])) {
|
||||
$trigger_text = (string) $list_settings['ajax_trigger_text'];
|
||||
}
|
||||
}
|
||||
?>
|
||||
<div class="text-center theme-pagination ajax-pag ajax-pagination aksrt-pagination-ajax content-stream__footer-nav"
|
||||
data-mode="<?php echo esc_attr($pagination_mode); ?>"
|
||||
data-next-page="<?php echo esc_attr((string) ($current_page + 1)); ?>"
|
||||
data-max-pages="<?php echo esc_attr((string) $max_pages); ?>"
|
||||
$trigger_text = __('加载更多', 'aksrt');
|
||||
$ias_max = 3;
|
||||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||||
$list_settings = \AKSRT\Settings\Settings::get_post_list_style_settings();
|
||||
if (!empty($list_settings['ajax_trigger'])) {
|
||||
$trigger_text = (string) $list_settings['ajax_trigger'];
|
||||
}
|
||||
$ias_max = max(0, (int) ($list_settings['ias_max'] ?? 3));
|
||||
}
|
||||
$auto_load = $pagination_mode === 'infinite' && ($ias_max === 0 || $current_page <= $ias_max);
|
||||
?>
|
||||
<div class="text-center theme-pagination ajax-pag"
|
||||
data-aksrt-pagination
|
||||
data-mode="<?php echo esc_attr($pagination_mode); ?>"
|
||||
data-next-page="<?php echo esc_attr((string) ($current_page + 1)); ?>"
|
||||
data-max-pages="<?php echo esc_attr((string) $max_pages); ?>"
|
||||
data-page-var="<?php echo esc_attr($page_var); ?>"
|
||||
data-query-context="<?php echo esc_attr($query_context); ?>"
|
||||
data-query-vars="<?php echo esc_attr(wp_json_encode($query_vars)); ?>"
|
||||
data-render-config="<?php echo esc_attr(wp_json_encode($render_config)); ?>">
|
||||
<div class="next-page ajax-next aksrt-load-more-btn<?php echo $pagination_mode === 'infinite' ? ' lazyload' : ''; ?>"<?php echo $pagination_mode === 'infinite' ? ' lazyload-action="ias"' : ''; ?> role="button" tabindex="0">
|
||||
<?php echo esc_html($trigger_text); ?>
|
||||
</div>
|
||||
<div class="aksrt-loading-indicator" style="display:none;" aria-hidden="true">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
<span><?php esc_html_e('加载中…', 'aksrt'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="next-page ajax-next<?php echo $auto_load ? ' lazyload' : ''; ?>"<?php echo $auto_load ? ' lazyload-action="ias"' : ''; ?>>
|
||||
<a href="<?php echo esc_url(add_query_arg($page_var, $current_page + 1)); ?>" data-aksrt-load-more><?php echo wp_kses_post($trigger_text); ?></a>
|
||||
</div>
|
||||
<div class="post_ajax_loader" style="display:none;" aria-hidden="true"><?php echo function_exists('aksrt_render_placeholder') ? aksrt_render_placeholder('list', 2) : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user