feat(forum): plate info follow/compose + mods grid + board depth
Sidebar plate widgets gain follow/compose actions, super-mod roles, board list sorting/styles, and matching CSS polish.
This commit is contained in:
1 parent
2dd3b33cb7
commit
2396ca98fb
4 files changed
+424
-149
No files matched your search
@@ -787,3 +787,99 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- batch9: plate info actions / mods grid / board list / term polish ---- */
|
||||||
|
.aksrt-plate-info__cover.is-icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 32px;
|
||||||
|
color: var(--color-primary, #3b82f6);
|
||||||
|
background: linear-gradient(135deg, #eff6ff, #f5f3ff);
|
||||||
|
}
|
||||||
|
.aksrt-plate-info__actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
.aksrt-plate-info__btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 999px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
.aksrt-plate-info__follow {
|
||||||
|
background: #ef4444;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
.aksrt-plate-info__follow.is-followed {
|
||||||
|
background: var(--surface-2, #e5e7eb);
|
||||||
|
color: inherit !important;
|
||||||
|
}
|
||||||
|
.aksrt-plate-info__compose {
|
||||||
|
background: var(--color-primary, #3b82f6);
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aksrt-plate-mods.style-grid .aksrt-plate-mods__list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
.aksrt-plate-mods.style-grid .aksrt-plate-mods__item {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
.aksrt-plate-mods.style-grid .aksrt-plate-mods__name {
|
||||||
|
font-size: 12px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.aksrt-plate-mods.style-grid .aksrt-plate-mods__role {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
.aksrt-plate-mods__item.role-author .aksrt-plate-mods__role,
|
||||||
|
.aksrt-plate-mods__item.role-super .aksrt-plate-mods__role {
|
||||||
|
color: #b45309;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aksrt-forum-widget__boards .aksrt-forum-widget__name {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.aksrt-forum-widget__boards .aksrt-forum-widget__count {
|
||||||
|
margin-left: 8px;
|
||||||
|
color: var(--muted-2-color, #999);
|
||||||
|
font-size: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.aksrt-forum-widget__boards.style-mini .aksrt-forum-widget__board a {
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.aksrt-forum-widget__thumb {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 6px;
|
||||||
|
object-fit: cover;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aksrt-tag-cloud .c-blue-2 { background: #bfdbfe; color: #1e40af; }
|
||||||
|
.aksrt-tag-cloud .c-green-2 { background: #bbf7d0; color: #166534; }
|
||||||
|
.aksrt-tag-cloud .c-yellow-2 { background: #fde68a; color: #92400e; }
|
||||||
|
.aksrt-tag-cloud .c-purple-2 { background: #ddd6fe; color: #5b21b6; }
|
||||||
|
.aksrt-tag-cloud .c-red-2 { background: #fecaca; color: #991b1b; }
|
||||||
|
|
||||||
|
.aksrt-home-widget__ajax .ajax-pag { margin-top: 12px; text-align: center; }
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
|
* Forum Board List Widget (board taxonomy + plate CPT fallback).
|
||||||
|
*
|
||||||
* @package AKSRT
|
* @package AKSRT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -7,97 +9,174 @@ namespace AKSRT\Widgets;
|
|||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/**
|
|
||||||
* Forum Board List Widget
|
|
||||||
*/
|
|
||||||
class WidgetForumBoardList extends \WP_Widget {
|
class WidgetForumBoardList extends \WP_Widget {
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
parent::__construct(
|
parent::__construct(
|
||||||
'aksrt_forum_board_list',
|
'aksrt_forum_board_list',
|
||||||
__('论坛 - 版块列表', 'aksrt'),
|
__('论坛 - 版块列表', 'aksrt'),
|
||||||
['description' => __('显示论坛版块列表及话题数量。', 'aksrt')]
|
['description' => __('显示论坛版块列表及话题数量。', 'aksrt')]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function widget($args, $instance): void {
|
public static function render_html(array $instance): string {
|
||||||
$title = !empty($instance['title']) ? $instance['title'] : __('版块列表', 'aksrt');
|
$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';
|
||||||
|
}
|
||||||
|
|
||||||
echo $args['before_widget'];
|
// Prefer plate CPT (same as plate_lists lite).
|
||||||
echo $args['before_title'] . esc_html($title) . $args['after_title'];
|
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();
|
||||||
|
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');
|
||||||
|
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" src="' . esc_url($thumb) . '" 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$rendered = false;
|
// Taxonomy fallback.
|
||||||
if (post_type_exists('aksrt_forum_plate')) {
|
$term_args = [
|
||||||
$plates = get_posts([
|
'taxonomy' => 'aksrt_forum_board',
|
||||||
'post_type' => 'aksrt_forum_plate',
|
'hide_empty' => !isset($instance['hide_empty']) || !empty($instance['hide_empty']),
|
||||||
'post_status' => 'publish',
|
'number' => $limit,
|
||||||
'posts_per_page' => 30,
|
'order' => 'ASC',
|
||||||
'orderby' => 'menu_order title',
|
];
|
||||||
'order' => 'ASC',
|
if ($orderby === 'count') {
|
||||||
]);
|
$term_args['orderby'] = 'count';
|
||||||
if ($plates) {
|
$term_args['order'] = 'DESC';
|
||||||
$rendered = true;
|
} elseif ($orderby === 'name') {
|
||||||
echo '<ul class="aksrt-forum-widget__boards">';
|
$term_args['orderby'] = 'name';
|
||||||
foreach ($plates as $plate) {
|
} else {
|
||||||
$icon = (string) get_post_meta($plate->ID, '_aksrt_icon', true);
|
$term_args['orderby'] = 'meta_value_num';
|
||||||
$count = (int) get_post_meta($plate->ID, '_aksrt_posts_count', true);
|
$term_args['meta_key'] = '_aksrt_sort_order';
|
||||||
echo '<li class="aksrt-forum-widget__board">';
|
}
|
||||||
echo '<a href="' . esc_url(get_permalink($plate)) . '">';
|
$boards = get_terms($term_args);
|
||||||
if ($icon !== '') {
|
if (is_wp_error($boards) || empty($boards)) {
|
||||||
echo '<i class="' . esc_attr($icon) . '"></i> ';
|
return function_exists('aksrt_get_ajax_null')
|
||||||
}
|
? aksrt_get_ajax_null(__('暂无版块', 'aksrt'))
|
||||||
echo esc_html(get_the_title($plate));
|
: '<p class="aksrt-forum-widget__empty ajax-item">' . esc_html__('暂无版块', 'aksrt') . '</p>';
|
||||||
echo '<span class="aksrt-forum-widget__count">' . $count . '</span>';
|
}
|
||||||
echo '</a>';
|
ob_start();
|
||||||
echo '</li>';
|
echo '<ul class="aksrt-forum-widget__boards style-' . esc_attr($style) . ' ajax-item">';
|
||||||
}
|
foreach ($boards as $board) {
|
||||||
echo '</ul>';
|
$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 (!$rendered) {
|
if ($icon) {
|
||||||
$boards = get_terms([
|
echo '<i class="' . esc_attr($icon) . '"></i> ';
|
||||||
'taxonomy' => 'aksrt_forum_board',
|
}
|
||||||
'hide_empty' => true,
|
echo '<span class="aksrt-forum-widget__name">' . esc_html($board->name) . '</span>';
|
||||||
'orderby' => 'meta_value_num',
|
echo '<span class="aksrt-forum-widget__count">' . esc_html((string) (int) $board->count) . '</span>';
|
||||||
'meta_key' => '_aksrt_sort_order',
|
echo '</a></li>';
|
||||||
'order' => 'ASC',
|
}
|
||||||
]);
|
echo '</ul>';
|
||||||
if (!is_wp_error($boards) && !empty($boards)) {
|
return (string) ob_get_clean();
|
||||||
echo '<ul class="aksrt-forum-widget__boards">';
|
}
|
||||||
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 esc_html($board->name);
|
|
||||||
echo '<span class="aksrt-forum-widget__count">' . (int) $board->count . '</span>';
|
|
||||||
echo '</a>';
|
|
||||||
echo '</li>';
|
|
||||||
}
|
|
||||||
echo '</ul>';
|
|
||||||
} else {
|
|
||||||
echo '<p class="aksrt-forum-widget__empty">' . esc_html__('暂无版块', 'aksrt') . '</p>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
echo $args['after_widget'];
|
public function widget($args, $instance): void {
|
||||||
}
|
$title = !empty($instance['title']) ? $instance['title'] : __('版块列表', 'aksrt');
|
||||||
|
$html = self::render_html($instance);
|
||||||
|
|
||||||
public function form($instance): void {
|
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
$title = !empty($instance['title']) ? $instance['title'] : __('版块列表', 'aksrt');
|
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
?>
|
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
<p>
|
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
<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>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($new_instance, $old_instance): array {
|
public function form($instance): void {
|
||||||
$instance = [];
|
$title = !empty($instance['title']) ? $instance['title'] : __('版块列表', 'aksrt');
|
||||||
$instance['title'] = sanitize_text_field($new_instance['title'] ?? '');
|
?>
|
||||||
return $instance;
|
<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,
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -22,41 +22,96 @@ class WidgetForumPlateInfo extends \WP_Widget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function widget($args, $instance): void {
|
/**
|
||||||
$plate = $this->resolve_current_plate();
|
* @return array{html:string}
|
||||||
|
*/
|
||||||
|
public static function render_payload(array $instance, ?\WP_Post $plate = null): array {
|
||||||
|
$plate = $plate ?: self::resolve_current_plate_static();
|
||||||
if (!$plate) {
|
if (!$plate) {
|
||||||
return;
|
return ['html' => ''];
|
||||||
}
|
}
|
||||||
|
|
||||||
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
$show_follow = !isset($instance['show_follow']) || !empty($instance['show_follow']);
|
||||||
|
$show_compose = !isset($instance['show_compose']) || !empty($instance['show_compose']);
|
||||||
|
$show_stats = !isset($instance['show_stats']) || !empty($instance['show_stats']);
|
||||||
|
|
||||||
$id = (int) $plate->ID;
|
$id = (int) $plate->ID;
|
||||||
$url = get_permalink($id);
|
$url = get_permalink($id);
|
||||||
$thumb = get_the_post_thumbnail_url($id, 'medium');
|
$thumb = get_the_post_thumbnail_url($id, 'medium');
|
||||||
$posts = (int) get_post_meta($id, '_aksrt_posts_count', true);
|
$posts = (int) get_post_meta($id, '_aksrt_posts_count', true);
|
||||||
$reply = (int) get_post_meta($id, '_aksrt_reply_count', true);
|
$reply = (int) get_post_meta($id, '_aksrt_reply_count', true);
|
||||||
$follow = (int) get_post_meta($id, '_aksrt_follow_count', true);
|
$follow = (int) get_post_meta($id, '_aksrt_follow_count', true);
|
||||||
$desc = $plate->post_excerpt !== '' ? $plate->post_excerpt : wp_trim_words(wp_strip_all_tags($plate->post_content), 30);
|
$views = (int) get_post_meta($id, '_aksrt_views', true);
|
||||||
|
$desc = $plate->post_excerpt !== '' ? $plate->post_excerpt : wp_trim_words(wp_strip_all_tags($plate->post_content), 30);
|
||||||
|
$icon = (string) get_post_meta($id, '_aksrt_icon', true);
|
||||||
|
|
||||||
echo '<div class="aksrt-plate-info">';
|
$forum = class_exists('\AKSRT\Forum\Forum') ? \AKSRT\Forum\Forum::get_instance() : null;
|
||||||
|
$uid = get_current_user_id();
|
||||||
|
$is_followed = $forum && $uid > 0 ? $forum->is_user_following_plate($uid, $id) : false;
|
||||||
|
|
||||||
|
$compose_url = function_exists('aksrt_get_forum_compose_url')
|
||||||
|
? aksrt_get_forum_compose_url(['board' => $id])
|
||||||
|
: home_url('/');
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
echo '<div class="aksrt-plate-info ajax-item">';
|
||||||
if ($thumb) {
|
if ($thumb) {
|
||||||
echo '<div class="aksrt-plate-info__cover" style="background-image:url(' . esc_url($thumb) . ')"></div>';
|
echo '<div class="aksrt-plate-info__cover" style="background-image:url(' . esc_url($thumb) . ')"></div>';
|
||||||
|
} elseif ($icon !== '') {
|
||||||
|
echo '<div class="aksrt-plate-info__cover is-icon"><i class="' . esc_attr($icon) . '" aria-hidden="true"></i></div>';
|
||||||
}
|
}
|
||||||
echo '<div class="aksrt-plate-info__body">';
|
echo '<div class="aksrt-plate-info__body">';
|
||||||
echo '<a class="aksrt-plate-info__title" href="' . esc_url($url) . '">' . esc_html(get_the_title($plate)) . '</a>';
|
echo '<a class="aksrt-plate-info__title" href="' . esc_url($url) . '">' . esc_html(get_the_title($plate)) . '</a>';
|
||||||
if ($desc !== '') {
|
if ($desc !== '') {
|
||||||
echo '<div class="aksrt-plate-info__desc">' . esc_html($desc) . '</div>';
|
echo '<div class="aksrt-plate-info__desc">' . esc_html($desc) . '</div>';
|
||||||
}
|
}
|
||||||
echo '<div class="aksrt-plate-info__stats">';
|
if ($show_stats) {
|
||||||
echo '<span><i class="fas fa-file-alt" aria-hidden="true"></i> ' . esc_html((string) $posts) . '</span>';
|
echo '<div class="aksrt-plate-info__stats">';
|
||||||
echo '<span><i class="fas fa-comment" aria-hidden="true"></i> ' . esc_html((string) $reply) . '</span>';
|
echo '<span title="' . esc_attr__('帖子', 'aksrt') . '"><i class="fas fa-file-alt" aria-hidden="true"></i> ' . esc_html((string) $posts) . '</span>';
|
||||||
echo '<span><i class="fas fa-heart" aria-hidden="true"></i> ' . esc_html((string) $follow) . '</span>';
|
echo '<span title="' . esc_attr__('回复', 'aksrt') . '"><i class="fas fa-comment" aria-hidden="true"></i> ' . esc_html((string) $reply) . '</span>';
|
||||||
echo '</div></div></div>';
|
if ($views > 0) {
|
||||||
|
echo '<span title="' . esc_attr__('浏览', 'aksrt') . '"><i class="fas fa-eye" aria-hidden="true"></i> ' . esc_html((string) $views) . '</span>';
|
||||||
|
}
|
||||||
|
echo '<span title="' . esc_attr__('关注', 'aksrt') . '"><i class="fas fa-heart" aria-hidden="true"></i> ' . esc_html((string) $follow) . '</span>';
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$actions = [];
|
||||||
|
if ($show_follow && $uid > 0) {
|
||||||
|
$actions[] = sprintf(
|
||||||
|
'<button type="button" class="aksrt-plate-info__btn aksrt-plate-info__follow js-aksrt-follow-plate%s" data-plate-id="%d" data-followed="%s"><i class="fas fa-heart" aria-hidden="true"></i> %s</button>',
|
||||||
|
$is_followed ? ' is-followed' : '',
|
||||||
|
$id,
|
||||||
|
$is_followed ? '1' : '0',
|
||||||
|
esc_html($is_followed ? __('已关注', 'aksrt') : __('关注', 'aksrt'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($show_compose) {
|
||||||
|
$actions[] = '<a class="aksrt-plate-info__btn aksrt-plate-info__compose" href="' . esc_url($compose_url) . '"><i class="fas fa-pen" aria-hidden="true"></i> ' . esc_html__('发帖', 'aksrt') . '</a>';
|
||||||
|
}
|
||||||
|
if ($actions) {
|
||||||
|
echo '<div class="aksrt-plate-info__actions">' . implode('', $actions) . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
}
|
||||||
|
echo '</div></div>';
|
||||||
|
return ['html' => (string) ob_get_clean()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function widget($args, $instance): void {
|
||||||
|
$payload = self::render_payload($instance);
|
||||||
|
if ($payload['html'] === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
$title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base);
|
||||||
|
if ($title !== '') {
|
||||||
|
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
}
|
||||||
|
echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolve_current_plate(): ?\WP_Post {
|
public static function resolve_current_plate_static(): ?\WP_Post {
|
||||||
if (is_singular('aksrt_forum_plate')) {
|
if (is_singular('aksrt_forum_plate')) {
|
||||||
$p = get_queried_object();
|
$p = get_queried_object();
|
||||||
return $p instanceof \WP_Post ? $p : null;
|
return $p instanceof \WP_Post ? $p : null;
|
||||||
@@ -65,7 +120,6 @@ class WidgetForumPlateInfo extends \WP_Widget {
|
|||||||
$topic_id = (int) get_queried_object_id();
|
$topic_id = (int) get_queried_object_id();
|
||||||
$plate_id = (int) get_post_meta($topic_id, '_aksrt_plate_id', true);
|
$plate_id = (int) get_post_meta($topic_id, '_aksrt_plate_id', true);
|
||||||
if ($plate_id <= 0) {
|
if ($plate_id <= 0) {
|
||||||
// Fallback: first linked board term → plate meta, or parent.
|
|
||||||
$boards = get_the_terms($topic_id, 'aksrt_forum_board');
|
$boards = get_the_terms($topic_id, 'aksrt_forum_board');
|
||||||
if (!is_wp_error($boards) && !empty($boards[0])) {
|
if (!is_wp_error($boards) && !empty($boards[0])) {
|
||||||
$linked = (int) get_term_meta((int) $boards[0]->term_id, '_aksrt_plate_id', true);
|
$linked = (int) get_term_meta((int) $boards[0]->term_id, '_aksrt_plate_id', true);
|
||||||
@@ -84,11 +138,32 @@ class WidgetForumPlateInfo extends \WP_Widget {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function resolve_current_plate(): ?\WP_Post {
|
||||||
|
return self::resolve_current_plate_static();
|
||||||
|
}
|
||||||
|
|
||||||
public function form($instance): void {
|
public function form($instance): void {
|
||||||
echo '<p class="description">' . esc_html__('无需配置。仅在版块页或帖子页显示对应版块信息。', 'aksrt') . '</p>';
|
?>
|
||||||
|
<p>
|
||||||
|
<label><?php esc_html_e('标题(可选)', 'aksrt'); ?>
|
||||||
|
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('title')); ?>" value="<?php echo esc_attr((string) ($instance['title'] ?? '')); ?>">
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_stats')); ?>" value="1" <?php checked(!isset($instance['show_stats']) || !empty($instance['show_stats'])); ?>> <?php esc_html_e('显示统计', 'aksrt'); ?></label><br>
|
||||||
|
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_follow')); ?>" value="1" <?php checked(!isset($instance['show_follow']) || !empty($instance['show_follow'])); ?>> <?php esc_html_e('显示关注按钮', 'aksrt'); ?></label><br>
|
||||||
|
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_compose')); ?>" value="1" <?php checked(!isset($instance['show_compose']) || !empty($instance['show_compose'])); ?>> <?php esc_html_e('显示发帖按钮', 'aksrt'); ?></label>
|
||||||
|
</p>
|
||||||
|
<p class="description"><?php esc_html_e('仅在版块页或帖子页显示对应版块信息。', 'aksrt'); ?></p>
|
||||||
|
<?php
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update($new_instance, $old_instance): array {
|
public function update($new_instance, $old_instance): array {
|
||||||
return [];
|
return [
|
||||||
|
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
|
||||||
|
'show_stats' => !empty($new_instance['show_stats']) ? 1 : 0,
|
||||||
|
'show_follow' => !empty($new_instance['show_follow']) ? 1 : 0,
|
||||||
|
'show_compose' => !empty($new_instance['show_compose']) ? 1 : 0,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,45 +22,65 @@ class WidgetForumPlateModerator extends \WP_Widget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function widget($args, $instance): void {
|
/**
|
||||||
$plate = $this->resolve_current_plate();
|
* @return array{html:string}
|
||||||
|
*/
|
||||||
|
public static function render_payload(array $instance, ?\WP_Post $plate = null): array {
|
||||||
|
$plate = $plate ?: WidgetForumPlateInfo::resolve_current_plate_static();
|
||||||
if (!$plate) {
|
if (!$plate) {
|
||||||
return;
|
return ['html' => ''];
|
||||||
}
|
}
|
||||||
|
|
||||||
$id = (int) $plate->ID;
|
$id = (int) $plate->ID;
|
||||||
$author_id = (int) $plate->post_author;
|
$author_id = (int) $plate->post_author;
|
||||||
$mods = get_post_meta($id, '_aksrt_moderators', true);
|
$mods = get_post_meta($id, '_aksrt_moderators', true);
|
||||||
if (!is_array($mods)) {
|
if (!is_array($mods)) {
|
||||||
$mods = [];
|
$mods = [];
|
||||||
}
|
}
|
||||||
$mods = array_values(array_unique(array_filter(array_map('intval', $mods))));
|
$mods = array_values(array_unique(array_filter(array_map('intval', $mods))));
|
||||||
|
|
||||||
|
// Super-mods meta (zibll-like).
|
||||||
|
$super = get_post_meta($id, '_aksrt_super_moderators', true);
|
||||||
|
if (!is_array($super)) {
|
||||||
|
$super = [];
|
||||||
|
}
|
||||||
|
$super = array_values(array_unique(array_filter(array_map('intval', $super))));
|
||||||
|
|
||||||
$people = [];
|
$people = [];
|
||||||
if ($author_id > 0) {
|
if ($author_id > 0) {
|
||||||
$people[] = ['id' => $author_id, 'role' => 'author'];
|
$people[] = ['id' => $author_id, 'role' => 'author'];
|
||||||
}
|
}
|
||||||
|
foreach ($super as $sid) {
|
||||||
|
if ($sid === $author_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$people[] = ['id' => $sid, 'role' => 'super'];
|
||||||
|
}
|
||||||
foreach ($mods as $mid) {
|
foreach ($mods as $mid) {
|
||||||
if ($mid === $author_id) {
|
if ($mid === $author_id || in_array($mid, $super, true)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$people[] = ['id' => $mid, 'role' => 'moderator'];
|
$people[] = ['id' => $mid, 'role' => 'moderator'];
|
||||||
}
|
}
|
||||||
if (!$people) {
|
if (!$people) {
|
||||||
return;
|
return ['html' => ''];
|
||||||
}
|
}
|
||||||
|
|
||||||
$title_text = (string) ($instance['title_text'] ?? __('版主', 'aksrt'));
|
$title_text = (string) ($instance['title_text'] ?? __('版主', 'aksrt'));
|
||||||
|
$show_avatar = !isset($instance['show_avatar']) || !empty($instance['show_avatar']);
|
||||||
|
$style = sanitize_key((string) ($instance['style'] ?? 'list'));
|
||||||
|
if (!in_array($style, ['list', 'grid'], true)) {
|
||||||
|
$style = 'list';
|
||||||
|
}
|
||||||
|
|
||||||
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
ob_start();
|
||||||
|
echo '<div class="aksrt-plate-mods style-' . esc_attr($style) . ' ajax-item">';
|
||||||
echo '<div class="aksrt-plate-mods">';
|
|
||||||
if ($title_text !== '') {
|
if ($title_text !== '') {
|
||||||
echo '<div class="aksrt-plate-mods__head"><div class="title-theme">' . esc_html($title_text) . '</div></div>';
|
echo '<div class="aksrt-plate-mods__head"><div class="title-theme">' . esc_html($title_text) . '</div></div>';
|
||||||
}
|
}
|
||||||
echo '<div class="aksrt-plate-mods__list">';
|
echo '<div class="aksrt-plate-mods__list">';
|
||||||
foreach ($people as $row) {
|
foreach ($people as $row) {
|
||||||
$uid = (int) $row['id'];
|
$uid = (int) $row['id'];
|
||||||
$user = get_userdata($uid);
|
$user = get_userdata($uid);
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
continue;
|
continue;
|
||||||
@@ -71,61 +91,66 @@ class WidgetForumPlateModerator extends \WP_Widget {
|
|||||||
$home = function_exists('aksrt_get_user_home_url')
|
$home = function_exists('aksrt_get_user_home_url')
|
||||||
? aksrt_get_user_home_url($uid)
|
? aksrt_get_user_home_url($uid)
|
||||||
: get_author_posts_url($uid);
|
: get_author_posts_url($uid);
|
||||||
$role_label = $row['role'] === 'author'
|
if ($row['role'] === 'author' || $row['role'] === 'super') {
|
||||||
? __('超级版主', 'aksrt')
|
$role_label = __('超级版主', 'aksrt');
|
||||||
: __('版主', 'aksrt');
|
} else {
|
||||||
echo '<a class="aksrt-plate-mods__item" href="' . esc_url($home) . '">';
|
$role_label = __('版主', 'aksrt');
|
||||||
echo '<img src="' . esc_url($avatar) . '" alt="" class="aksrt-plate-mods__avatar" loading="lazy" width="40" height="40" />';
|
}
|
||||||
|
echo '<a class="aksrt-plate-mods__item role-' . esc_attr($row['role']) . '" href="' . esc_url($home) . '">';
|
||||||
|
if ($show_avatar) {
|
||||||
|
echo '<img src="' . esc_url($avatar) . '" alt="" class="aksrt-plate-mods__avatar" loading="lazy" width="40" height="40" />';
|
||||||
|
}
|
||||||
echo '<span class="aksrt-plate-mods__name">' . esc_html($user->display_name) . '</span>';
|
echo '<span class="aksrt-plate-mods__name">' . esc_html($user->display_name) . '</span>';
|
||||||
echo '<span class="aksrt-plate-mods__role">' . esc_html($role_label) . '</span>';
|
echo '<span class="aksrt-plate-mods__role">' . esc_html($role_label) . '</span>';
|
||||||
echo '</a>';
|
echo '</a>';
|
||||||
}
|
}
|
||||||
echo '</div></div>';
|
echo '</div></div>';
|
||||||
|
return ['html' => (string) ob_get_clean()];
|
||||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolve_current_plate(): ?\WP_Post {
|
public function widget($args, $instance): void {
|
||||||
if (is_singular('aksrt_forum_plate')) {
|
$payload = self::render_payload($instance);
|
||||||
$p = get_queried_object();
|
if ($payload['html'] === '') {
|
||||||
return $p instanceof \WP_Post ? $p : null;
|
return;
|
||||||
}
|
}
|
||||||
if (is_singular('aksrt_forum_topic')) {
|
|
||||||
$topic_id = (int) get_queried_object_id();
|
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
$plate_id = (int) get_post_meta($topic_id, '_aksrt_plate_id', true);
|
// title_text is rendered inside payload head (zibll-like); optional WP title still allowed.
|
||||||
if ($plate_id <= 0) {
|
$title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base);
|
||||||
$boards = get_the_terms($topic_id, 'aksrt_forum_board');
|
if ($title !== '') {
|
||||||
if (!is_wp_error($boards) && !empty($boards[0])) {
|
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
$linked = (int) get_term_meta((int) $boards[0]->term_id, '_aksrt_plate_id', true);
|
|
||||||
if ($linked > 0) {
|
|
||||||
$plate_id = $linked;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($plate_id > 0) {
|
|
||||||
$p = get_post($plate_id);
|
|
||||||
if ($p instanceof \WP_Post && $p->post_type === 'aksrt_forum_plate') {
|
|
||||||
return $p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
}
|
}
|
||||||
|
|
||||||
public function form($instance): void {
|
public function form($instance): void {
|
||||||
?>
|
?>
|
||||||
<p>
|
<p>
|
||||||
<label><?php esc_html_e('标题文案', 'aksrt'); ?>
|
<label><?php esc_html_e('小标题文案', 'aksrt'); ?>
|
||||||
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('title_text')); ?>" value="<?php echo esc_attr((string) ($instance['title_text'] ?? __('版主', 'aksrt'))); ?>">
|
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('title_text')); ?>" value="<?php echo esc_attr((string) ($instance['title_text'] ?? __('版主', 'aksrt'))); ?>">
|
||||||
</label>
|
</label>
|
||||||
</p>
|
</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="grid" <?php selected(($instance['style'] ?? ''), 'grid'); ?>><?php esc_html_e('头像网格', 'aksrt'); ?></option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('show_avatar')); ?>" value="1" <?php checked(!isset($instance['show_avatar']) || !empty($instance['show_avatar'])); ?>> <?php esc_html_e('显示头像', 'aksrt'); ?></label>
|
||||||
|
</p>
|
||||||
<p class="description"><?php esc_html_e('仅在版块/帖子页显示。', 'aksrt'); ?></p>
|
<p class="description"><?php esc_html_e('仅在版块/帖子页显示。', 'aksrt'); ?></p>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update($new_instance, $old_instance): array {
|
public function update($new_instance, $old_instance): array {
|
||||||
return [
|
return [
|
||||||
'title_text' => sanitize_text_field((string) ($new_instance['title_text'] ?? '')),
|
'title_text' => sanitize_text_field((string) ($new_instance['title_text'] ?? '')),
|
||||||
|
'style' => ($new_instance['style'] ?? '') === 'grid' ? 'grid' : 'list',
|
||||||
|
'show_avatar' => !empty($new_instance['show_avatar']) ? 1 : 0,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user