Board list, plate lists, topic terms and oneline posts no longer wrap static SSR in inert ajaxpager attributes without a real pager.
200 lines
8.5 KiB
PHP
200 lines
8.5 KiB
PHP
<?php
|
|
/**
|
|
* Forum Board List Widget (board taxonomy + plate CPT fallback).
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
namespace AKSRT\Widgets;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
class WidgetForumBoardList extends \WP_Widget {
|
|
|
|
public function __construct() {
|
|
parent::__construct(
|
|
'aksrt_forum_board_list',
|
|
__('论坛 - 版块列表', 'aksrt'),
|
|
['description' => __('显示论坛版块列表及话题数量。', 'aksrt')]
|
|
);
|
|
}
|
|
|
|
public static function render_html(array $instance): string {
|
|
$limit = max(1, min(50, (int) ($instance['count'] ?? $instance['showposts'] ?? 30)));
|
|
$orderby = sanitize_key((string) ($instance['orderby'] ?? 'menu_order'));
|
|
$style = sanitize_key((string) ($instance['style'] ?? 'list'));
|
|
if (!in_array($style, ['list', 'mini'], true)) {
|
|
$style = 'list';
|
|
}
|
|
|
|
// Prefer plate CPT (same as plate_lists lite).
|
|
if (post_type_exists('aksrt_forum_plate')) {
|
|
$query_args = [
|
|
'post_type' => 'aksrt_forum_plate',
|
|
'post_status' => 'publish',
|
|
'posts_per_page' => $limit,
|
|
'order' => 'ASC',
|
|
'no_found_rows' => true,
|
|
];
|
|
switch ($orderby) {
|
|
case 'posts':
|
|
$query_args['meta_key'] = '_aksrt_posts_count';
|
|
$query_args['orderby'] = 'meta_value_num';
|
|
$query_args['order'] = 'DESC';
|
|
break;
|
|
case 'views':
|
|
$query_args['meta_key'] = '_aksrt_views';
|
|
$query_args['orderby'] = 'meta_value_num';
|
|
$query_args['order'] = 'DESC';
|
|
break;
|
|
case 'date':
|
|
$query_args['orderby'] = 'date';
|
|
$query_args['order'] = 'DESC';
|
|
break;
|
|
default:
|
|
$query_args['orderby'] = 'menu_order title';
|
|
}
|
|
$plates = get_posts($query_args);
|
|
if ($plates) {
|
|
ob_start();
|
|
if ($style === 'mini' && function_exists('aksrt_render_plate_row')) {
|
|
// Compact mini still uses shared plate row for consistent DOM/lazy.
|
|
echo '<div class="plate-lists aksrt-forum-widget__boards style-mini ajax-item">';
|
|
foreach ($plates as $plate) {
|
|
echo aksrt_render_plate_row($plate); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
echo '</div>';
|
|
} elseif (function_exists('aksrt_render_plate_row')) {
|
|
echo '<div class="plate-lists aksrt-forum-widget__boards style-list ajax-item">';
|
|
foreach ($plates as $plate) {
|
|
echo aksrt_render_plate_row($plate); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
echo '</div>';
|
|
} else {
|
|
echo '<ul class="aksrt-forum-widget__boards style-' . esc_attr($style) . ' ajax-item">';
|
|
foreach ($plates as $plate) {
|
|
$icon = (string) get_post_meta($plate->ID, '_aksrt_icon', true);
|
|
$count = (int) get_post_meta($plate->ID, '_aksrt_posts_count', true);
|
|
$thumb = get_the_post_thumbnail_url($plate->ID, 'thumbnail');
|
|
$ph = get_template_directory_uri() . '/assets/img/placeholder.svg';
|
|
echo '<li class="aksrt-forum-widget__board">';
|
|
echo '<a href="' . esc_url(get_permalink($plate)) . '">';
|
|
if ($style === 'mini' && $thumb) {
|
|
echo '<img class="aksrt-forum-widget__thumb aksrt-lazy lazyload" data-src="' . esc_url($thumb) . '" src="' . esc_url($ph) . '" alt="" width="28" height="28" loading="lazy" />';
|
|
} elseif ($icon !== '') {
|
|
echo '<i class="' . esc_attr($icon) . '"></i> ';
|
|
}
|
|
echo '<span class="aksrt-forum-widget__name">' . esc_html(get_the_title($plate)) . '</span>';
|
|
echo '<span class="aksrt-forum-widget__count">' . esc_html((string) $count) . '</span>';
|
|
echo '</a></li>';
|
|
}
|
|
echo '</ul>';
|
|
}
|
|
return (string) ob_get_clean();
|
|
}
|
|
}
|
|
|
|
|
|
// Taxonomy fallback.
|
|
$term_args = [
|
|
'taxonomy' => 'aksrt_forum_board',
|
|
'hide_empty' => !isset($instance['hide_empty']) || !empty($instance['hide_empty']),
|
|
'number' => $limit,
|
|
'order' => 'ASC',
|
|
];
|
|
if ($orderby === 'count') {
|
|
$term_args['orderby'] = 'count';
|
|
$term_args['order'] = 'DESC';
|
|
} elseif ($orderby === 'name') {
|
|
$term_args['orderby'] = 'name';
|
|
} else {
|
|
$term_args['orderby'] = 'meta_value_num';
|
|
$term_args['meta_key'] = '_aksrt_sort_order';
|
|
}
|
|
$boards = get_terms($term_args);
|
|
if (is_wp_error($boards) || empty($boards)) {
|
|
return function_exists('aksrt_get_ajax_null')
|
|
? aksrt_get_ajax_null(__('暂无版块', 'aksrt'))
|
|
: '<p class="aksrt-forum-widget__empty ajax-item">' . esc_html__('暂无版块', 'aksrt') . '</p>';
|
|
}
|
|
ob_start();
|
|
echo '<ul class="aksrt-forum-widget__boards style-' . esc_attr($style) . ' ajax-item">';
|
|
foreach ($boards as $board) {
|
|
$icon = get_term_meta($board->term_id, '_aksrt_icon', true);
|
|
echo '<li class="aksrt-forum-widget__board">';
|
|
echo '<a href="' . esc_url(get_term_link($board)) . '">';
|
|
if ($icon) {
|
|
echo '<i class="' . esc_attr($icon) . '"></i> ';
|
|
}
|
|
echo '<span class="aksrt-forum-widget__name">' . esc_html($board->name) . '</span>';
|
|
echo '<span class="aksrt-forum-widget__count">' . esc_html((string) (int) $board->count) . '</span>';
|
|
echo '</a></li>';
|
|
}
|
|
echo '</ul>';
|
|
return (string) ob_get_clean();
|
|
}
|
|
|
|
public function widget($args, $instance): void {
|
|
$title = !empty($instance['title']) ? $instance['title'] : __('版块列表', 'aksrt');
|
|
$html = self::render_html($instance);
|
|
|
|
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
|
|
public function form($instance): void {
|
|
$title = !empty($instance['title']) ? $instance['title'] : __('版块列表', 'aksrt');
|
|
?>
|
|
<p>
|
|
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php esc_html_e('标题:', 'aksrt'); ?></label>
|
|
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>" name="<?php echo esc_attr($this->get_field_name('title')); ?>" type="text" value="<?php echo esc_attr($title); ?>">
|
|
</p>
|
|
<p>
|
|
<label><?php esc_html_e('数量', 'aksrt'); ?>
|
|
<input class="tiny-text" type="number" min="1" max="50" name="<?php echo esc_attr($this->get_field_name('count')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['count'] ?? 30))); ?>">
|
|
</label>
|
|
</p>
|
|
<p>
|
|
<label><?php esc_html_e('排序', 'aksrt'); ?>
|
|
<select name="<?php echo esc_attr($this->get_field_name('orderby')); ?>">
|
|
<option value="menu_order" <?php selected(($instance['orderby'] ?? 'menu_order'), 'menu_order'); ?>><?php esc_html_e('菜单顺序', 'aksrt'); ?></option>
|
|
<option value="posts" <?php selected(($instance['orderby'] ?? ''), 'posts'); ?>><?php esc_html_e('帖子数', 'aksrt'); ?></option>
|
|
<option value="views" <?php selected(($instance['orderby'] ?? ''), 'views'); ?>><?php esc_html_e('浏览量', 'aksrt'); ?></option>
|
|
<option value="date" <?php selected(($instance['orderby'] ?? ''), 'date'); ?>><?php esc_html_e('创建时间', 'aksrt'); ?></option>
|
|
<option value="name" <?php selected(($instance['orderby'] ?? ''), 'name'); ?>><?php esc_html_e('名称', 'aksrt'); ?></option>
|
|
<option value="count" <?php selected(($instance['orderby'] ?? ''), 'count'); ?>><?php esc_html_e('分类计数', 'aksrt'); ?></option>
|
|
</select>
|
|
</label>
|
|
</p>
|
|
<p>
|
|
<label><?php esc_html_e('样式', 'aksrt'); ?>
|
|
<select name="<?php echo esc_attr($this->get_field_name('style')); ?>">
|
|
<option value="list" <?php selected(($instance['style'] ?? 'list'), 'list'); ?>><?php esc_html_e('列表', 'aksrt'); ?></option>
|
|
<option value="mini" <?php selected(($instance['style'] ?? ''), 'mini'); ?>><?php esc_html_e('迷你图', 'aksrt'); ?></option>
|
|
</select>
|
|
</label>
|
|
</p>
|
|
<p>
|
|
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('hide_empty')); ?>" value="1" <?php checked(!isset($instance['hide_empty']) || !empty($instance['hide_empty'])); ?>> <?php esc_html_e('隐藏空版块(分类模式)', 'aksrt'); ?></label>
|
|
</p>
|
|
<?php
|
|
}
|
|
|
|
public function update($new_instance, $old_instance): array {
|
|
$orderby = sanitize_key((string) ($new_instance['orderby'] ?? 'menu_order'));
|
|
$allowed = ['menu_order', 'posts', 'views', 'date', 'name', 'count'];
|
|
if (!in_array($orderby, $allowed, true)) {
|
|
$orderby = 'menu_order';
|
|
}
|
|
return [
|
|
'title' => sanitize_text_field($new_instance['title'] ?? ''),
|
|
'count' => max(1, min(50, (int) ($new_instance['count'] ?? 30))),
|
|
'orderby' => $orderby,
|
|
'style' => ($new_instance['style'] ?? '') === 'mini' ? 'mini' : 'list',
|
|
'hide_empty' => !empty($new_instance['hide_empty']) ? 1 : 0,
|
|
];
|
|
}
|
|
}
|