feat: rewrite schema-driven widget system
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace AKSRT\WidgetSystem\Renderers;
|
||||
|
||||
use AKSRT\WidgetSystem\PostRenderer;
|
||||
use AKSRT\WidgetSystem\RendererHelpers;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/** Render article discovery and paid-content widgets. */
|
||||
final class ContentRenderer {
|
||||
public static function render(string $slug, array $instance, array $context = []): string {
|
||||
switch ($slug) {
|
||||
case 'term_cards': return self::term_cards($instance);
|
||||
case 'term_aggregation': return self::term_aggregation($instance);
|
||||
case 'post_pay': return self::post_pay($instance);
|
||||
case 'tab_posts': return self::tab_posts($instance, $context);
|
||||
case 'posts':
|
||||
case 'hot_posts':
|
||||
case 'oneline_posts': return self::posts($slug, $instance, $context);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private static function terms(array $instance): array {
|
||||
$args = [
|
||||
'taxonomy' => (string) $instance['taxonomy'],
|
||||
'number' => (int) $instance['count'],
|
||||
'hide_empty' => true,
|
||||
'orderby' => 'count',
|
||||
'order' => 'DESC',
|
||||
];
|
||||
$ids = RendererHelpers::ids((string) $instance['term_ids']);
|
||||
if ($ids) {
|
||||
$args['include'] = $ids;
|
||||
$args['orderby'] = 'include';
|
||||
}
|
||||
$terms = get_terms($args);
|
||||
return is_wp_error($terms) ? [] : (array) $terms;
|
||||
}
|
||||
|
||||
private static function term_cards(array $instance): string {
|
||||
$terms = self::terms($instance);
|
||||
if (!$terms) {
|
||||
return RendererHelpers::empty_state(__('暂无分类', 'aksrt'));
|
||||
}
|
||||
$html = '<div class="aksrt-widget-grid aksrt-term-cards" style="--aksrt-cols:' . (int) $instance['pc_row'] . ';--aksrt-cols-m:' . (int) $instance['m_row'] . '">';
|
||||
foreach ($terms as $term) {
|
||||
$link = get_term_link($term);
|
||||
if (is_wp_error($link)) {
|
||||
continue;
|
||||
}
|
||||
$image = (string) get_term_meta((int) $term->term_id, 'aksrt_cover_url', true);
|
||||
if ($image === '') {
|
||||
$image = (string) get_term_meta((int) $term->term_id, 'cover_url', true);
|
||||
}
|
||||
$html .= '<a class="aksrt-term-card" href="' . esc_url($link) . '"><span class="aksrt-term-card__media">' . RendererHelpers::image($image, $term->name) . '</span><span class="aksrt-term-card__body"><strong>' . esc_html($term->name) . '</strong><small>' . esc_html(wp_trim_words((string) $term->description, 18)) . '</small><em>' . sprintf(esc_html__('%s 篇内容', 'aksrt'), number_format_i18n((int) $term->count)) . '</em></span></a>';
|
||||
}
|
||||
return $html . '</div>';
|
||||
}
|
||||
|
||||
private static function term_aggregation(array $instance): string {
|
||||
$terms = self::terms($instance);
|
||||
if (!$terms) {
|
||||
return RendererHelpers::empty_state(__('暂无聚合内容', 'aksrt'));
|
||||
}
|
||||
$taxonomy = (string) $instance['taxonomy'];
|
||||
$term_ids = array_map(static fn($term): int => (int) $term->term_id, $terms);
|
||||
$query = new \WP_Query([
|
||||
'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => min(100, count($terms) * 6),
|
||||
'ignore_sticky_posts' => true, 'no_found_rows' => true,
|
||||
'tax_query' => [['taxonomy' => $taxonomy, 'field' => 'term_id', 'terms' => $term_ids]],
|
||||
]);
|
||||
$by_term = [];
|
||||
foreach ($query->posts as $post) {
|
||||
foreach (wp_get_post_terms((int) $post->ID, $taxonomy, ['fields' => 'ids']) as $term_id) {
|
||||
if (in_array((int) $term_id, $term_ids, true) && count($by_term[$term_id] ?? []) < 4) {
|
||||
$by_term[$term_id][] = $post;
|
||||
}
|
||||
}
|
||||
}
|
||||
$html = '<div class="aksrt-term-aggregation">';
|
||||
foreach ($terms as $term) {
|
||||
$link = get_term_link($term);
|
||||
if (is_wp_error($link)) {
|
||||
continue;
|
||||
}
|
||||
$html .= '<section class="aksrt-term-aggregation__card"><header><a href="' . esc_url($link) . '"><strong>' . esc_html($term->name) . '</strong><span>' . esc_html__('查看全部', 'aksrt') . '</span></a></header><ul>';
|
||||
foreach ($by_term[$term->term_id] ?? [] as $post) {
|
||||
$html .= '<li><a href="' . esc_url(get_permalink($post)) . '">' . get_the_post_thumbnail($post, 'thumbnail') . '<span>' . esc_html(get_the_title($post)) . '</span></a></li>';
|
||||
}
|
||||
$html .= '</ul></section>';
|
||||
}
|
||||
return $html . '</div>';
|
||||
}
|
||||
|
||||
private static function posts(string $slug, array $instance, array $context): string {
|
||||
$widget_id = (string) ($context['widget_id'] ?? '');
|
||||
if (($instance['load_mode'] ?? 'sync') === 'ajax') {
|
||||
return '<div class="aksrt-widget-items is-loading" data-widget-items data-widget="' . esc_attr($slug) . '" data-instance="' . esc_attr($widget_id) . '" data-page="1"><div class="aksrt-widget-skeleton" aria-label="' . esc_attr__('正在加载', 'aksrt') . '"></div></div>';
|
||||
}
|
||||
$payload = PostRenderer::payload($instance, $slug, 1);
|
||||
return '<div class="aksrt-widget-items" data-widget-items data-widget="' . esc_attr($slug) . '" data-instance="' . esc_attr($widget_id) . '" data-page="1">' . $payload['html'] . $payload['paginate_html'] . '</div>';
|
||||
}
|
||||
|
||||
private static function tab_posts(array $instance, array $context): string {
|
||||
$tabs = array_values((array) $instance['tabs']);
|
||||
if (!$tabs) {
|
||||
return RendererHelpers::empty_state(__('请配置文章栏目', 'aksrt'));
|
||||
}
|
||||
$buttons = '';
|
||||
foreach ($tabs as $index => $tab) {
|
||||
$buttons .= '<button type="button" role="tab" aria-selected="' . ($index === 0 ? 'true' : 'false') . '" data-segment="' . $index . '">' . esc_html((string) ($tab['title'] ?? sprintf(__('栏目 %d', 'aksrt'), $index + 1))) . '</button>';
|
||||
}
|
||||
$payload = PostRenderer::payload($instance, 'tab_posts', 1, '0');
|
||||
return '<div class="aksrt-widget-tabs" data-widget="tab_posts" data-instance="' . esc_attr((string) ($context['widget_id'] ?? '')) . '"><div class="aksrt-widget-tabs__nav" role="tablist">' . $buttons . '</div><div class="aksrt-widget-tabs__panel" role="tabpanel" data-widget-items data-segment="0">' . $payload['html'] . $payload['paginate_html'] . '</div></div>';
|
||||
}
|
||||
|
||||
private static function post_pay(array $instance): string {
|
||||
$post = get_post();
|
||||
if (!$post instanceof \WP_Post || !function_exists('aksrt_get_pay_meta')) {
|
||||
return '';
|
||||
}
|
||||
$meta = aksrt_get_pay_meta($post);
|
||||
if (($meta['pay_type'] ?? 'no') === 'no') {
|
||||
return RendererHelpers::empty_state(__('当前文章未配置付费内容', 'aksrt'));
|
||||
}
|
||||
if (function_exists('aksrt_has_paid_access') && aksrt_has_paid_access($post)) {
|
||||
$html = '<div class="aksrt-post-pay is-authorized ' . esc_attr((string) $instance['theme']) . '"><i class="fas fa-check-circle" aria-hidden="true"></i><strong>' . esc_html__('内容已解锁', 'aksrt') . '</strong><p>' . esc_html__('你已拥有当前知识内容的访问权限。', 'aksrt') . '</p>';
|
||||
$html .= function_exists('aksrt_get_pay_attributes_html') ? aksrt_get_pay_attributes_html($post, 'aksrt-post-pay__attrs') : '';
|
||||
$html .= function_exists('aksrt_get_demo_link_html') ? aksrt_get_demo_link_html($post, 'aksrt-widget-button') : '';
|
||||
return $html . '</div>';
|
||||
}
|
||||
return function_exists('aksrt_get_paywall_html') ? aksrt_get_paywall_html($post, true) : RendererHelpers::empty_state(__('请登录或购买后查看', 'aksrt'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user