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.
This commit is contained in:
@@ -324,6 +324,7 @@ require_once AKSRT_DIR . '/inc/classes/shop/class-aksrt-product-meta-box.php';
|
||||
require_once AKSRT_DIR . '/inc/classes/shop/class-aksrt-product-variants-meta-box.php';
|
||||
require_once AKSRT_DIR . '/inc/classes/forum/class-aksrt-plate-meta-box.php';
|
||||
require_once AKSRT_DIR . '/inc/classes/forum/class-aksrt-topic-admin-list.php';
|
||||
require_once AKSRT_DIR . '/inc/classes/forum/class-aksrt-topic-meta-box.php';
|
||||
require_once AKSRT_DIR . '/inc/classes/shop/shop-traits/trait-aksrt-shop-part-1.php';
|
||||
require_once AKSRT_DIR . '/inc/classes/shop/shop-traits/trait-aksrt-shop-part-2.php';
|
||||
require_once AKSRT_DIR . '/inc/classes/shop/shop-traits/trait-aksrt-shop-part-3.php';
|
||||
|
||||
@@ -39,6 +39,12 @@ class AKSRT_Shop_Term_Meta {
|
||||
add_action('shop_discount_edit_form_fields', [$this, 'render_discount_edit_fields'], 10, 1);
|
||||
add_action('created_shop_discount', [$this, 'save_discount_term_fields']);
|
||||
add_action('edited_shop_discount', [$this, 'save_discount_term_fields']);
|
||||
|
||||
// Product category inheritance fields.
|
||||
add_action('aksrt_product_cat_add_form_fields', [$this, 'render_cat_add_fields']);
|
||||
add_action('aksrt_product_cat_edit_form_fields', [$this, 'render_cat_edit_fields'], 10, 1);
|
||||
add_action('created_aksrt_product_cat', [$this, 'save_cat_term_fields']);
|
||||
add_action('edited_aksrt_product_cat', [$this, 'save_cat_term_fields']);
|
||||
}
|
||||
|
||||
// ─── Taxonomy Registration ───────────────────────────────────
|
||||
@@ -565,4 +571,110 @@ class AKSRT_Shop_Term_Meta {
|
||||
update_term_meta($term_id, $key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function render_cat_add_fields(): void {
|
||||
foreach ($this->get_cat_field_definitions() as $key => $def) {
|
||||
echo '<div class="form-field">';
|
||||
echo '<label for="' . esc_attr($key) . '">' . esc_html((string) ($def['description'] ?? $key)) . '</label>';
|
||||
$this->render_cat_field_control($key, $def['default'] ?? '', false);
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
public function render_cat_edit_fields($term): void {
|
||||
if (!($term instanceof WP_Term)) {
|
||||
return;
|
||||
}
|
||||
foreach ($this->get_cat_field_definitions() as $key => $def) {
|
||||
$value = get_term_meta($term->term_id, $key, true);
|
||||
if ($value === '' || $value === false) {
|
||||
$value = $def['default'] ?? '';
|
||||
}
|
||||
echo '<tr class="form-field"><th scope="row"><label for="' . esc_attr($key) . '">' . esc_html((string) ($def['description'] ?? $key)) . '</label></th><td>';
|
||||
$this->render_cat_field_control($key, $value, true);
|
||||
echo '</td></tr>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
private function render_cat_field_control(string $key, $value, bool $edit): void {
|
||||
$val = (string) $value;
|
||||
if (in_array($key, ['shop_cat_guest_buy', 'shop_cat_email_fill', 'shop_cat_content_show_bg'], true)) {
|
||||
echo '<label><input type="checkbox" name="' . esc_attr($key) . '" value="1" ' . checked($val, '1', false) . '> ' . esc_html__('启用', 'aksrt') . '</label>';
|
||||
return;
|
||||
}
|
||||
if (in_array($key, ['shop_cat_service', 'shop_cat_single_tab', 'shop_cat_content_after'], true)) {
|
||||
echo '<textarea class="large-text" rows="3" name="' . esc_attr($key) . '" id="' . esc_attr($key) . '">' . esc_textarea($val) . '</textarea>';
|
||||
return;
|
||||
}
|
||||
if ($key === 'shop_cat_shipping_fee') {
|
||||
$opts = ['' => __('继承', 'aksrt'), 'free' => __('包邮', 'aksrt'), 'fixed' => __('固定运费', 'aksrt'), 'amount' => __('满额包邮', 'aksrt')];
|
||||
echo '<select name="' . esc_attr($key) . '" id="' . esc_attr($key) . '">';
|
||||
foreach ($opts as $k => $label) {
|
||||
printf('<option value="%s"%s>%s</option>', esc_attr($k), selected($val, $k, false), esc_html($label));
|
||||
}
|
||||
echo '</select>';
|
||||
return;
|
||||
}
|
||||
if ($key === 'shop_cat_after_sale') {
|
||||
$opts = ['' => __('继承', 'aksrt'), 'refund' => __('仅退款', 'aksrt'), 'refund_return' => __('退货退款', 'aksrt'), 'none' => __('不支持', 'aksrt')];
|
||||
echo '<select name="' . esc_attr($key) . '" id="' . esc_attr($key) . '">';
|
||||
foreach ($opts as $k => $label) {
|
||||
printf('<option value="%s"%s>%s</option>', esc_attr($k), selected($val, $k, false), esc_html($label));
|
||||
}
|
||||
echo '</select>';
|
||||
return;
|
||||
}
|
||||
if ($key === 'shop_cat_content_layout') {
|
||||
$opts = ['' => __('继承', 'aksrt'), 'adapt' => __('自适应', 'aksrt'), 'full' => __('通栏', 'aksrt'), 'sidebar' => __('侧栏', 'aksrt')];
|
||||
echo '<select name="' . esc_attr($key) . '" id="' . esc_attr($key) . '">';
|
||||
foreach ($opts as $k => $label) {
|
||||
printf('<option value="%s"%s>%s</option>', esc_attr($k), selected($val, $k, false), esc_html($label));
|
||||
}
|
||||
echo '</select>';
|
||||
return;
|
||||
}
|
||||
if ($key === 'shop_cat_list_style') {
|
||||
$opts = ['' => __('继承', 'aksrt'), 'default' => __('默认', 'aksrt'), 'card-lg' => __('大卡片', 'aksrt'), 'card-sm' => __('小卡片', 'aksrt')];
|
||||
echo '<select name="' . esc_attr($key) . '" id="' . esc_attr($key) . '">';
|
||||
foreach ($opts as $k => $label) {
|
||||
printf('<option value="%s"%s>%s</option>', esc_attr($k), selected($val, $k, false), esc_html($label));
|
||||
}
|
||||
echo '</select>';
|
||||
return;
|
||||
}
|
||||
$type = $key === 'shop_cat_limit_buy' ? 'number' : 'text';
|
||||
printf(
|
||||
'<input type="%s" class="%s" name="%s" id="%s" value="%s" />',
|
||||
esc_attr($type),
|
||||
$edit ? 'regular-text' : '',
|
||||
esc_attr($key),
|
||||
esc_attr($key),
|
||||
esc_attr($val)
|
||||
);
|
||||
}
|
||||
|
||||
public function save_cat_term_fields(int $term_id): void {
|
||||
if (!current_user_can('manage_categories')) {
|
||||
return;
|
||||
}
|
||||
foreach ($this->get_cat_field_definitions() as $key => $def) {
|
||||
if (in_array($key, ['shop_cat_guest_buy', 'shop_cat_email_fill', 'shop_cat_content_show_bg'], true)) {
|
||||
$raw = isset($_POST[$key]) ? '1' : '';
|
||||
} else {
|
||||
if (!isset($_POST[$key])) {
|
||||
continue;
|
||||
}
|
||||
$raw = wp_unslash($_POST[$key]);
|
||||
}
|
||||
if (isset($def['sanitize']) && is_callable($def['sanitize'])) {
|
||||
$value = call_user_func($def['sanitize'], $raw);
|
||||
} else {
|
||||
$value = sanitize_text_field((string) $raw);
|
||||
}
|
||||
update_term_meta($term_id, $key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user