Extract shared comment helpers (content/item/form/geo/actions), port GIF [g=] smilies + FixedInput/moveForm UX, wire close_comments/city/quick settings, REST comment get, and align product review chrome with zibll.
422 lines
21 KiB
PHP
422 lines
21 KiB
PHP
<?php
|
||
/**
|
||
* AKSRT Theme Core Hooks
|
||
*
|
||
* 从 functions.php 中抽离的核心功能钩子:
|
||
* - Gravatar 头像源替换(4层拦截)
|
||
* - SMTP 邮件配置注入
|
||
* - 评论开关控制
|
||
* - Banner CPT 注册
|
||
* - Admin Bar 隐藏
|
||
*
|
||
* @package AKSRT
|
||
* @version 3.2.0
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
// ============================================================
|
||
// 评论功能开关
|
||
// ============================================================
|
||
|
||
add_filter('comments_open', function ($open, $post_id) {
|
||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||
$display = \AKSRT\Settings\Settings::get_comment_display_settings();
|
||
if (!empty($display['close_comments'])) {
|
||
return false;
|
||
}
|
||
}
|
||
if (!get_option('aksrt_comment_enabled', true)) {
|
||
return false;
|
||
}
|
||
return $open;
|
||
}, 10, 2);
|
||
|
||
add_filter('comment_text', function ($comment_text, $comment = null, $args = []) {
|
||
if (function_exists('aksrt_render_comment_content')) {
|
||
return aksrt_render_comment_content((string) $comment_text);
|
||
}
|
||
return $comment_text;
|
||
}, 20, 3);
|
||
|
||
// ============================================================
|
||
// 注册自定义文章类型 - Banner (REST API for SPA)
|
||
// ============================================================
|
||
|
||
function aksrt_register_banner_cpt() {
|
||
register_post_type('aksrt_banner', array(
|
||
'labels' => 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);
|
||
}
|
||
}
|
||
});
|
||
|
||
// ============================================================
|