Files
wordpress-theme-aksrt/inc/classes/class-aksrt-forum.php
T
kate522 ee40a074d7 refactor(db): drop option/data migration from DB migrator
Keep dbDelta table schema only. Remove aksrt_basic_settings dual-write,
layout/cms/resource/order/plate option migrators, and part-1 trait.
Plate CPT activation no longer gated on migration flag.
2026-07-11 18:32:48 +08:00

802 lines
30 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Forum domain service.
*
* Keeps the canonical forum model on top of:
* - post type: aksrt_forum_topic
* - board taxonomy: aksrt_forum_board
* - tag taxonomy: aksrt_forum_tag
* - governance data: post meta / term meta
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
class AKSRT_Forum {
private static $instance = null;
const TIER_NONE = 0; // 游客/无权
const TIER_MODERATOR = 1; // 版主(plate meta _aksrt_moderators)
const TIER_PLATE_AUTHOR = 2; // 超级版主(plate post_author)
const TIER_CAT_MOD = 3; // 分区版主(plate_cat term meta moderator)
const TIER_FORUM_ADMIN = 4; // 论坛管理员(bbs_admin_users + manage_options)
private static array $cap_cache = [];
private static array $tier_cache = [];
private ?AKSRT_Forum_Permission_Service $perm_service = null;
private ?AKSRT_Forum_Score_Service $score_service = null;
private ?AKSRT_Forum_Comment_Service $comment_service = null;
private ?AKSRT_Forum_Draft_Service $draft_svc = null;
private ?AKSRT_Forum_Board_Service $board_svc = null;
const VISIBILITY_PUBLIC = 'public';
const VISIBILITY_LOGIN = 'login';
const VISIBILITY_COMMENT = 'comment';
const VISIBILITY_ROLE = 'role';
const VISIBILITY_CREDITS = 'credits';
const VISIBILITY_PAY = 'pay';
const VISIBILITY_MODERATOR = 'moderator';
const REVIEW_APPROVED = 'approved';
const REVIEW_PENDING = 'pending';
const REVIEW_REJECTED = 'rejected';
const APPLICATION_PENDING = 'pending';
const APPLICATION_APPROVED = 'approved';
const APPLICATION_REJECTED = 'rejected';
const STICKY_NONE = 0;
const STICKY_PLATE = 1;
const STICKY_SUPER = 2;
const STICKY_GLOBAL = 3;
const BBS_TYPE_STANDARD = 'standard';
const BBS_TYPE_QUESTION = 'question';
const QUESTION_UNSOLVED = 0;
const QUESTION_SOLVED = 1;
public static function get_instance(): self {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function permission_service(): AKSRT_Forum_Permission_Service {
if (!$this->perm_service) {
$this->perm_service = new AKSRT_Forum_Permission_Service($this);
}
return $this->perm_service;
}
private function score_service(): AKSRT_Forum_Score_Service {
if (!$this->score_service) {
$this->score_service = new AKSRT_Forum_Score_Service($this);
}
return $this->score_service;
}
private function comment_service(): AKSRT_Forum_Comment_Service {
if (!$this->comment_service) {
$this->comment_service = new AKSRT_Forum_Comment_Service($this);
}
return $this->comment_service;
}
private function draft_service(): AKSRT_Forum_Draft_Service {
if (!$this->draft_svc) {
require_once __DIR__ . '/forum/class-aksrt-forum-draft-service.php';
$this->draft_svc = new AKSRT_Forum_Draft_Service($this);
}
return $this->draft_svc;
}
private ?AKSRT_Forum_Topic_Service $topic_svc = null;
private ?AKSRT_Forum_Moderation_Service $mod_svc = null;
private function moderation_service(): AKSRT_Forum_Moderation_Service {
if ($this->mod_svc === null) {
$this->mod_svc = new AKSRT_Forum_Moderation_Service($this);
}
return $this->mod_svc;
}
private ?AKSRT_Forum_View_Builder $view_builder = null;
private function view_builder(): AKSRT_Forum_View_Builder {
if ($this->view_builder === null) {
$this->view_builder = new AKSRT_Forum_View_Builder($this);
}
return $this->view_builder;
}
private function topic_service(): AKSRT_Forum_Topic_Service {
if ($this->topic_svc === null) {
$this->topic_svc = new AKSRT_Forum_Topic_Service($this);
}
return $this->topic_svc;
}
private function board_service(): AKSRT_Forum_Board_Service {
if (!$this->board_svc) {
$this->board_svc = new AKSRT_Forum_Board_Service($this);
}
return $this->board_svc;
}
public function is_plate_cpt_active(): bool {
// Plate CPT is the native board model; no option migration gate.
return post_type_exists('aksrt_forum_plate');
}
public function get_config(): array {
if (class_exists('AKSRT_Settings')) {
return AKSRT_Settings::get_forum_settings();
}
return ['enabled' => false];
}
public function get_boards(array $args = []): array {
return $this->board_service()->get_boards($args);
}
public function create_board(array $data): int {
return $this->board_service()->create_board($data);
}
public function update_board(int $board_id, array $data): bool {
return $this->board_service()->update_board($board_id, $data);
}
public function delete_board(int $board_id): bool {
return $this->board_service()->delete_board($board_id);
}
public function reorder_boards(array $order_map): bool {
return $this->board_service()->reorder_boards($order_map);
}
// §7.0 Plate CPT methods —板块 CPT 化 CRUD
public function get_plates(array $args = []): array {
return $this->board_service()->get_plates($args);
}
public function get_plate(int $plate_id): ?array {
return $this->board_service()->get_plate($plate_id);
}
public function build_plate_payload(\WP_Post $post): array {
return $this->board_service()->build_plate_payload($post);
}
public function create_plate(array $data): int {
return $this->board_service()->create_plate($data);
}
public function update_plate(int $plate_id, array $data): bool {
return $this->board_service()->update_plate($plate_id, $data);
}
public function delete_plate(int $plate_id, string $cascade = 'trash', int $move_to = 0): bool {
return $this->board_service()->delete_plate($plate_id, $cascade, $move_to);
}
public function reorder_plates(array $order_map): bool {
return $this->board_service()->reorder_plates($order_map);
}
public function get_topic_plate_id(int $topic_id): int {
return $this->board_service()->get_topic_plate_id($topic_id);
}
public function is_plate_moderator(int $user_id, int $plate_id): bool {
return $this->board_service()->is_plate_moderator($user_id, $plate_id);
}
public function get_plate_view(int $plate_id, array $args = []): array {
return $this->board_service()->get_plate_view($plate_id, $args);
}
public function get_topics(array $args = []): array {
$view = $this->get_topic_list($args);
return $view['items'];
}
public function get_topic_list(array $args = []): array {
return $this->view_builder()->get_topic_list($args);
}
public function get_home_view(int $user_id = 0): array {
return $this->view_builder()->get_home_view($user_id);
}
public function get_follow_stream(int $user_id, int $page = 1, int $limit = 15): array {
return $this->view_builder()->get_follow_stream($user_id, $page, $limit);
}
public function get_synthesis_stream(int $page = 1, int $limit = 15, int $viewer = 0): array {
return $this->view_builder()->get_synthesis_stream($page, $limit, $viewer);
}
public function get_pending_stream(int $user_id, int $page = 1, int $limit = 15): array {
return $this->view_builder()->get_pending_stream($user_id, $page, $limit);
}
public function ajax_home_tab(): void {
$this->view_builder()->ajax_home_tab();
}
public function render_topic_row(array $topic): void {
$this->view_builder()->render_topic_row($topic);
}
public function get_board_view(int $board_id, array $args = []): array {
return $this->board_service()->get_board_view($board_id, $args);
}
public function can_view_plate(int $user_id, int $plate_id, string $allow_view = ''): bool {
return $this->board_service()->can_view_plate($user_id, $plate_id, $allow_view);
}
public function can_compose_in_plate(int $user_id, int $plate_id): bool {
return $this->board_service()->can_compose_in_plate($user_id, $plate_id);
}
public function is_user_following_plate(int $user_id, int $plate_id): bool {
return $this->board_service()->is_user_following_plate($user_id, $plate_id);
}
public function toggle_follow_plate(int $user_id, int $plate_id): array {
return $this->board_service()->toggle_follow_plate($user_id, $plate_id);
}
public function get_user_followed_plates(int $user_id): array {
return $this->board_service()->get_user_followed_plates($user_id);
}
public function get_user_managed_plates(int $user_id): array {
return $this->board_service()->get_user_managed_plates($user_id);
}
public function get_user_forum_topics(int $user_id, array $args = []): array {
return $this->view_builder()->get_user_forum_topics($user_id, $args);
}
public function get_user_favorite_topics(int $user_id, int $page = 1, int $limit = 10): array {
return $this->view_builder()->get_user_favorite_topics($user_id, $page, $limit);
}
public function get_user_forum_stats(int $user_id): array {
return $this->view_builder()->get_user_forum_stats($user_id);
}
public function increment_plate_views(int $plate_id): void {
$this->board_service()->increment_plate_views($plate_id);
}
public function is_hot_plate(int $plate_id): bool {
return $this->board_service()->is_hot_plate($plate_id);
}
public function get_plate_categories(): array {
return $this->board_service()->get_plate_categories();
}
public function is_cat_moderator(int $user_id, int $cat_id): bool {
return $this->board_service()->is_cat_moderator($user_id, $cat_id);
}
public function get_sorted_plates(string $orderby = 'menu_order', string $order = 'ASC', int $limit = 50): array {
return $this->board_service()->get_sorted_plates($orderby, $order, $limit);
}
public function get_topic_view(int $topic_id, int $user_id = 0): array {
return $this->view_builder()->get_topic_view($topic_id, $user_id);
}
public function get_compose_view(int $user_id, array $args = []): array {
return $this->view_builder()->get_compose_view($user_id, $args);
}
public function get_stats(): array {
return $this->view_builder()->get_stats();
}
public function can_edit_topic(int $user_id, int $topic_id): bool {
return $this->topic_service()->can_edit_topic($user_id, $topic_id);
}
public function can_moderate_topic(int $user_id, int $topic_id): bool {
return $this->forum_user_can($user_id, 'topic_moderate', $topic_id);
}
public function update_topic(int $topic_id, array $data) {
return $this->topic_service()->update_topic($topic_id, $data);
}
public function get_tags(): array {
return $this->view_builder()->get_tags();
}
public function get_tag_archive_view(array $args = []): array {
return $this->view_builder()->get_tag_archive_view($args);
}
public function init(): void {
add_action('wp_ajax_aksrt_forum_update_topic', [$this, 'ajax_update_topic']);
add_action('wp_ajax_aksrt_forum_topic_list', [$this, 'ajax_topic_list']);
add_action('wp_ajax_aksrt_forum_create_topic', [$this, 'ajax_create_topic']);
add_action('wp_ajax_aksrt_forum_follow_plate', [$this, 'ajax_follow_plate']);
add_action('wp_ajax_aksrt_forum_unlock_topic', [$this, 'ajax_unlock_topic']);
// §7.4 draft persistence
add_action('wp_ajax_aksrt_forum_save_draft', [$this, 'ajax_save_draft']);
add_action('wp_ajax_aksrt_forum_load_draft', [$this, 'ajax_load_draft']);
add_action('wp_ajax_aksrt_forum_delete_draft', [$this, 'ajax_delete_draft']);
// §7.4 remote search selectors
add_action('wp_ajax_aksrt_forum_search_boards', [$this, 'ajax_search_boards']);
add_action('wp_ajax_nopriv_aksrt_forum_search_boards', [$this, 'ajax_search_boards']);
add_action('wp_ajax_aksrt_forum_search_tags', [$this, 'ajax_search_tags']);
add_action('wp_ajax_nopriv_aksrt_forum_search_tags', [$this, 'ajax_search_tags']);
add_action('wp_ajax_aksrt_forum_search_topics', [$this, 'ajax_search_topics']);
add_action('wp_ajax_nopriv_aksrt_forum_search_topics', [$this, 'ajax_search_topics']);
// §7.4 AJAX-based topic editing
add_action('wp_ajax_aksrt_forum_edit_topic', [$this, 'ajax_edit_topic']);
// §7.6 forum comment engine
add_action('wp_ajax_aksrt_forum_comments', [$this, 'ajax_forum_comments']);
add_action('wp_ajax_nopriv_aksrt_forum_comments', [$this, 'ajax_forum_comments']);
add_action('wp_ajax_aksrt_forum_comment_top', [$this, 'ajax_comment_topping']);
self::register_hide_shortcode();
// §7.10 forum home tab AJAX
add_action('wp_ajax_aksrt_forum_home_tab', [$this, 'ajax_home_tab']);
add_action('wp_ajax_nopriv_aksrt_forum_home_tab', [$this, 'ajax_home_tab']);
add_action('admin_init', [$this, 'maybe_migrate_boards'], 25);
add_filter('template_include', [$this, 'template_routing']);
add_action('wp', [$this, 'maybe_refresh_recommend_on_view']);
add_action('comment_post', [$this, 'on_forum_comment_posted'], 10, 3);
// §7.2 板块多维统计 hooks
add_action('save_post_aksrt_forum_topic', [$this, 'on_topic_saved_sync_plate'], 20, 2);
add_action('comment_post', [$this, 'on_comment_sync_plate_reply'], 25, 3);
add_action('wp_login', [$this, 'cap_cache_on_login'], 10, 2);
add_action('updated_post_meta', [$this, 'cap_cache_on_plate_meta'], 10, 3);
add_action('added_post_meta', [$this, 'cap_cache_on_plate_meta'], 10, 3);
add_action('deleted_post_meta', [$this, 'cap_cache_on_plate_meta'], 10, 3);
add_action('updated_term_meta', [$this, 'cap_cache_on_cat_meta'], 10, 3);
add_action('save_post_aksrt_forum_plate', [$this, 'cap_cache_on_plate_save'], 10, 1);
}
public function on_topic_saved_sync_plate(int $post_id, \WP_Post $post): void {
$this->moderation_service()->on_topic_saved_sync_plate($post_id, $post);
}
public function on_comment_sync_plate_reply(int $comment_id, $approved, array $commentdata): void {
$this->moderation_service()->on_comment_sync_plate_reply($comment_id, $approved, $commentdata);
}
public function template_routing(string $template): string {
return $this->view_builder()->template_routing($template);
}
public function update_topic_meta(int $topic_id, array $meta): bool {
return $this->topic_service()->update_topic_meta($topic_id, $meta);
}
public function is_moderator(int $user_id, int $topic_id): bool {
return $this->moderation_service()->is_moderator($user_id, $topic_id);
}
public function ajax_update_topic(): void {
$this->topic_service()->ajax_update_topic();
}
public function ajax_topic_list(): void {
$this->view_builder()->ajax_topic_list();
}
public function ajax_create_topic(): void {
$this->topic_service()->ajax_create_topic();
}
public function create_topic(int $user_id, array $data) {
return $this->topic_service()->create_topic($user_id, $data);
}
public function moderate_topic(int $topic_id, string $action, array $payload, int $operator_id = 0) {
return $this->topic_service()->moderate_topic($topic_id, $action, $payload, $operator_id);
}
public function submit_vote(int $topic_id, int $user_id, array $option_ids) {
return $this->topic_service()->submit_vote($topic_id, $user_id, $option_ids);
}
public function ajax_follow_plate(): void {
$this->board_service()->ajax_follow_plate();
}
public function ajax_unlock_topic(): void {
$this->topic_service()->ajax_unlock_topic();
}
public function apply_moderator(int $user_id, int $board_id, string $reason) {
return $this->moderation_service()->apply_moderator($user_id, $board_id, $reason);
}
public function review_moderator_application(string $application_id, string $status, string $note, int $reviewer_id) {
return $this->moderation_service()->review_moderator_application($application_id, $status, $note, $reviewer_id);
}
public function get_moderator_application_list(array $args = []): array {
return $this->moderation_service()->get_moderator_application_list($args);
}
public function sync_board_count(int $board_id): void {
$this->moderation_service()->sync_board_count($board_id);
}
public function sync_plate_counts(int $plate_id): void {
$this->moderation_service()->sync_plate_counts($plate_id);
}
public function get_board_moderators(int $board_id): array {
return $this->moderation_service()->get_board_moderators($board_id);
}
public function get_plate_moderators(int $plate_id): array {
return $this->moderation_service()->get_plate_moderators($plate_id);
}
public function is_forum_admin(int $user_id): bool {
return $this->moderation_service()->is_forum_admin($user_id);
}
public function is_board_moderator(int $user_id, int $board_id): bool {
return $this->moderation_service()->is_board_moderator($user_id, $board_id);
}
public function get_board_moderator_profiles(int $board_id): array {
return $this->moderation_service()->get_board_moderator_profiles($board_id);
}
public function get_board_moderator_profiles_with_roles(int $board_id): array {
return $this->moderation_service()->get_board_moderator_profiles_with_roles($board_id);
}
public function get_moderator_roles(int $board_id): array {
return $this->moderation_service()->get_moderator_roles($board_id);
}
public function set_moderator_role(int $user_id, int $board_id, string $role): bool {
return $this->moderation_service()->set_moderator_role($user_id, $board_id, $role);
}
public function add_moderator(int $user_id, int $board_id, string $role = 'moderator'): bool {
return $this->moderation_service()->add_moderator($user_id, $board_id, $role);
}
public function remove_moderator(int $user_id, int $board_id): bool {
return $this->moderation_service()->remove_moderator($user_id, $board_id);
}
public function get_user_moderator_boards(int $user_id): array {
return $this->moderation_service()->get_user_moderator_boards($user_id);
}
public function has_moderator_role(int $user_id, int $board_id, string $min_role = 'moderator'): bool {
return $this->moderation_service()->has_moderator_role($user_id, $board_id, $min_role);
}
public function get_board_moderator_applications(int $board_id): array {
return $this->moderation_service()->get_board_moderator_applications($board_id);
}
public function get_plate_moderator_applications(int $plate_id): array {
return $this->moderation_service()->get_plate_moderator_applications($plate_id);
}
public function get_board_application_for_user(int $user_id, int $board_id): ?array {
return $this->moderation_service()->get_board_application_for_user($user_id, $board_id);
}
public function get_visibility_options(): array {
return $this->topic_service()->get_visibility_options();
}
public function get_review_options(): array {
return $this->topic_service()->get_review_options();
}
public function can_user_publish_directly(int $user_id, int $board_id = 0): bool {
return $this->topic_service()->can_user_publish_directly($user_id, $board_id);
}
public function get_sticky_topics_for_board(int $board_id): array {
return $this->view_builder()->get_sticky_topics_for_board($board_id);
}
public function get_topic_detail(int $topic_id, int $viewer_user_id = 0): array {
return $this->view_builder()->get_topic_detail($topic_id, $viewer_user_id);
}
public function increment_view_count(int $topic_id): void {
$this->view_builder()->increment_view_count($topic_id);
}
public function maybe_migrate_boards(): void {
$this->board_service()->maybe_migrate_boards();
}
public function build_topic_payload(WP_Post $post, int $viewer_user_id = 0): array {
return $this->topic_service()->build_topic_payload($post, $viewer_user_id);
}
public function unlock_topic_with_credits(int $user_id, int $topic_id): array {
return $this->topic_service()->unlock_topic_with_credits($user_id, $topic_id);
}
public function prepare_vote_meta(array $data): array {
return $this->topic_service()->prepare_vote_meta($data);
}
public function save_vote_meta(int $topic_id, array $vote_meta): void {
$this->topic_service()->save_vote_meta($topic_id, $vote_meta);
}
public function normalize_post_status_query(string $status) {
return $this->topic_service()->normalize_post_status_query($status);
}
private function build_user_summary(int $user_id): array {
return $this->topic_service()->build_user_summary($user_id);
}
private function get_user_avatar_url(int $user_id): string {
return $this->topic_service()->get_user_avatar_url($user_id);
}
public function save_cover_meta(int $post_id, array $data): void {
$this->topic_service()->save_cover_meta($post_id, $data);
}
public function split_tags(string $tags): array {
return $this->topic_service()->split_tags($tags);
}
private function get_visibility_map(): array {
return $this->topic_service()->get_visibility_map();
}
private function get_review_map(): array {
return $this->topic_service()->get_review_map();
}
private function get_visibility_label(string $visibility): string {
return $this->topic_service()->get_visibility_label($visibility);
}
private function get_review_label(string $review_status): string {
return $this->topic_service()->get_review_label($review_status);
}
public function is_favorited(int $user_id, int $topic_id): bool {
return $this->score_service()->is_favorited($user_id, $topic_id);
}
public function toggle_favorite(int $user_id, int $topic_id) {
return $this->score_service()->toggle_favorite($user_id, $topic_id);
}
public function score_topic(int $user_id, int $topic_id, int $amount) {
return $this->score_service()->score_topic($user_id, $topic_id, $amount);
}
public function get_score_detail(int $topic_id): array {
return $this->score_service()->get_score_detail($topic_id);
}
public function calculate_recommend_score(int $topic_id): float {
return $this->score_service()->calculate_recommend_score($topic_id);
}
public function refresh_recommend_score(int $topic_id): float {
return $this->score_service()->refresh_recommend_score($topic_id);
}
public function batch_refresh_recommend_scores(int $limit = 100): int {
return $this->score_service()->batch_refresh_recommend_scores($limit);
}
public function maybe_refresh_recommend_on_view(): void {
$this->score_service()->maybe_refresh_recommend_on_view();
}
public function notify(int $user_id, string $type, string $content, array $data = []): void {
$this->score_service()->notify($user_id, $type, $content, $data);
}
public function notify_topic_pending(int $topic_id, int $author_id): void {
$this->score_service()->notify_topic_pending($topic_id, $author_id);
}
public function notify_moderation_result(int $topic_id, string $action, int $operator_id): void {
$this->score_service()->notify_moderation_result($topic_id, $action, $operator_id);
}
public function notify_topic_reply(int $topic_id, int $commenter_id): void {
$this->score_service()->notify_topic_reply($topic_id, $commenter_id);
}
public function notify_topic_scored(int $topic_id, int $scorer_id, int $amount): void {
$this->score_service()->notify_topic_scored($topic_id, $scorer_id, $amount);
}
const COMMENT_TOP_NONE = 0;
const COMMENT_TOP_NORMAL = 1;
const COMMENT_TOP_HOT = 2;
const COMMENT_TOP_BEST = 3;
public function on_forum_comment_posted(int $comment_id, $approved, array $commentdata = []): void {
$this->score_service()->on_forum_comment_posted($comment_id, $approved, $commentdata);
}
public function ajax_forum_comments(): void {
$this->comment_service()->ajax_forum_comments();
}
public function ajax_comment_topping(): void {
$this->comment_service()->ajax_comment_topping();
}
public function render_forum_comments(array $comments, int $topic_id, int $adopted_id = 0): void {
$this->comment_service()->render_forum_comments($comments, $topic_id, $adopted_id);
}
public function adopt_answer(int $topic_id, int $comment_id, int $operator_id) {
return $this->comment_service()->adopt_answer($topic_id, $comment_id, $operator_id);
}
public function get_adopted_comment_id(int $topic_id): int {
return $this->comment_service()->get_adopted_comment_id($topic_id);
}
public function get_forum_comments(int $topic_id, string $sort = 'newest', bool $author_only = false, int $page = 1, int $per_page = 30): array {
return $this->comment_service()->get_forum_comments($topic_id, $sort, $author_only, $page, $per_page);
}
public function set_comment_topping(int $comment_id, int $level): bool {
return $this->comment_service()->set_comment_topping($comment_id, $level);
}
public function maybe_mark_hot_comment(int $comment_id): bool {
return $this->comment_service()->maybe_mark_hot_comment($comment_id);
}
public function is_hot_comment(int $comment_id): bool {
return $this->comment_service()->is_hot_comment($comment_id);
}
public function get_commenter_badge(int $user_id, int $topic_id): ?array {
return $this->comment_service()->get_commenter_badge($user_id, $topic_id);
}
public function save_draft(int $user_id, array $data) {
return $this->draft_service()->save_draft($user_id, $data);
}
public function get_user_draft_count(int $user_id): int {
return $this->draft_service()->get_user_draft_count($user_id);
}
public function get_user_drafts(int $user_id, int $limit = 20): array {
return $this->draft_service()->get_user_drafts($user_id, $limit);
}
public function delete_draft(int $user_id, int $draft_id): bool {
return $this->draft_service()->delete_draft($user_id, $draft_id);
}
public function load_draft_data(int $user_id, int $draft_id): ?array {
return $this->draft_service()->load_draft_data($user_id, $draft_id);
}
public function ajax_save_draft(): void {
$this->draft_service()->ajax_save_draft();
}
public function ajax_load_draft(): void {
$this->draft_service()->ajax_load_draft();
}
public function ajax_delete_draft(): void {
$this->draft_service()->ajax_delete_draft();
}
public function ajax_search_boards(): void {
$this->view_builder()->ajax_search_boards();
}
public function ajax_search_tags(): void {
$this->view_builder()->ajax_search_tags();
}
public function ajax_search_topics(): void {
$this->view_builder()->ajax_search_topics();
}
public function ajax_edit_topic(): void {
$this->topic_service()->ajax_edit_topic();
}
public function get_compose_capabilities(int $user_id): array {
return $this->permission_service()->get_compose_capabilities($user_id);
}
public function sanitize_topic_content(int $user_id, string $content): string {
return $this->topic_service()->sanitize_topic_content($user_id, $content);
}
public static function register_hide_shortcode(): void {
add_shortcode('aksrt_hide', [AKSRT_Forum_Topic_Service::class, 'render_hide_shortcode']);
}
public function publish_draft(int $user_id, int $draft_id, array $data) {
return $this->draft_service()->publish_draft($user_id, $draft_id, $data);
}
//
// 四级层级(对标 zibll):
// TIER_FORUM_ADMIN (4) — bbs_admin_users + manage_options
// TIER_CAT_MOD (3) — aksrt_plate_cat term meta 'moderator'
// TIER_PLATE_AUTHOR(2) — plate CPT post_author(超级版主)
// TIER_MODERATOR (1) — plate CPT post meta '_aksrt_moderators' list
//
// 公开 API:
// forum_user_can( $uid, $cap, $context_id = 0 ): bool
// get_user_plate_tier( $uid, $plate_id ): int
// flush_cap_cache( $uid = 0 ): void
public function get_user_plate_tier(int $user_id, int $plate_id): int {
return $this->permission_service()->get_user_plate_tier($user_id, $plate_id);
}
public function forum_user_can(int $user_id, string $cap, int $context_id = 0): bool {
return $this->permission_service()->forum_user_can($user_id, $cap, $context_id);
}
public function flush_cap_cache(int $user_id = 0): void {
$this->permission_service()->flush_cap_cache($user_id);
}
public function cap_cache_on_login(string $user_login, \WP_User $user): void {
$this->permission_service()->cap_cache_on_login($user_login, $user);
}
public function cap_cache_on_plate_meta(int $meta_id, int $object_id, string $meta_key): void {
$this->permission_service()->cap_cache_on_plate_meta($meta_id, $object_id, $meta_key);
}
public function cap_cache_on_cat_meta(int $meta_id, int $object_id, string $meta_key): void {
$this->permission_service()->cap_cache_on_cat_meta($meta_id, $object_id, $meta_key);
}
public function cap_cache_on_plate_save(int $post_id): void {
$this->permission_service()->cap_cache_on_plate_save($post_id);
}
}