Files
wordpress-theme-aksrt/inc/classes/forum/class-aksrt-topic-meta-box.php
T
kate522 1770e8e0db feat(admin): topic governance meta box and product category term fields
Add native side meta box for forum topics (plate/sticky/lock/review/pay
visibility) and taxonomy form fields for aksrt_product_cat inheritance
settings. Source-only changes; no SPA build artifacts.
2026-07-15 02:24:00 +08:00

192 lines
10 KiB
PHP

<?php
/**
* Native topic governance meta box for aksrt_forum_topic.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
class AKSRT_Topic_Meta_Box {
private static $instance = null;
public static function get_instance(): self {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
public function init(): void {
if (!is_admin()) {
return;
}
add_action('add_meta_boxes', [$this, 'register_meta_box']);
add_action('save_post_aksrt_forum_topic', [$this, 'save'], 20, 2);
}
public function register_meta_box(): void {
add_meta_box(
'aksrt_topic_governance',
__('帖子治理', 'aksrt'),
[$this, 'render'],
'aksrt_forum_topic',
'side',
'high'
);
}
public function render(WP_Post $post): void {
wp_nonce_field('aksrt_topic_meta_save', 'aksrt_topic_meta_nonce');
$plate_id = (int) get_post_meta($post->ID, '_aksrt_plate_id', true);
$sticky = (int) get_post_meta($post->ID, '_aksrt_sticky', true);
$locked = (int) get_post_meta($post->ID, '_aksrt_locked', true);
$featured = (int) get_post_meta($post->ID, '_aksrt_featured', true);
$review = (string) get_post_meta($post->ID, '_aksrt_review_status', true);
if ($review === '') {
$review = 'approved';
}
$bbs_type = (string) (get_post_meta($post->ID, '_aksrt_bbs_type', true) ?: 'standard');
$visibility = (string) (get_post_meta($post->ID, '_aksrt_visibility', true) ?: 'public');
$allow_view = (string) (get_post_meta($post->ID, '_aksrt_allow_view', true) ?: 'public');
$pay_price = (float) get_post_meta($post->ID, '_aksrt_pay_price', true);
$pay_credits= (int) get_post_meta($post->ID, '_aksrt_pay_credits', true);
$plates = get_posts([
'post_type' => 'aksrt_forum_plate',
'post_status' => 'publish',
'posts_per_page' => 200,
'orderby' => 'title',
'order' => 'ASC',
]);
?>
<p>
<label for="aksrt_plate_id"><strong><?php esc_html_e('所属版块', 'aksrt'); ?></strong></label>
<select name="aksrt_plate_id" id="aksrt_plate_id" class="widefat">
<option value="0"><?php esc_html_e('未指定', 'aksrt'); ?></option>
<?php foreach ($plates as $plate) : ?>
<option value="<?php echo esc_attr((string) $plate->ID); ?>" <?php selected($plate_id, (int) $plate->ID); ?>>
<?php echo esc_html(get_the_title($plate)); ?>
</option>
<?php endforeach; ?>
</select>
</p>
<p>
<label for="aksrt_sticky"><strong><?php esc_html_e('置顶', 'aksrt'); ?></strong></label>
<select name="aksrt_sticky" id="aksrt_sticky" class="widefat">
<option value="0" <?php selected($sticky, 0); ?>><?php esc_html_e('否', 'aksrt'); ?></option>
<option value="1" <?php selected($sticky, 1); ?>><?php esc_html_e('版块置顶', 'aksrt'); ?></option>
<option value="2" <?php selected($sticky, 2); ?>><?php esc_html_e('超级置顶', 'aksrt'); ?></option>
<option value="3" <?php selected($sticky, 3); ?>><?php esc_html_e('全局置顶', 'aksrt'); ?></option>
</select>
</p>
<p>
<label><input type="checkbox" name="aksrt_locked" value="1" <?php checked($locked, 1); ?>> <?php esc_html_e('锁定回复', 'aksrt'); ?></label><br>
<label><input type="checkbox" name="aksrt_featured" value="1" <?php checked($featured, 1); ?>> <?php esc_html_e('精华', 'aksrt'); ?></label>
</p>
<p>
<label for="aksrt_review_status"><strong><?php esc_html_e('审核状态', 'aksrt'); ?></strong></label>
<select name="aksrt_review_status" id="aksrt_review_status" class="widefat">
<option value="approved" <?php selected($review, 'approved'); ?>><?php esc_html_e('已通过', 'aksrt'); ?></option>
<option value="pending" <?php selected($review, 'pending'); ?>><?php esc_html_e('待审核', 'aksrt'); ?></option>
<option value="rejected" <?php selected($review, 'rejected'); ?>><?php esc_html_e('已拒绝', 'aksrt'); ?></option>
</select>
</p>
<p>
<label for="aksrt_bbs_type"><strong><?php esc_html_e('帖子类型', 'aksrt'); ?></strong></label>
<select name="aksrt_bbs_type" id="aksrt_bbs_type" class="widefat">
<option value="standard" <?php selected($bbs_type, 'standard'); ?>><?php esc_html_e('标准', 'aksrt'); ?></option>
<option value="question" <?php selected($bbs_type, 'question'); ?>><?php esc_html_e('提问', 'aksrt'); ?></option>
</select>
</p>
<p>
<label for="aksrt_visibility"><strong><?php esc_html_e('可见性', 'aksrt'); ?></strong></label>
<select name="aksrt_visibility" id="aksrt_visibility" class="widefat">
<?php foreach (['public' => __('公开', 'aksrt'), 'login' => __('登录可见', 'aksrt'), 'comment' => __('评论可见', 'aksrt'), 'role' => __('角色', 'aksrt'), 'credits' => __('积分', 'aksrt'), 'pay' => __('付费', 'aksrt'), 'moderator' => __('版主', 'aksrt')] as $k => $label) : ?>
<option value="<?php echo esc_attr($k); ?>" <?php selected($visibility, $k); ?>><?php echo esc_html($label); ?></option>
<?php endforeach; ?>
</select>
</p>
<p>
<label for="aksrt_allow_view"><strong><?php esc_html_e('允许查看', 'aksrt'); ?></strong></label>
<select name="aksrt_allow_view" id="aksrt_allow_view" class="widefat">
<?php foreach (['public' => __('公开', 'aksrt'), 'login' => __('登录', 'aksrt'), 'pay' => __('付费', 'aksrt'), 'moderator' => __('版主', 'aksrt')] as $k => $label) : ?>
<option value="<?php echo esc_attr($k); ?>" <?php selected($allow_view, $k); ?>><?php echo esc_html($label); ?></option>
<?php endforeach; ?>
</select>
</p>
<p>
<label for="aksrt_pay_price"><strong><?php esc_html_e('付费价格', 'aksrt'); ?></strong></label>
<input type="number" step="0.01" min="0" class="widefat" name="aksrt_pay_price" id="aksrt_pay_price" value="<?php echo esc_attr((string) $pay_price); ?>">
</p>
<p>
<label for="aksrt_pay_credits"><strong><?php esc_html_e('付费积分', 'aksrt'); ?></strong></label>
<input type="number" step="1" min="0" class="widefat" name="aksrt_pay_credits" id="aksrt_pay_credits" value="<?php echo esc_attr((string) $pay_credits); ?>">
</p>
<?php
}
public function save(int $post_id, WP_Post $post): void {
if (!isset($_POST['aksrt_topic_meta_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash((string) $_POST['aksrt_topic_meta_nonce'])), 'aksrt_topic_meta_save')) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if ($post->post_type !== 'aksrt_forum_topic' || !current_user_can('edit_post', $post_id)) {
return;
}
$plate_id = isset($_POST['aksrt_plate_id']) ? max(0, (int) $_POST['aksrt_plate_id']) : 0;
update_post_meta($post_id, '_aksrt_plate_id', $plate_id);
$sticky = isset($_POST['aksrt_sticky']) ? max(0, min(3, (int) $_POST['aksrt_sticky'])) : 0;
update_post_meta($post_id, '_aksrt_sticky', $sticky);
update_post_meta($post_id, '_aksrt_locked', !empty($_POST['aksrt_locked']) ? 1 : 0);
update_post_meta($post_id, '_aksrt_featured', !empty($_POST['aksrt_featured']) ? 1 : 0);
$review = isset($_POST['aksrt_review_status']) ? sanitize_key((string) wp_unslash($_POST['aksrt_review_status'])) : 'approved';
if (!in_array($review, ['approved', 'pending', 'rejected'], true)) {
$review = 'approved';
}
update_post_meta($post_id, '_aksrt_review_status', $review);
$bbs_type = isset($_POST['aksrt_bbs_type']) ? sanitize_key((string) wp_unslash($_POST['aksrt_bbs_type'])) : 'standard';
if (!in_array($bbs_type, ['standard', 'question'], true)) {
$bbs_type = 'standard';
}
update_post_meta($post_id, '_aksrt_bbs_type', $bbs_type);
$visibility = isset($_POST['aksrt_visibility']) ? sanitize_key((string) wp_unslash($_POST['aksrt_visibility'])) : 'public';
update_post_meta($post_id, '_aksrt_visibility', $visibility);
$allow_view = isset($_POST['aksrt_allow_view']) ? sanitize_key((string) wp_unslash($_POST['aksrt_allow_view'])) : 'public';
update_post_meta($post_id, '_aksrt_allow_view', $allow_view);
update_post_meta($post_id, '_aksrt_pay_price', isset($_POST['aksrt_pay_price']) ? max(0, (float) wp_unslash($_POST['aksrt_pay_price'])) : 0);
update_post_meta($post_id, '_aksrt_pay_credits', isset($_POST['aksrt_pay_credits']) ? max(0, (int) wp_unslash($_POST['aksrt_pay_credits'])) : 0);
// Keep board taxonomy bridge roughly in sync when plate selected.
if ($plate_id > 0 && taxonomy_exists('aksrt_forum_board')) {
$slug = 'plate-' . $plate_id;
$term = get_term_by('slug', $slug, 'aksrt_forum_board');
if (!$term) {
$title = get_the_title($plate_id) ?: $slug;
$created = wp_insert_term($title, 'aksrt_forum_board', ['slug' => $slug]);
if (!is_wp_error($created) && !empty($created['term_id'])) {
$term_id = (int) $created['term_id'];
} else {
$term_id = 0;
}
} else {
$term_id = (int) $term->term_id;
}
if ($term_id > 0) {
wp_set_object_terms($post_id, [$term_id], 'aksrt_forum_board', false);
}
}
}
}