'; echo ''; } public static function close(): void { echo '
'; get_footer(); } public static function sidebar(string $context): void { echo ''; } public static function home(): void { HomeView::render(); } public static function listing(): void { $obj = get_queried_object(); $plate = $obj instanceof \WP_Post && $obj->post_type === Core::PLATE ? $obj : null; $term = $obj instanceof \WP_Term ? $obj : null; $title = $plate ? $plate->post_title : ($term ? $term->name : '论坛'); $context = $plate ? 'plate' : 'term'; self::open($title, $context); \Jio\WidgetSystem\WidgetAreas::render('forum_' . $context . '_top_fluid'); echo '
'; echo '

' . esc_html($title) . '

'; if ($plate) { echo '
' . wp_kses_post(wpautop($plate->post_excerpt ?: $plate->post_content)) . '
'; echo '

' . (int) get_post_meta($plate->ID, '_jio_forum_follow_count', true) . ' 人关注

'; echo Cards::follow_button($plate->ID, 'but c-blue'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped if (Access::is_moderator(get_current_user_id(), $plate->ID)) { self::plate_editor($plate); } if (is_user_logged_in() && !Access::is_moderator(get_current_user_id(), $plate->ID) && jio_get_setting('jio_forum_moderator_apply', true)) { self::action('apply', $plate->ID, '申请版主'); } if (Access::is_admin(get_current_user_id()) || (int) $plate->post_author === get_current_user_id()) { self::applications($plate->ID); } } elseif ($term) { echo '

' . esc_html($term->description) . '

'; } echo '
'; self::tabs(); if ($term && $term->taxonomy === Core::CATEGORY) { self::plates(['tax_query' => [['taxonomy' => Core::CATEGORY, 'terms' => [$term->term_id]]]]); } else { $args = ['post_type' => Core::POST, 'post_status' => 'publish']; if ($plate) { $args['meta_query'] = [['key' => '_jio_forum_plate_id', 'value' => $plate->ID]]; } elseif ($term) { $args['tax_query'] = [['taxonomy' => $term->taxonomy, 'terms' => [$term->term_id]]]; } self::posts($args, $context); if ($plate && Access::is_moderator(get_current_user_id(), $plate->ID)) { echo '

待审核帖子

'; $args['post_status'] = 'pending'; self::posts($args, $context); } } echo '
'; self::sidebar($context); echo '
'; \Jio\WidgetSystem\WidgetAreas::render('forum_' . $context . '_bottom_fluid'); self::close(); } /** Listing pages (plate / taxonomy) use a fixed, always-available tab set. */ public static function tabs(): void { $tabs = ['latest' => '最新', 'popular' => '热门', 'essence' => '精华', 'question' => '问答', 'vote' => '投票']; $base_url = is_singular(Core::PLATE) ? get_permalink(get_queried_object_id()) : (is_tax([Core::CATEGORY, Core::TOPIC, Core::TAG]) ? get_term_link(get_queried_object()) : Core::home_url()); echo ''; } public static function posts(array $args, string $context = 'home'): void { $view = sanitize_key((string) ($_GET['forum_view'] ?? 'latest')); if (!in_array($view, ['latest', 'popular', 'essence', 'question', 'vote'], true)) { $view = 'latest'; } if (in_array($view, ['question', 'vote'], true)) { $args['meta_query'][] = ['key' => '_jio_forum_type', 'value' => $view]; } if ($view === 'essence') { $args['meta_query'][] = ['key' => '_jio_forum_essence', 'value' => 1]; } $args['posts_per_page'] = max(1, min(50, (int) jio_get_setting('jio_forum_page_size', 20))); $args['paged'] = max(1, (int) get_query_var('paged', 1)); $args['orderby'] = 'date'; $args['order'] = 'DESC'; $args['jio_forum_list'] = $view; $query = new \WP_Query($args); \Jio\WidgetSystem\WidgetAreas::render('forum_' . $context . '_top_content'); if (!$query->have_posts()) { echo '
' . jio_get_null('暂无帖子') . '
'; } else { Cards::prime($query->posts); echo '
'; foreach ($query->posts as $post) { echo Cards::post_detail($post, 'ajax-item'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } echo '
'; } self::pagination($query); \Jio\WidgetSystem\WidgetAreas::render('forum_' . $context . '_bottom_content'); } public static function plates(array $args): void { $query = new \WP_Query(array_merge(['post_type' => Core::PLATE, 'post_status' => 'publish', 'posts_per_page' => 20], $args)); if (!$query->have_posts()) { echo jio_get_null('暂无版块'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped return; } PlateStats::prime($query->posts ? wp_list_pluck($query->posts, 'ID') : []); echo '
'; foreach ($query->posts as $plate) { echo Cards::plate_item($plate); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } echo '
'; } public static function plate_card(\WP_Post $plate): void { echo Cards::plate_item($plate); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } public static function post_card(\WP_Post $post): void { echo Cards::post_detail($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } public static function replies(int $post_id): void { $page = max(1, (int) ($_GET['cpage'] ?? 1)); $limit = max(1, min(100, (int) jio_get_setting('jio_forum_reply_page_size', 20))); $comments = get_comments(['post_id' => $post_id, 'status' => 'approve', 'number' => $limit, 'offset' => ($page - 1) * $limit, 'orderby' => 'comment_date_gmt', 'order' => 'ASC']); $total = (int) get_comments(['post_id' => $post_id, 'status' => 'approve', 'count' => true]); echo '

回复 ' . $total . '

'; if (!$comments) echo '

暂无回复

'; foreach ($comments as $comment) { $adopted = (bool) get_comment_meta($comment->comment_ID, '_jio_forum_adopted', true); $hot = (bool) get_comment_meta($comment->comment_ID, '_jio_forum_hot', true); echo '
' . get_avatar((int) $comment->user_id, 40) . '
' . esc_html(get_comment_author($comment)) . '' . ($adopted ? '已采纳' : '') . '
'; if ($hot) echo '热门回复'; if ((int) $comment->comment_parent > 0) { $parent = get_comment((int) $comment->comment_parent); if ($parent instanceof \WP_Comment) echo '

回复 @' . esc_html(get_comment_author($parent)) . '

'; } echo '
' . wp_kses_post(wpautop($comment->comment_content)) . '
'; if (is_user_logged_in()) echo ''; if (is_user_logged_in() && ((int) $comment->user_id === get_current_user_id() || Access::is_moderator(get_current_user_id(), (int) get_post_meta($post_id, '_jio_forum_plate_id', true)))) echo ''; if (Access::is_moderator(get_current_user_id(), (int) get_post_meta($post_id, '_jio_forum_plate_id', true))) echo ''; if (is_user_logged_in()) echo ''; if (get_post_meta($post_id, '_jio_forum_type', true) === 'question' && !get_post_meta($post_id, '_jio_forum_adopted_comment', true) && Access::can_manage_post(get_current_user_id(), $post_id)) { echo ''; } echo '
'; } if ($total > $limit) { $links = paginate_links(['base' => add_query_arg('cpage', '%#%', get_permalink($post_id)), 'current' => $page, 'total' => (int) ceil($total / $limit), 'type' => 'list']); echo ''; } if (get_post_field('comment_status', $post_id) === 'open') { if (is_user_logged_in()) { echo '

发表回复

'; } else { echo '

登录后回复

'; } } else { echo '

回复已关闭

'; } echo '
'; } private static function plate_editor(\WP_Post $plate): void { $id = $plate->ID; echo ''; echo ''; echo '

编辑版块

'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo '

'; } private static function applications(int $plate_id): void { $users = get_users(['meta_key' => '_jio_forum_application_' . $plate_id, 'meta_value' => 'pending', 'number' => 20]); echo '

版主管理

'; $moderators = array_map('absint', (array) get_post_meta($plate_id, '_jio_forum_moderators', true)); foreach ($moderators as $user_id) { $user = get_userdata($user_id); if ($user) echo '
' . esc_html($user->display_name) . '
'; } echo '

'; if ($users) echo '

待处理申请

'; foreach ($users as $user) { echo '
' . esc_html($user->display_name) . '
'; } echo '
'; } public static function pagination(\WP_Query $query): void { if ($query->max_num_pages <= 1) { return; } echo ''; } public static function action(string $action, int $id, string $label): void { echo ''; } public static function user_marked_ids(int $user_id, string $prefix): array { if ($user_id <= 0) return []; $ids = []; foreach (get_user_meta($user_id) as $key => $values) { if (str_starts_with((string) $key, $prefix) && !empty($values[0])) { $id = absint(substr((string) $key, strlen($prefix))); if ($id) $ids[] = $id; } } return array_values(array_unique($ids)); } public static function user_panel(int $user_id, bool $owner): void { $tab = sanitize_key((string) ($_GET['forum_tab'] ?? 'posts')); $tabs = ['posts' => '帖子', 'plates' => '版块']; if ($owner) $tabs += ['favorites' => '收藏', 'follow' => '关注']; if (!isset($tabs[$tab])) $tab = 'posts'; echo '
'; if ($owner) echo '

发布帖子

'; $args = ['post_status' => $owner ? ['publish', 'pending'] : 'publish', 'posts_per_page' => 20]; if ($tab === 'posts' || $tab === 'plates') { $args['post_type'] = $tab === 'posts' ? Core::POST : Core::PLATE; $args['author'] = $user_id; } else { $args['post_type'] = $tab === 'favorites' ? Core::POST : Core::PLATE; $ids = self::user_marked_ids($user_id, $tab === 'favorites' ? '_jio_forum_favorite_' : '_jio_forum_follow_'); $args['post__in'] = $ids ?: [0]; } $query = new \WP_Query($args); echo '
'; if (!$query->have_posts()) echo '

暂无内容

'; Cards::prime($query->posts); foreach ($query->posts as $post) { if ($post->post_type === Core::POST) { echo Cards::post_detail($post); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped continue; } $url = $post->post_status === 'publish' ? get_permalink($post) : ''; echo '
' . ($url ? '' : '') . esc_html($post->post_title) . ($url ? '' : '') . ($url ? '' : '待审核') . '
'; if ($owner && !$url) self::plate_editor($post); } echo '
'; } }