array( 'name' => __('Banners', 'aksrt'), 'singular_name' => __('Banner', 'aksrt'), ), 'public' => false, 'show_ui' => false, 'show_in_rest' => true, 'supports' => array('title'), 'menu_icon' => 'dashicons-images-alt2', 'capability_type' => 'post', 'capabilities' => array('create_posts' => 'manage_options'), 'map_meta_cap' => true, )); } add_action('init', 'aksrt_register_banner_cpt'); // ============================================================ // §3.7 Register Topics taxonomy for posts (专题分类) // ============================================================ function aksrt_register_topics_taxonomy() { register_taxonomy('topics', 'post', [ 'labels' => [ 'name' => __('专题', 'aksrt'), 'singular_name' => __('专题', 'aksrt'), 'search_items' => __('搜索专题', 'aksrt'), 'all_items' => __('所有专题', 'aksrt'), 'edit_item' => __('编辑专题', 'aksrt'), 'add_new_item' => __('添加专题', 'aksrt'), 'menu_name' => __('专题', 'aksrt'), ], 'hierarchical' => true, 'public' => true, 'show_in_rest' => true, 'show_admin_column' => true, 'rewrite' => ['slug' => 'topics'], ]); } add_action('init', 'aksrt_register_topics_taxonomy'); // ============================================================ // 注册自定义文章类型 - Forum Topic & 分类法 - Forum Board // ============================================================ function aksrt_register_forum_cpt() { // Respect bbs_s switch — skip CPT registration when forum is disabled. // Admin context always registers so the backend settings page works. if (!is_admin() && class_exists('\AKSRT\Settings\Settings')) { $forum = \AKSRT\Settings\Settings::get_forum_settings(); if (empty($forum['enabled'])) { return; } } // Read custom slugs / names from settings when available $plate_slug = 'board'; $topic_slug = 'topic'; $forum_enabled = true; $forum_settings = []; if (class_exists('\AKSRT\Settings\Settings')) { $forum_settings = \AKSRT\Settings\Settings::get_forum_settings(); $plate_slug = !empty($forum_settings['other']['plate_slug']) ? $forum_settings['other']['plate_slug'] : 'board'; $topic_slug = !empty($forum_settings['other']['posts_slug']) ? $forum_settings['other']['posts_slug'] : 'topic'; $forum_enabled = !empty($forum_settings['enabled']); } // Admin always registers types; menu follows bbs_s (zibll: show when forum on). $forum_show_menu = is_admin() ? $forum_enabled : false; $names = !empty($forum_settings['names']) ? $forum_settings['names'] : []; $forum_label = sanitize_text_field((string) ($names['forum'] ?? __('论坛', 'aksrt'))); $posts_label = sanitize_text_field((string) ($names['posts'] ?? __('帖子', 'aksrt'))); $topic_label = sanitize_text_field((string) ($names['topic'] ?? __('话题', 'aksrt'))); $tag_label = sanitize_text_field((string) ($names['tag'] ?? __('标签', 'aksrt'))); // Legacy board taxonomy: keep rewrite/bridge, hide from admin (plate CPT is canonical). register_taxonomy('aksrt_forum_board', 'aksrt_forum_topic', [ 'labels' => [ 'name' => __('论坛版块', 'aksrt'), 'singular_name' => __('版块', 'aksrt'), 'search_items' => __('搜索版块', 'aksrt'), 'all_items' => __('所有版块', 'aksrt'), 'edit_item' => __('编辑版块', 'aksrt'), 'add_new_item' => __('添加版块', 'aksrt'), ], 'hierarchical' => true, 'public' => true, 'show_ui' => false, 'show_in_menu' => false, 'show_in_rest' => true, 'show_admin_column' => false, 'rewrite' => ['slug' => $plate_slug], ]); // Forum Tag taxonomy register_taxonomy('aksrt_forum_tag', 'aksrt_forum_topic', [ 'labels' => [ 'name' => sprintf(/* translators: %s: forum name */ __('%s标签', 'aksrt'), $forum_label), 'singular_name' => $tag_label, 'search_items' => sprintf(/* translators: %s: tag name */ __('搜索%s', 'aksrt'), $tag_label), 'all_items' => sprintf(/* translators: %s: tag name */ __('所有%s', 'aksrt'), $tag_label), 'edit_item' => sprintf(/* translators: %s: tag name */ __('编辑%s', 'aksrt'), $tag_label), 'add_new_item' => sprintf(/* translators: %s: tag name */ __('添加%s', 'aksrt'), $tag_label), 'menu_name' => $tag_label, ], 'hierarchical' => false, 'public' => true, 'show_ui' => true, 'show_in_menu' => $forum_show_menu, 'show_in_rest' => true, 'show_admin_column' => true, 'rewrite' => ['slug' => 'forum-tag'], ]); // Forum Topic taxonomy (话题,单选,区别于标签) register_taxonomy('aksrt_forum_topic_cat', 'aksrt_forum_topic', [ 'labels' => [ 'name' => sprintf(/* translators: %s: forum name */ __('%s话题', 'aksrt'), $forum_label), 'singular_name' => $topic_label, 'search_items' => sprintf(/* translators: %s: topic name */ __('搜索%s', 'aksrt'), $topic_label), 'all_items' => sprintf(/* translators: %s: topic name */ __('所有%s', 'aksrt'), $topic_label), 'edit_item' => sprintf(/* translators: %s: topic name */ __('编辑%s', 'aksrt'), $topic_label), 'add_new_item' => sprintf(/* translators: %s: topic name */ __('添加%s', 'aksrt'), $topic_label), 'menu_name' => $topic_label, ], 'hierarchical' => false, 'public' => true, 'show_ui' => true, 'show_in_menu' => $forum_show_menu, 'show_in_rest' => true, 'show_admin_column' => true, 'rewrite' => ['slug' => 'forum-topic'], ]); // Forum Topic CPT — native sidebar (zibll: forum_post @ pos 40) register_post_type('aksrt_forum_topic', [ 'labels' => [ 'name' => $forum_label . $posts_label, 'singular_name' => $posts_label, 'add_new' => sprintf(/* translators: %s: posts name */ __('添加%s', 'aksrt'), $posts_label), 'add_new_item' => sprintf(/* translators: %s: posts name */ __('发布新%s', 'aksrt'), $posts_label), 'edit_item' => sprintf(/* translators: %s: posts name */ __('编辑%s', 'aksrt'), $posts_label), 'view_item' => sprintf(/* translators: %s: posts name */ __('查看%s', 'aksrt'), $posts_label), 'all_items' => sprintf(/* translators: %s: posts name */ __('所有%s', 'aksrt'), $posts_label), 'menu_name' => $forum_label . $posts_label, ], 'public' => true, 'show_ui' => true, 'show_in_menu' => $forum_show_menu, 'show_in_rest' => true, 'has_archive' => true, 'menu_position' => 40, 'menu_icon' => 'dashicons-buddicons-topics', 'supports' => ['title', 'editor', 'author', 'comments', 'thumbnail', 'excerpt'], 'capability_type' => 'post', 'rewrite' => ['slug' => $topic_slug], ]); } add_action('init', 'aksrt_register_forum_cpt'); // ============================================================ // 注册板块 CPT (aksrt_forum_plate) + 板块分区 taxonomy (aksrt_plate_cat) // §7.0 plate CPT 脚手架:板块从 taxonomy 迁移为独立 CPT, // 支持作者(超级版主)、正文/摘要/封面、层级父子、独立 meta 扩展位。 // ============================================================ function aksrt_register_forum_plate_cpt() { if (!is_admin() && class_exists('\AKSRT\Settings\Settings')) { $forum = \AKSRT\Settings\Settings::get_forum_settings(); if (empty($forum['enabled'])) { return; } } $plate_slug = 'board'; $forum_enabled = true; $forum = []; if (class_exists('\AKSRT\Settings\Settings')) { $forum = \AKSRT\Settings\Settings::get_forum_settings(); $plate_slug = !empty($forum['other']['plate_slug']) ? $forum['other']['plate_slug'] : 'board'; $forum_enabled = !empty($forum['enabled']); } $forum_show_menu = is_admin() ? $forum_enabled : false; $names = !empty($forum['names']) ? $forum['names'] : []; $forum_label = sanitize_text_field((string) ($names['forum'] ?? __('论坛', 'aksrt'))); $plate_label = sanitize_text_field((string) ($names['plate'] ?? __('版块', 'aksrt'))); // Plate category taxonomy (分区) register_taxonomy('aksrt_plate_cat', 'aksrt_forum_plate', [ 'labels' => [ 'name' => sprintf(/* translators: %s: plate name */ __('%s分区', 'aksrt'), $plate_label), 'singular_name' => __('分区', 'aksrt'), 'search_items' => __('搜索分区', 'aksrt'), 'all_items' => __('所有分区', 'aksrt'), 'edit_item' => __('编辑分区', 'aksrt'), 'add_new_item' => __('添加分区', 'aksrt'), 'menu_name' => __('分区', 'aksrt'), ], 'hierarchical' => true, 'public' => true, 'show_ui' => true, 'show_in_menu' => $forum_show_menu, 'show_in_rest' => true, 'show_admin_column' => true, 'rewrite' => ['slug' => 'plate-cat'], ]); // Plate CPT (板块) — native sidebar (zibll: plate @ pos 40) register_post_type('aksrt_forum_plate', [ 'labels' => [ 'name' => $forum_label . $plate_label, 'singular_name' => $plate_label, 'add_new' => sprintf(/* translators: %s: plate name */ __('添加%s', 'aksrt'), $plate_label), 'add_new_item' => sprintf(/* translators: %s: plate name */ __('创建%s', 'aksrt'), $plate_label), 'edit_item' => sprintf(/* translators: %s: plate name */ __('编辑%s', 'aksrt'), $plate_label), 'view_item' => sprintf(/* translators: %s: plate name */ __('查看%s', 'aksrt'), $plate_label), 'search_items' => sprintf(/* translators: %s: plate name */ __('搜索%s', 'aksrt'), $plate_label), 'not_found' => sprintf(/* translators: %s: plate name */ __('未找到%s', 'aksrt'), $plate_label), 'not_found_in_trash' => sprintf(/* translators: %s: plate name */ __('回收站中未找到%s', 'aksrt'), $plate_label), 'all_items' => sprintf(/* translators: %s: plate name */ __('所有%s', 'aksrt'), $plate_label), 'menu_name' => $forum_label . $plate_label, ], 'public' => true, 'hierarchical' => true, 'show_ui' => true, 'show_in_menu' => $forum_show_menu, 'show_in_rest' => true, 'has_archive' => false, 'menu_position' => 40, 'menu_icon' => 'dashicons-buddicons-forums', 'supports' => ['title', 'editor', 'author', 'excerpt', 'thumbnail', 'page-attributes'], 'capability_type' => 'post', 'rewrite' => ['slug' => $plate_slug, 'with_front' => false], ]); // Keep aksrt_forum_topic assignable to plates via taxonomy bridge register_taxonomy_for_object_type('aksrt_forum_board', 'aksrt_forum_topic'); } add_action('init', 'aksrt_register_forum_plate_cpt'); // ============================================================ // §7.0 forum_post CPT 对齐:注册帖子 meta 扩展位地基 // 为 aksrt_forum_topic 注册全部 meta key,提供类型安全 + REST 暴露。 // ============================================================ function aksrt_register_forum_topic_meta() { $post_type = 'aksrt_forum_topic'; $meta_fields = [ // 基础治理 meta (已有,补注册) '_aksrt_visibility' => ['type' => 'string', 'default' => 'public'], '_aksrt_review_status' => ['type' => 'string', 'default' => ''], '_aksrt_sticky' => ['type' => 'integer', 'default' => 0], '_aksrt_featured' => ['type' => 'integer', 'default' => 0], '_aksrt_locked' => ['type' => 'integer', 'default' => 0], '_aksrt_highlight' => ['type' => 'string', 'default' => ''], '_aksrt_views' => ['type' => 'integer', 'default' => 0], '_aksrt_moderation_note' => ['type' => 'string', 'default' => ''], '_aksrt_moderated_by' => ['type' => 'integer', 'default' => 0], '_aksrt_moderated_at' => ['type' => 'string', 'default' => ''], // 帖子类型 + 问答状态 (Wave3) '_aksrt_bbs_type' => ['type' => 'string', 'default' => 'standard'], '_aksrt_question_status' => ['type' => 'integer', 'default' => 0], '_aksrt_adopted_comment' => ['type' => 'integer', 'default' => 0], // 投票 (已有,补注册) '_aksrt_vote_enabled' => ['type' => 'integer', 'default' => 0], '_aksrt_vote_title' => ['type' => 'string', 'default' => ''], '_aksrt_vote_multiple' => ['type' => 'integer', 'default' => 0], '_aksrt_vote_type' => ['type' => 'string', 'default' => 'standard'], '_aksrt_vote_expiry_days' => ['type' => 'integer', 'default' => 0], // 评分 (Wave3) '_aksrt_score' => ['type' => 'integer', 'default' => 0], '_aksrt_recommend_score' => ['type' => 'number', 'default' => 0], '_aksrt_hot_rewarded' => ['type' => 'integer', 'default' => 0], // 收藏 (Wave3) '_aksrt_favorite_count' => ['type' => 'integer', 'default' => 0], // 封面扩展位(论坛帖子封面;前台 forum-topic 渲染) '_aksrt_cover_type' => ['type' => 'string', 'default' => ''], '_aksrt_cover_image' => ['type' => 'string', 'default' => ''], '_aksrt_featured_slide' => ['type' => 'array', 'default' => []], '_aksrt_featured_video' => ['type' => 'string', 'default' => ''], '_aksrt_cover_ratio' => ['type' => 'string', 'default' => '16:9'], // 付费内容扩展位(论坛帖子付费门槛;前台 forum-topic 渲染) '_aksrt_allow_view' => ['type' => 'string', 'default' => 'public'], '_aksrt_pay_price' => ['type' => 'number', 'default' => 0], '_aksrt_pay_vip_price' => ['type' => 'number', 'default' => 0], // legacy single VIP '_aksrt_pay_vip1_price' => ['type' => 'number', 'default' => 0], '_aksrt_pay_vip2_price' => ['type' => 'number', 'default' => 0], '_aksrt_pay_credits' => ['type' => 'integer', 'default' => 0], // legacy alias of credits_cost '_aksrt_credits_cost' => ['type' => 'integer', 'default' => 0], // runtime unlock price '_aksrt_credits_vip1' => ['type' => 'integer', 'default' => 0], '_aksrt_credits_vip2' => ['type' => 'integer', 'default' => 0], '_aksrt_pay_hide_part' => ['type' => 'integer', 'default' => 0], '_aksrt_virtual_sales' => ['type' => 'integer', 'default' => 0], '_aksrt_topic_coupon_s' => ['type' => 'integer', 'default' => 0], '_aksrt_visibility_roles' => ['type' => 'array', 'default' => []], // 状态工作流扩展位 (Wave4) '_aksrt_closed' => ['type' => 'integer', 'default' => 0], '_aksrt_hidden' => ['type' => 'integer', 'default' => 0], // 板块 CPT 关联 (§7.0 新增) '_aksrt_plate_id' => ['type' => 'integer', 'default' => 0], ]; foreach ($meta_fields as $key => $args) { $schema = [ 'type' => $args['type'], 'description' => $key, 'single' => true, 'default' => $args['default'], 'show_in_rest' => false, ]; if ($args['type'] === 'array') { $schema['show_in_rest'] = false; $schema['type'] = 'array'; } register_post_meta($post_type, $key, $schema); } // Plate CPT meta registration $plate_meta = [ '_aksrt_sort_order' => ['type' => 'integer', 'default' => 0], '_aksrt_icon' => ['type' => 'string', 'default' => ''], '_aksrt_moderators' => ['type' => 'array', 'default' => []], '_aksrt_moderator_roles' => ['type' => 'array', 'default' => []], '_aksrt_posts_count' => ['type' => 'integer', 'default' => 0], '_aksrt_reply_count' => ['type' => 'integer', 'default' => 0], '_aksrt_today_reply_count' => ['type' => 'integer', 'default' => 0], '_aksrt_plate_views' => ['type' => 'integer', 'default' => 0], '_aksrt_follow_count' => ['type' => 'integer', 'default' => 0], '_aksrt_last_reply' => ['type' => 'string', 'default' => ''], '_aksrt_last_post' => ['type' => 'string', 'default' => ''], '_aksrt_allow_view' => ['type' => 'string', 'default' => 'public'], '_aksrt_add_limit' => ['type' => 'integer', 'default' => 0], '_aksrt_follow_pay' => ['type' => 'integer', 'default' => 0], '_aksrt_follow_pay_modo' => ['type' => 'string', 'default' => 'money'], '_aksrt_follow_pay_price' => ['type' => 'number', 'default' => 0], '_aksrt_follow_pay_points' => ['type' => 'integer', 'default' => 0], '_aksrt_follow_pay_vip_price' => ['type' => 'number', 'default' => 0], // legacy read fallback → vip1 '_aksrt_follow_pay_vip1_price' => ['type' => 'number', 'default' => 0], '_aksrt_follow_pay_vip2_price' => ['type' => 'number', 'default' => 0], '_aksrt_follow_pay_coupon_s' => ['type' => 'integer', 'default' => 0], ]; foreach ($plate_meta as $key => $args) { register_post_meta('aksrt_forum_plate', $key, [ 'type' => $args['type'] === 'array' ? 'array' : $args['type'], 'description' => $key, 'single' => true, 'default' => $args['default'], 'show_in_rest' => false, ]); } } add_action('init', 'aksrt_register_forum_topic_meta'); // Include forum topics in frontend search results (§7.10). add_action('pre_get_posts', function ($query) { if (!is_admin() && $query->is_main_query() && $query->is_search()) { $post_types = $query->get('post_type'); if (empty($post_types) || $post_types === 'post') { $query->set('post_type', ['post', 'page', 'aksrt_forum_topic']); } elseif (is_array($post_types) && !in_array('aksrt_forum_topic', $post_types, true)) { $post_types[] = 'aksrt_forum_topic'; $query->set('post_type', $post_types); } } }); // ============================================================