- cards: restore the shared card shell, add author follow/message actions, score group, last-reply meta and reference plate header actions - home: desktop left tab rail, widget-only sidebar, reference load-more markup - plate: 1-based tabs, reference defaults (全部/推荐/最新回复/热门/精华) - post: fixed action rail, score footer, author card, h1 article title - quick publish: plate selector moved into the submit row like the reference
186 lines
14 KiB
PHP
186 lines
14 KiB
PHP
<?php
|
|
|
|
namespace Jio\Forum;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
/** Forum compose/edit page (reference two-column editor + settings sidebar). */
|
|
final class EditView {
|
|
public static function render(): void {
|
|
$edit_id = absint(get_query_var('jio_forum_edit'));
|
|
$post = $edit_id > 0 ? get_post($edit_id) : null;
|
|
if ($edit_id > 0 && (!$post instanceof \WP_Post || !Access::can_manage_post(get_current_user_id(), $edit_id))) {
|
|
status_header(403);
|
|
echo '<main id="forum" class="jio-forum forum-edit"><div class="container"><div class="jio-panel full-widget-sm text-center" style="min-height:60vh;">' . jio_get_null('抱歉!您暂无编辑此内容的权限', 60, 'null-post.svg') . '</div></div></main>';
|
|
get_footer();
|
|
return;
|
|
}
|
|
$user_id = get_current_user_id();
|
|
$type = $post ? (string) get_post_meta($post->ID, '_jio_forum_type', true) : 'normal';
|
|
$plate_id = $post ? (int) get_post_meta($post->ID, '_jio_forum_plate_id', true) : absint(is_scalar($_GET['plate'] ?? 0) ? $_GET['plate'] : 0);
|
|
$view_limit = $post ? (string) get_post_meta($post->ID, '_jio_forum_view_limit', true) : 'all';
|
|
$vote_options = $post ? (array) get_post_meta($post->ID, '_jio_forum_vote_options', true) : [];
|
|
$topics = $post ? wp_get_post_terms($post->ID, Core::TOPIC, ['fields' => 'names']) : [];
|
|
$tags = $post ? wp_get_post_terms($post->ID, Core::TAG, ['fields' => 'names']) : [];
|
|
|
|
wp_enqueue_editor();
|
|
echo '<main id="forum" class="jio-forum forum-edit"><form id="bbs-posts-edit" data-forum-form="post" data-id="' . (int) $edit_id . '"><div class="container"><div class="content-wrap"><div class="content-layout">';
|
|
echo '<div class="jio-panel full-widget-sm editor-main-box" style="min-height:60vh">';
|
|
if ($user_id <= 0) {
|
|
echo jio_get_null('请先登录后再发布', 40, 'null-user.svg') . '<p class="text-center"><a class="but jb-blue padding-lg" href="' . esc_url(jio_get_login_url(Core::edit_url($edit_id))) . '"><i class="fa fas fa-sign-in-alt mr6"></i>登录</a></p>';
|
|
echo '</div>';
|
|
self::close();
|
|
return;
|
|
}
|
|
// Cover
|
|
$cover = $post ? get_the_post_thumbnail_url($post, 'large') : '';
|
|
echo '<div class="relative edit-posts-featured mb20" data-forum-cover>';
|
|
echo '<div class="forum-cover-preview' . ($cover ? '' : ' is-empty') . '">' . ($cover ? '<img src="' . esc_url($cover) . '" alt="">' : '<i class="fa far fa-image em3x"></i>') . '</div>';
|
|
echo '<button type="button" class="but hollow c-blue padding-lg" data-forum-cover-pick><i class="fa fas fa-image mr6"></i>' . ($cover ? '更换封面' : '添加封面') . '</button>';
|
|
echo '<input type="file" accept="image/*" data-forum-cover-file hidden><input type="hidden" name="featured_image_id" value="' . (int) get_post_thumbnail_id($edit_id) . '"></div>';
|
|
// Title
|
|
echo '<div class="relative edit-posts-title"><textarea class="line-form-input input-lg new-title" name="title" rows="1" maxlength="120" tabindex="1" placeholder="' . esc_attr((string) jio_get_setting('jio_forum_title_placeholder', '请输入标题')) . '">' . esc_textarea($post ? $post->post_title : '') . '</textarea><i class="line-form-line"></i></div>';
|
|
// Editor
|
|
wp_editor($post ? $post->post_content : '', 'jio_forum_content', [
|
|
'textarea_name' => 'content',
|
|
'textarea_rows' => 20,
|
|
'editor_height' => wp_is_mobile() ? 460 : 486,
|
|
'media_buttons' => false,
|
|
'quicktags' => false,
|
|
'default_editor' => 'tinymce',
|
|
'tinymce' => ['placeholder' => (string) jio_get_setting('jio_forum_content_placeholder', '请输入内容')],
|
|
]);
|
|
echo '<div class="jio-forum__editor-tools mt10">';
|
|
foreach (['image' => ['插入图片', 'fa-image'], 'video' => ['插入视频', 'fa-video'], 'resource' => ['插入附件', 'fa-paperclip']] as $kind => [$label, $icon]) {
|
|
$setting = 'jio_forum_upload_' . ($kind === 'resource' ? 'file' : $kind);
|
|
if (jio_get_setting($setting, $kind === 'image')) {
|
|
echo '<button type="button" class="but hollow px12" data-forum-upload="' . esc_attr($kind) . '"><i class="fa fas ' . esc_attr($icon) . ' mr6"></i>' . esc_html($label) . '</button>';
|
|
}
|
|
}
|
|
echo '<input type="file" data-forum-file hidden></div>';
|
|
self::hidden_fields($post, $type, $view_limit);
|
|
echo '</div>'; // editor-main-box
|
|
|
|
// Sidebar: submit, status, access, plate, topic, tag, type, vote
|
|
echo '<div class="sidebar show-sidebar">';
|
|
echo self::submit_box($post);
|
|
echo self::status_box($post);
|
|
echo self::allow_view_box($view_limit);
|
|
echo self::plate_box($plate_id);
|
|
echo self::term_box('topics', '话题', Core::TOPIC, $topics, 'fa-hashtag');
|
|
echo self::term_box('tags', '标签', Core::TAG, $tags, 'fa-tag');
|
|
echo self::type_box($type);
|
|
echo self::vote_box($vote_options, $post);
|
|
echo self::hide_box($post);
|
|
if (!$post && function_exists('jio_render_captcha') && function_exists('jio_is_captcha_enabled_for') && jio_is_captcha_enabled_for('forum_post')) {
|
|
echo '<div class="jio-panel mb10-sm mb20 jio-forum__captcha">';
|
|
jio_render_captcha('forum_post');
|
|
echo '</div>';
|
|
}
|
|
\Jio\WidgetSystem\WidgetAreas::render('forum_edit_sidebar');
|
|
echo '</div>';
|
|
self::close();
|
|
}
|
|
|
|
private static function hidden_fields(?\WP_Post $post, string $type, string $view_limit): void {
|
|
echo '<input type="hidden" name="type" value="' . esc_attr($type) . '">';
|
|
echo '<input type="hidden" name="view_limit" value="' . esc_attr($view_limit) . '">';
|
|
echo '<p class="jio-forum__message" role="status" aria-live="polite"></p>';
|
|
}
|
|
|
|
private static function submit_box(?\WP_Post $post): string {
|
|
$last = $post ? get_the_modified_time('Y-m-d H:i:s', $post->ID) : '';
|
|
$html = '<div class="jio-panel mb10-sm mb20"><div class="but-average mb20 main-radius">';
|
|
if (!$post || !in_array($post->post_status, ['publish', 'pending'], true)) {
|
|
$html .= '<button type="button" class="but jb-green padding-10" data-forum-draft><i class="fa far fa-save mr6"></i>保存草稿</button>';
|
|
}
|
|
$html .= '<button type="submit" class="but jb-blue padding-10 bbs-posts-submit"><i class="fa far fa-paper-plane mr6"></i>' . ($post ? '保存' : '发布') . '</button>';
|
|
$html .= '</div>';
|
|
if ($post && $last !== '') {
|
|
$html .= '<div class="muted-3-color px12"><span class="badg badg-sm mr6">编辑内容</span>最后更新:' . esc_html($last) . '</div>';
|
|
}
|
|
return $html . '</div>';
|
|
}
|
|
|
|
private static function status_box(?\WP_Post $post): string {
|
|
if (!$post instanceof \WP_Post) return '';
|
|
$status = in_array($post->post_status, ['pending', 'draft', 'publish'], true) ? $post->post_status : 'pending';
|
|
$list = '';
|
|
foreach (['pending' => '待审核', 'draft' => '草稿', 'publish' => '发布'] as $key => $label) {
|
|
$list .= '<span data-forum-status="' . $key . '" class="badg mr3 p2-10 pointer' . ($key === $status ? ' active' : '') . '">' . $label . '</span>';
|
|
}
|
|
return '<div class="jio-panel mb10 type-drop"><div class="flex ac jsb"><div class="flex ac c-red"><i class="fa fas fa-thumbtack mr10"></i>设置状态</div><div class="em09">' . $list . '</div></div><input type="hidden" name="post_status" value="' . esc_attr($status) . '"></div>';
|
|
}
|
|
|
|
private static function allow_view_box(string $current): string {
|
|
$labels = ['all' => '公开', 'login' => '登录后可查看', 'follow' => '关注版块后可查看', 'points' => '支付积分查看', 'pay' => '付费查看'];
|
|
$options = '';
|
|
foreach ($labels as $key => $label) {
|
|
$options .= '<div data-forum-view="' . $key . '" class="pointer but p2-10 mb6' . ($key === $current ? ' active' : '') . '">' . esc_html($label) . '</div>';
|
|
}
|
|
return '<div class="allow-view-drop drop-select dropdown jio-panel mb10-sm mb20"><div data-toggle-class="open" data-target=".allow-view-drop" class="flex ac jsb drop-btn"><div class="flex ac"><i class="fa far fa-eye mr6"></i>阅读权限</div><div class="flex ac"><span name="view_limit" class="em09 muted-2-color">' . esc_html($labels[$current] ?? '公开') . '</span><i class="ml6 fa fas fa-angle-right em12"></i></div></div><div class="dropdown-menu fluid"><div class="padding-10 flex jsb muted-2-color em09">设置阅读权限<span data-toggle-class="close" data-target=".allow-view-drop" class="pointer">完成</span></div><div class="mini-scrollbar padding-w10 select-drop-box">' . $options . '</div></div></div>';
|
|
}
|
|
|
|
private static function plate_box(int $current): string {
|
|
$plates = get_posts(['post_type' => Core::PLATE, 'post_status' => 'publish', 'posts_per_page' => 200, 'orderby' => 'title', 'order' => 'ASC']);
|
|
$options = '';
|
|
foreach ($plates as $plate) {
|
|
$options .= '<div data-forum-plate="' . (int) $plate->ID . '" class="pointer but p2-10 mb6' . ((int) $plate->ID === $current ? ' active' : '') . '">' . esc_html($plate->post_title) . '</div>';
|
|
}
|
|
$name = $current > 0 ? get_the_title($current) : '请选择';
|
|
return '<div class="plate-drop drop-select dropdown jio-panel mb10-sm mb20"><div data-toggle-class="open" data-target=".plate-drop" class="flex ac jsb drop-btn"><div class="flex ac"><i class="fa fas fa-cube mr6"></i>版块</div><div class="flex ac"><span name="plate_id" class="em09 muted-2-color text-ellipsis">' . esc_html($name) . '</span><i class="ml6 fa fas fa-angle-right em12"></i></div></div><input type="hidden" name="plate_id" value="' . ($current ?: '') . '"><div class="dropdown-menu fluid"><div class="mini-scrollbar padding-w10 select-drop-box">' . $options . '</div></div></div>';
|
|
}
|
|
|
|
/** @param string[] $selected */
|
|
private static function term_box(string $field, string $label, string $taxonomy, array $selected, string $icon): string {
|
|
$terms = get_terms(['taxonomy' => $taxonomy, 'hide_empty' => false, 'number' => 200, 'orderby' => 'count', 'order' => 'DESC']);
|
|
$selected = array_values(array_filter(array_map('strval', $selected)));
|
|
$options = '';
|
|
foreach (is_array($terms) ? $terms : [] as $term) {
|
|
$active = in_array($term->name, $selected, true);
|
|
$options .= '<label class="but p2-10 mb6 pointer' . ($active ? ' active' : '') . '"><input type="checkbox" data-forum-' . esc_attr($field) . ' value="' . esc_attr($term->name) . '"' . checked($active, true, false) . ' hidden> ' . esc_html($term->name) . '</label>';
|
|
}
|
|
return '<div class="' . esc_attr($field) . '-drop drop-select dropdown jio-panel mb10-sm mb20"><div data-toggle-class="open" data-target=".' . esc_attr($field) . '-drop" class="flex ac jsb drop-btn"><div class="flex ac"><i class="fa fas ' . esc_attr($icon) . ' mr6"></i>' . esc_html($label) . '</div><div class="flex ac"><span class="em09 muted-2-color text-ellipsis" data-forum-' . esc_attr($field) . '-label>' . esc_html($selected ? implode('、', array_slice($selected, 0, 2)) : '请选择') . '</span><i class="ml6 fa fas fa-angle-right em12"></i></div></div><input type="hidden" name="' . esc_attr($field) . '" value="' . esc_attr(implode(',', $selected)) . '"><div class="dropdown-menu fluid"><div class="mini-scrollbar padding-w10 select-drop-box">' . $options . '</div></div></div>';
|
|
}
|
|
|
|
private static function type_box(string $current): string {
|
|
$options = [];
|
|
$options['normal'] = '标准';
|
|
if (jio_get_setting('jio_forum_question_enabled', true)) $options['question'] = '提问';
|
|
if (jio_get_setting('jio_forum_vote_enabled', true)) $options['vote'] = '投票';
|
|
if (count($options) < 2) return '';
|
|
$list = '';
|
|
foreach ($options as $key => $label) {
|
|
$list .= '<span data-forum-type-set="' . $key . '" class="but p2-10 pointer' . ($key === $current ? ' active' : '') . '">' . esc_html($label) . '</span>';
|
|
}
|
|
return '<div class="type-drop jio-panel mb10-sm mb20"><div class="flex ac jsb"><div class="flex ac"><i class="fa fas fa-delicious mr6"></i>发布类型</div><div class="but-average radius em09">' . $list . '</div></div></div>';
|
|
}
|
|
|
|
/** Hidden-content composer: the block becomes a site visibility shortcode on save. */
|
|
private static function hide_box(?\WP_Post $post): string {
|
|
$types = '';
|
|
foreach (['logged' => '登录可见', 'reply' => '评论可见', 'vip1' => '会员可见', 'payshow' => '付费可见'] as $key => $label) {
|
|
$types .= '<span data-forum-hide-type="' . $key . '" class="mb6 mr6 badg p2-10 pointer' . ($key === 'logged' ? ' active' : '') . '">' . esc_html($label) . '</span>';
|
|
}
|
|
return '<div class="hide-type-drop drop-select dropdown jio-panel mb10-sm mb20"><div data-toggle-class="open" data-target=".hide-type-drop" class="flex ac jsb drop-btn"><span class="flex ac"><i class="far fa-eye-slash mr6"></i>隐藏内容</span><i class="ml6 fa fas fa-angle-right em12"></i></div>'
|
|
. '<input type="hidden" name="hide_type" value="">'
|
|
. '<div class="dropdown-menu fluid"><div class="mini-scrollbar padding-w10 select-drop-box"><div class="em09 muted-3-color mb10">添加额外的隐藏内容</div><div class="flex hh">' . $types . '</div>'
|
|
. '<textarea rows="6" name="hide_content" class="form-control input-textarea" placeholder="在此输入需要隐藏的内容"></textarea></div></div></div>';
|
|
}
|
|
|
|
/** @param string[] $options */
|
|
private static function vote_box(array $options, ?\WP_Post $post): string {
|
|
$type = $post ? (string) get_post_meta($post->ID, '_jio_forum_type', true) : 'normal';
|
|
return '<div class="type-drop jio-panel mb10-sm mb20 forum-type-vote"' . ($type === 'vote' ? '' : ' hidden') . '><div class="mb10"><i class="fa fas fa-poll mr6"></i>投票设置</div>'
|
|
. '<input class="form-control mb6" name="vote_title" maxlength="60" placeholder="投票标题" value="' . esc_attr($post ? (string) get_post_meta($post->ID, '_jio_forum_vote_title', true) : '') . '">'
|
|
. '<select class="form-control mb6" name="vote_type"><option value="single">单选</option><option value="multiple">多选</option><option value="pk">双选 PK</option></select>'
|
|
. '<textarea class="form-control mb6" name="vote_options" rows="4" placeholder="每行一个选项">' . esc_textarea(implode("\n", $options)) . '</textarea>'
|
|
. '<select class="form-control" name="vote_days"><option value="0">永久</option><option value="1">1 天</option><option value="7">7 天</option><option value="30">30 天</option></select></div>';
|
|
}
|
|
|
|
private static function close(): void {
|
|
echo '</div></div></div></form></main>';
|
|
get_footer();
|
|
}
|
|
}
|