get_review_map() as $value => $label) { $options[] = ['label' => $label, 'value' => $value]; } return $options; } /** * Check whether a user can publish directly. */ public function can_user_publish_directly(int $user_id, int $board_id = 0): bool { if ($user_id <= 0) { return false; } if (user_can($user_id, 'manage_options')) { return true; } if ($this->forum->is_forum_admin($user_id)) { return true; } if ($board_id > 0 && $this->forum->is_board_moderator($user_id, $board_id)) { return true; } return false; } // ── AJAX edit (extracted from facade) ── public function ajax_edit_topic(): void { check_ajax_referer('aksrt_forum_compose', '_nonce'); $user_id = get_current_user_id(); $topic_id = (int) ($_POST['topic_id'] ?? 0); if ($user_id <= 0) { wp_send_json_error(['message' => __('请先登录', 'aksrt')]); } if (!$this->forum->can_edit_topic($user_id, $topic_id)) { wp_send_json_error(['message' => __('无编辑权限', 'aksrt')]); } $title = sanitize_text_field((string) ($_POST['title'] ?? '')); $content = wp_kses_post((string) ($_POST['content'] ?? '')); if ($title === '' || $content === '') { wp_send_json_error(['message' => __('标题和内容不能为空', 'aksrt')]); } $result = wp_update_post([ 'ID' => $topic_id, 'post_title' => $title, 'post_content' => $content, ], true); if (is_wp_error($result)) { wp_send_json_error(['message' => $result->get_error_message()]); } $tags = $this->split_tags((string) ($_POST['tags'] ?? '')); $clean_tags = array_slice(array_values(array_filter(array_map('sanitize_text_field', $tags))), 0, 5); wp_set_object_terms($topic_id, $clean_tags, 'aksrt_forum_tag'); if (isset($_POST['special_topic'])) { update_post_meta($topic_id, '_aksrt_special_topic', sanitize_text_field((string) $_POST['special_topic'])); } if (isset($_POST['topic_cat']) && taxonomy_exists('aksrt_forum_topic_cat')) { $topic_cat = sanitize_text_field((string) $_POST['topic_cat']); wp_set_object_terms($topic_id, $topic_cat !== '' ? [$topic_cat] : [], 'aksrt_forum_topic_cat'); } $caps = $this->forum->get_compose_capabilities($user_id); if ($caps['can_set_visibility'] && isset($_POST['visibility'])) { $visibility = sanitize_key((string) $_POST['visibility']); if (isset($this->get_visibility_map()[$visibility])) { update_post_meta($topic_id, '_aksrt_visibility', $visibility); if ($visibility === self::VISIBILITY_CREDITS) { update_post_meta($topic_id, '_aksrt_credits_cost', max(0, (int) ($_POST['credits_cost'] ?? 0))); } if ($visibility === self::VISIBILITY_PAY) { update_post_meta($topic_id, '_aksrt_pay_price', sanitize_text_field((string) ($_POST['pay_price'] ?? ''))); } if ($visibility === self::VISIBILITY_ROLE) { $roles = isset($_POST['visibility_roles']) && is_array($_POST['visibility_roles']) ? array_map('sanitize_key', $_POST['visibility_roles']) : []; update_post_meta($topic_id, '_aksrt_visibility_roles', $roles); } } } if ($caps['can_set_cover']) { $this->save_cover_meta($topic_id, [ 'cover_type' => sanitize_key((string) ($_POST['cover_type'] ?? '')), 'cover_image' => esc_url_raw((string) ($_POST['cover_image'] ?? '')), 'featured_slide' => (string) ($_POST['featured_slide'] ?? ''), 'featured_video' => esc_url_raw((string) ($_POST['featured_video'] ?? '')), ]); } if ($caps['can_set_vote'] && isset($_POST['vote_enabled'])) { $vote_data = [ 'vote_enabled' => !empty($_POST['vote_enabled']), 'vote_title' => sanitize_text_field((string) ($_POST['vote_title'] ?? '')), 'vote_options_text' => sanitize_textarea_field((string) ($_POST['vote_options'] ?? '')), 'vote_multiple' => !empty($_POST['vote_multiple']), 'vote_type' => sanitize_key((string) ($_POST['vote_type'] ?? 'standard')), 'vote_expiry_days' => (int) ($_POST['vote_expiry_days'] ?? 0), ]; $vote_meta = $this->prepare_vote_meta($vote_data); $this->save_vote_meta($topic_id, $vote_meta); } wp_send_json_success([ 'message' => __('帖子已更新', 'aksrt'), 'redirect' => get_permalink($topic_id), ]); } public function can_edit_topic(int $user_id, int $topic_id): bool { if ($user_id <= 0 || $topic_id <= 0) { return false; } // Moderators and above can always edit if ($this->forum->forum_user_can($user_id, 'topic_edit_other', $topic_id)) { return true; } // Authors can edit their own unlocked topics $post = get_post($topic_id); if (!$post || $post->post_type !== 'aksrt_forum_topic') { return false; } if ((int) $post->post_author !== $user_id) { return false; } return get_post_meta($topic_id, '_aksrt_locked', true) !== '1'; } public function update_topic_meta(int $topic_id, array $meta): bool { if ($topic_id <= 0) { return false; } if (!$this->forum->can_moderate_topic(get_current_user_id(), $topic_id) && !current_user_can('manage_options')) { return false; } $allowed_keys = ['_aksrt_sticky', '_aksrt_featured', '_aksrt_locked', '_aksrt_highlight']; foreach ($meta as $key => $value) { if (!in_array($key, $allowed_keys, true)) { continue; } update_post_meta($topic_id, $key, !empty($value) ? '1' : '0'); } return true; } public function ajax_update_topic(): void { $user_id = get_current_user_id(); $topic_id = (int) ($_POST['topic_id'] ?? 0); if ($topic_id <= 0 || !$this->forum->forum_user_can($user_id, 'topic_moderate', $topic_id)) { wp_send_json_error(['message' => __('权限不足', 'aksrt')]); } $meta = []; if (isset($_POST['sticky'])) { $meta['_aksrt_sticky'] = !empty($_POST['sticky']); } if (isset($_POST['featured'])) { $meta['_aksrt_featured'] = !empty($_POST['featured']); } if (isset($_POST['locked'])) { $meta['_aksrt_locked'] = !empty($_POST['locked']); } if ($this->update_topic_meta($topic_id, $meta)) { wp_send_json_success(['message' => __('已更新', 'aksrt')]); } wp_send_json_error(['message' => __('更新失败', 'aksrt')]); } public function ajax_create_topic(): void { check_ajax_referer('aksrt_forum_compose', '_nonce'); $user_id = get_current_user_id(); if ($user_id <= 0) { wp_send_json_error(['message' => __('请先登录', 'aksrt')]); } $data = [ 'board_id' => (int) ($_POST['board_id'] ?? 0), 'title' => sanitize_text_field((string) ($_POST['title'] ?? '')), 'content' => wp_kses_post((string) ($_POST['content'] ?? '')), 'tags' => $this->split_tags((string) ($_POST['tags'] ?? '')), 'special_topic' => sanitize_text_field((string) ($_POST['special_topic'] ?? '')), 'visibility' => sanitize_key((string) ($_POST['visibility'] ?? self::VISIBILITY_PUBLIC)), 'bbs_type' => sanitize_key((string) ($_POST['bbs_type'] ?? self::BBS_TYPE_STANDARD)), 'topic_cat' => sanitize_text_field((string) ($_POST['topic_cat'] ?? '')), 'vote_enabled' => !empty($_POST['vote_enabled']), 'vote_title' => sanitize_text_field((string) ($_POST['vote_title'] ?? '')), 'vote_options_text' => sanitize_textarea_field((string) ($_POST['vote_options'] ?? '')), 'vote_multiple' => !empty($_POST['vote_multiple']), 'cover_type' => sanitize_key((string) ($_POST['cover_type'] ?? '')), 'cover_image' => esc_url_raw((string) ($_POST['cover_image'] ?? '')), 'featured_slide' => (string) ($_POST['featured_slide'] ?? ''), 'featured_video' => esc_url_raw((string) ($_POST['featured_video'] ?? '')), 'credits_cost' => (int) ($_POST['credits_cost'] ?? 0), 'pay_price' => sanitize_text_field((string) ($_POST['pay_price'] ?? '')), 'visibility_roles' => isset($_POST['visibility_roles']) && is_array($_POST['visibility_roles']) ? array_map('sanitize_key', $_POST['visibility_roles']) : [], ]; $draft_id = (int) ($_POST['draft_id'] ?? 0); if ($draft_id > 0) { $result = $this->forum->publish_draft($user_id, $draft_id, $data); } else { $result = $this->create_topic($user_id, $data); } if (is_wp_error($result)) { wp_send_json_error(['message' => $result->get_error_message()]); } wp_send_json_success([ 'message' => (string) ($result['message'] ?? __('主题已提交', 'aksrt')), 'post_id' => (int) ($result['post_id'] ?? 0), 'redirect' => (string) ($result['redirect'] ?? aksrt_get_forum_home_url()), ]); } public function ajax_unlock_topic(): void { check_ajax_referer('aksrt_forum_action', '_nonce'); $user_id = get_current_user_id(); if ($user_id <= 0) { wp_send_json_error(['message' => __('请先登录', 'aksrt')]); } $topic_id = (int) ($_POST['topic_id'] ?? 0); if ($topic_id <= 0) { wp_send_json_error(['message' => __('主题不存在', 'aksrt')]); } $result = $this->unlock_topic_with_credits($user_id, $topic_id); if (!empty($result['success'])) { wp_send_json_success($result); } else { wp_send_json_error(['message' => $result['message'] ?? __('解锁失败', 'aksrt')]); } } public function ajax_purchase_topic(): void { check_ajax_referer('aksrt_forum_action', '_nonce'); $user_id = get_current_user_id(); if ($user_id <= 0) { wp_send_json_error(['message' => __('请先登录', 'aksrt')]); } $topic_id = (int) ($_POST['topic_id'] ?? 0); if ($topic_id <= 0) { wp_send_json_error(['message' => __('主题不存在', 'aksrt')]); } $result = $this->purchase_topic_with_balance($user_id, $topic_id); if (!empty($result['success'])) { wp_send_json_success($result); } else { wp_send_json_error(['message' => $result['message'] ?? __('购买失败', 'aksrt')]); } } }