导入 AKSRT 主题开发源码
This commit is contained in:
1 parent
9681dd3d48
commit
1268a55dd0
595 files changed
+127705
No files matched your search
@@ -0,0 +1,362 @@
|
||||
<?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 (!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')) {
|
||||
$forum = AKSRT_Settings::get_forum_settings();
|
||||
if (empty($forum['enabled'])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Read custom slugs from settings when available
|
||||
$plate_slug = 'board';
|
||||
$topic_slug = 'topic';
|
||||
if (class_exists('AKSRT_Settings')) {
|
||||
$forum = AKSRT_Settings::get_forum_settings();
|
||||
$plate_slug = !empty($forum['other']['plate_slug']) ? $forum['other']['plate_slug'] : 'board';
|
||||
$topic_slug = !empty($forum['other']['posts_slug']) ? $forum['other']['posts_slug'] : 'topic';
|
||||
}
|
||||
|
||||
// Forum Board taxonomy
|
||||
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_in_rest' => true,
|
||||
'show_admin_column' => true,
|
||||
'rewrite' => ['slug' => $plate_slug],
|
||||
]);
|
||||
|
||||
// Forum Tag taxonomy
|
||||
register_taxonomy('aksrt_forum_tag', 'aksrt_forum_topic', [
|
||||
'labels' => [
|
||||
'name' => __('论坛标签', 'aksrt'),
|
||||
'singular_name' => __('标签', 'aksrt'),
|
||||
'search_items' => __('搜索标签', 'aksrt'),
|
||||
'all_items' => __('所有标签', 'aksrt'),
|
||||
'edit_item' => __('编辑标签', 'aksrt'),
|
||||
'add_new_item' => __('添加标签', 'aksrt'),
|
||||
],
|
||||
'hierarchical' => false,
|
||||
'public' => true,
|
||||
'show_in_rest' => true,
|
||||
'show_admin_column' => false,
|
||||
'rewrite' => ['slug' => 'forum-tag'],
|
||||
]);
|
||||
|
||||
// Forum Topic taxonomy (话题,单选,区别于标签)
|
||||
register_taxonomy('aksrt_forum_topic_cat', 'aksrt_forum_topic', [
|
||||
'labels' => [
|
||||
'name' => __('论坛话题', 'aksrt'),
|
||||
'singular_name' => __('话题', 'aksrt'),
|
||||
'search_items' => __('搜索话题', 'aksrt'),
|
||||
'all_items' => __('所有话题', 'aksrt'),
|
||||
'edit_item' => __('编辑话题', 'aksrt'),
|
||||
'add_new_item' => __('添加话题', 'aksrt'),
|
||||
],
|
||||
'hierarchical' => false,
|
||||
'public' => true,
|
||||
'show_in_rest' => true,
|
||||
'show_admin_column' => true,
|
||||
'rewrite' => ['slug' => 'forum-topic'],
|
||||
]);
|
||||
|
||||
// Forum Topic CPT
|
||||
register_post_type('aksrt_forum_topic', [
|
||||
'labels' => [
|
||||
'name' => __('论坛主题', 'aksrt'),
|
||||
'singular_name' => __('主题', 'aksrt'),
|
||||
'add_new_item' => __('发布新主题', 'aksrt'),
|
||||
'edit_item' => __('编辑主题', 'aksrt'),
|
||||
'view_item' => __('查看主题', 'aksrt'),
|
||||
],
|
||||
'public' => true,
|
||||
'show_in_rest' => true,
|
||||
'has_archive' => true,
|
||||
'menu_icon' => 'dashicons-comments',
|
||||
'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')) {
|
||||
$forum = AKSRT_Settings::get_forum_settings();
|
||||
if (empty($forum['enabled'])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$plate_slug = 'board';
|
||||
if (class_exists('AKSRT_Settings')) {
|
||||
$forum = AKSRT_Settings::get_forum_settings();
|
||||
$plate_slug = !empty($forum['other']['plate_slug']) ? $forum['other']['plate_slug'] : 'board';
|
||||
}
|
||||
|
||||
// Plate category taxonomy (分区)
|
||||
register_taxonomy('aksrt_plate_cat', 'aksrt_forum_plate', [
|
||||
'labels' => [
|
||||
'name' => __('板块分区', 'aksrt'),
|
||||
'singular_name' => __('分区', 'aksrt'),
|
||||
'search_items' => __('搜索分区', 'aksrt'),
|
||||
'all_items' => __('所有分区', 'aksrt'),
|
||||
'edit_item' => __('编辑分区', 'aksrt'),
|
||||
'add_new_item' => __('添加分区', 'aksrt'),
|
||||
],
|
||||
'hierarchical' => true,
|
||||
'public' => true,
|
||||
'show_in_rest' => true,
|
||||
'show_admin_column' => true,
|
||||
'rewrite' => ['slug' => 'plate-cat'],
|
||||
]);
|
||||
|
||||
// Plate CPT (板块)
|
||||
register_post_type('aksrt_forum_plate', [
|
||||
'labels' => [
|
||||
'name' => __('论坛版块', 'aksrt'),
|
||||
'singular_name' => __('版块', 'aksrt'),
|
||||
'add_new_item' => __('创建版块', 'aksrt'),
|
||||
'edit_item' => __('编辑版块', 'aksrt'),
|
||||
'view_item' => __('查看版块', 'aksrt'),
|
||||
'search_items' => __('搜索版块', 'aksrt'),
|
||||
'not_found' => __('未找到版块', 'aksrt'),
|
||||
'not_found_in_trash' => __('回收站中未找到版块', 'aksrt'),
|
||||
],
|
||||
'public' => true,
|
||||
'hierarchical' => true,
|
||||
'show_in_rest' => true,
|
||||
'has_archive' => false,
|
||||
'menu_icon' => 'dashicons-grid-view',
|
||||
'supports' => ['title', 'editor', 'author', 'excerpt', 'thumbnail', 'page-attributes'],
|
||||
'capability_type' => 'post',
|
||||
'rewrite' => ['slug' => $plate_slug, 'with_front' => false],
|
||||
'show_in_menu' => 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],
|
||||
|
||||
// 封面扩展位 (§7.3 待实现)
|
||||
'_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'],
|
||||
|
||||
// 付费内容扩展位 (§7.3 待实现)
|
||||
'_aksrt_allow_view' => ['type' => 'string', 'default' => 'public'],
|
||||
'_aksrt_pay_price' => ['type' => 'number', 'default' => 0],
|
||||
'_aksrt_pay_vip_price' => ['type' => 'number', 'default' => 0],
|
||||
'_aksrt_pay_credits' => ['type' => 'integer', 'default' => 0],
|
||||
'_aksrt_pay_hide_part' => ['type' => 'integer', 'default' => 0],
|
||||
|
||||
// 状态工作流扩展位 (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],
|
||||
];
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================␍
|
||||
@@ -0,0 +1,491 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
// 前端隐藏 WordPress Admin Bar
|
||||
// ============================================================
|
||||
|
||||
add_filter('show_admin_bar', '__return_false');
|
||||
|
||||
// ============================================================
|
||||
// 隐藏不需要的默认菜单项
|
||||
// ============================================================
|
||||
|
||||
add_action('admin_menu', function () {
|
||||
remove_menu_page('link-manager.php');
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Gravatar 头像源替换(4层拦截:get_avatar_url / pre_get_avatar_data / avatar_defaults / ob_start 兜底)
|
||||
// ============================================================
|
||||
|
||||
function aksrt_get_gravatar_source() {
|
||||
if (class_exists('AKSRT_Settings')) {
|
||||
return AKSRT_Settings::avatar_source();
|
||||
}
|
||||
|
||||
$source = aksrt_get_setting('avatar_source', 'cn.cravatar.com');
|
||||
$allowed = array('cn.cravatar.com', 'cn.gravatar.com', 'gravatar.com');
|
||||
return in_array($source, $allowed, true) ? $source : 'cn.cravatar.com';
|
||||
}
|
||||
|
||||
function aksrt_replace_gravatar_domain($url) {
|
||||
$source = aksrt_get_gravatar_source();
|
||||
if ($source === 'gravatar.com') return $url;
|
||||
return preg_replace('#^https?://([0-9]+\.)?(secure\.)?gravatar\.com#i', 'https://' . $source, $url);
|
||||
}
|
||||
|
||||
add_filter('get_avatar_url', function ($url) {
|
||||
return aksrt_replace_gravatar_domain($url);
|
||||
});
|
||||
|
||||
add_filter('pre_get_avatar_data', function ($args) {
|
||||
if (!empty($args['url'])) {
|
||||
$args['url'] = aksrt_replace_gravatar_domain($args['url']);
|
||||
}
|
||||
return $args;
|
||||
}, 10, 1);
|
||||
|
||||
add_filter('avatar_defaults', function ($defaults) {
|
||||
foreach ($defaults as &$url) {
|
||||
$url = aksrt_replace_gravatar_domain($url);
|
||||
}
|
||||
unset($url);
|
||||
return $defaults;
|
||||
});
|
||||
|
||||
// 全局输出缓冲兜底(覆盖 JS/API 直接请求的 URL)
|
||||
add_action('init', function () {
|
||||
if (is_admin()) ob_start(function ($html) {
|
||||
return preg_replace_callback(
|
||||
'#https?://([0-9]+\.)?(secure\.)?gravatar\.com#i',
|
||||
function () { return 'https://' . aksrt_get_gravatar_source(); },
|
||||
$html
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// SMTP 邮件配置注入
|
||||
// ============================================================
|
||||
|
||||
add_action('phpmailer_init', function ($phpmailer) {
|
||||
$mail = get_option('aksrt_mail_smtp', array());
|
||||
if (empty($mail['enabled']) || empty($mail['host'])) return;
|
||||
|
||||
$phpmailer->isSMTP();
|
||||
$phpmailer->Host = $mail['host'];
|
||||
$phpmailer->Port = (int) (isset($mail['port']) ? $mail['port'] : 465);
|
||||
$phpmailer->SMTPAuth = !empty($mail['username']);
|
||||
$phpmailer->Username = $mail['username'];
|
||||
$phpmailer->Password = $mail['password'];
|
||||
$phpmailer->SMTPSecure = isset($mail['encryption']) ? $mail['encryption'] : 'ssl';
|
||||
|
||||
// 性能优化:超时 + 连接保持
|
||||
$phpmailer->Timeout = 10; // 连接/读取超时 10 秒
|
||||
$phpmailer->Timelimit = 15; // 总执行上限 15 秒
|
||||
|
||||
if (!empty($mail['from_address'])) {
|
||||
$from_name = isset($mail['from_name']) ? $mail['from_name'] : '';
|
||||
// mail_showname 覆盖 from_name
|
||||
if (class_exists('AKSRT_Settings')) {
|
||||
$branding = AKSRT_Settings::get_mail_branding();
|
||||
if ($branding['showname'] !== '') {
|
||||
$from_name = $branding['showname'];
|
||||
}
|
||||
}
|
||||
$phpmailer->setFrom($mail['from_address'], $from_name);
|
||||
}
|
||||
if (!empty($mail['from_name'])) {
|
||||
$phpmailer->FromName = $mail['from_name'];
|
||||
}
|
||||
// mail_showname 全局覆盖 FromName
|
||||
if (class_exists('AKSRT_Settings')) {
|
||||
$branding = AKSRT_Settings::get_mail_branding();
|
||||
if ($branding['showname'] !== '') {
|
||||
$phpmailer->FromName = $branding['showname'];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// mail_title_prefix:为所有邮件主题添加前缀
|
||||
add_filter('wp_mail', function ($atts) {
|
||||
if (!class_exists('AKSRT_Settings') || empty($atts['subject'])) return $atts;
|
||||
$branding = AKSRT_Settings::get_mail_branding();
|
||||
if ($branding['title_prefix'] !== '' && strpos($atts['subject'], $branding['title_prefix']) !== 0) {
|
||||
$atts['subject'] = $branding['title_prefix'] . ' ' . $atts['subject'];
|
||||
}
|
||||
return $atts;
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// 分类 Term Meta 字段(封面图 + 推荐描述)
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 编辑分类页面 - 显示自定义字段
|
||||
*/
|
||||
function aksrt_category_meta_fields($term) {
|
||||
$cover_id = (int) get_term_meta($term->term_id, 'aksrt_category_cover_id', true);
|
||||
$cover_url = $cover_id > 0 ? wp_get_attachment_url($cover_id) : '';
|
||||
$recommend_desc = (string) get_term_meta($term->term_id, 'aksrt_category_recommend_desc', true);
|
||||
?>
|
||||
<tr class="form-field">
|
||||
<th scope="row"><label for="aksrt_category_cover_id"><?php esc_html_e('分类封面图', 'aksrt'); ?></label></th>
|
||||
<td>
|
||||
<div id="aksrt-cover-preview" style="margin-bottom:8px;">
|
||||
<?php if ($cover_url) : ?>
|
||||
<img src="<?php echo esc_url($cover_url); ?>" style="max-width:200px;height:auto;border-radius:6px;" alt="">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<input type="hidden" id="aksrt_category_cover_id" name="aksrt_category_cover_id" value="<?php echo esc_attr((string) $cover_id); ?>">
|
||||
<button type="button" class="button" id="aksrt-pick-cover"><?php esc_html_e('选择图片', 'aksrt'); ?></button>
|
||||
<button type="button" class="button" id="aksrt-remove-cover" <?php echo $cover_id > 0 ? '' : 'style="display:none;"'; ?>><?php esc_html_e('移除', 'aksrt'); ?></button>
|
||||
<p class="description"><?php esc_html_e('分类推荐模块的封面图片。', 'aksrt'); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="form-field">
|
||||
<th scope="row"><label for="aksrt_category_recommend_desc"><?php esc_html_e('推荐描述', 'aksrt'); ?></label></th>
|
||||
<td>
|
||||
<textarea id="aksrt_category_recommend_desc" name="aksrt_category_recommend_desc" rows="3" class="large-text"><?php echo esc_textarea($recommend_desc); ?></textarea>
|
||||
<p class="description"><?php esc_html_e('分类推荐模块中显示的描述文字。留空则使用分类默认描述。', 'aksrt'); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增分类页面 - 显示自定义字段
|
||||
*/
|
||||
function aksrt_category_meta_fields_add() {
|
||||
?>
|
||||
<div class="form-field">
|
||||
<label for="aksrt_category_cover_id"><?php esc_html_e('分类封面图', 'aksrt'); ?></label>
|
||||
<div id="aksrt-cover-preview" style="margin-bottom:8px;"></div>
|
||||
<input type="hidden" id="aksrt_category_cover_id" name="aksrt_category_cover_id" value="">
|
||||
<button type="button" class="button" id="aksrt-pick-cover"><?php esc_html_e('选择图片', 'aksrt'); ?></button>
|
||||
<button type="button" class="button" id="aksrt-remove-cover" style="display:none;"><?php esc_html_e('移除', 'aksrt'); ?></button>
|
||||
<p class="description"><?php esc_html_e('分类推荐模块的封面图片。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label for="aksrt_category_recommend_desc"><?php esc_html_e('推荐描述', 'aksrt'); ?></label>
|
||||
<textarea id="aksrt_category_recommend_desc" name="aksrt_category_recommend_desc" rows="3"></textarea>
|
||||
<p class="description"><?php esc_html_e('分类推荐模块中显示的描述文字。留空则使用分类默认描述。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
add_action('category_edit_form_fields', 'aksrt_category_meta_fields', 10, 1);
|
||||
add_action('category_add_form_fields', 'aksrt_category_meta_fields_add', 10, 1);
|
||||
|
||||
/**
|
||||
* 保存分类 term meta
|
||||
*/
|
||||
function aksrt_save_category_meta(int $term_id) {
|
||||
if (!current_user_can('manage_categories')) return;
|
||||
|
||||
$cover_id = isset($_POST['aksrt_category_cover_id']) ? absint($_POST['aksrt_category_cover_id']) : 0;
|
||||
$recommend_desc = isset($_POST['aksrt_category_recommend_desc']) ? sanitize_textarea_field(wp_unslash($_POST['aksrt_category_recommend_desc'])) : '';
|
||||
|
||||
if ($cover_id > 0) {
|
||||
update_term_meta($term_id, 'aksrt_category_cover_id', $cover_id);
|
||||
} else {
|
||||
delete_term_meta($term_id, 'aksrt_category_cover_id');
|
||||
}
|
||||
|
||||
if ($recommend_desc !== '') {
|
||||
update_term_meta($term_id, 'aksrt_category_recommend_desc', $recommend_desc);
|
||||
} else {
|
||||
delete_term_meta($term_id, 'aksrt_category_recommend_desc');
|
||||
}
|
||||
|
||||
if (class_exists('AKSRT_Settings')) {
|
||||
AKSRT_Settings::flush_category_recommend_cache();
|
||||
}
|
||||
}
|
||||
|
||||
add_action('edited_category', 'aksrt_save_category_meta', 10, 1);
|
||||
add_action('created_category', 'aksrt_save_category_meta', 10, 1);
|
||||
|
||||
/**
|
||||
* 分类编辑页加载媒体库脚本(wp_enqueue_media 仅在 AKSRT 面板加载,此处补上)
|
||||
*/
|
||||
add_action('admin_enqueue_scripts', function (string $hook_suffix) {
|
||||
if ($hook_suffix === 'edit-tags.php' || $hook_suffix === 'term.php') {
|
||||
wp_enqueue_media();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 分类编辑页内联 JS - 媒体选择器
|
||||
*/
|
||||
function aksrt_category_meta_admin_js() {
|
||||
$screen = get_current_screen();
|
||||
if (!$screen || $screen->taxonomy !== 'category') return;
|
||||
?>
|
||||
<script>
|
||||
jQuery(function($) {
|
||||
var frame;
|
||||
|
||||
$(document).on('click', '#aksrt-pick-cover', function(e) {
|
||||
e.preventDefault();
|
||||
if (typeof wp === 'undefined' || !wp.media) return;
|
||||
if (frame) { frame.open(); return; }
|
||||
|
||||
frame = wp.media({
|
||||
title: '<?php echo esc_js(__('选择分类封面图', 'aksrt')); ?>',
|
||||
button: { text: '<?php echo esc_js(__('使用此图片', 'aksrt')); ?>' },
|
||||
multiple: false
|
||||
});
|
||||
|
||||
frame.on('select', function() {
|
||||
var attachment = frame.state().get('selection').first().toJSON();
|
||||
$('#aksrt_category_cover_id').val(attachment.id);
|
||||
$('#aksrt-cover-preview').html('<img src="' + attachment.url + '" style="max-width:200px;height:auto;border-radius:6px;" alt="">');
|
||||
$('#aksrt-remove-cover').show();
|
||||
});
|
||||
|
||||
frame.open();
|
||||
});
|
||||
|
||||
$(document).on('click', '#aksrt-remove-cover', function(e) {
|
||||
e.preventDefault();
|
||||
$('#aksrt_category_cover_id').val('');
|
||||
$('#aksrt-cover-preview').html('');
|
||||
$(this).hide();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
add_action('admin_footer', 'aksrt_category_meta_admin_js');
|
||||
|
||||
// ============================================================
|
||||
// 资源归档:/resources 重写规则 + 排序参数注入
|
||||
// 站内搜索:包含「资源」(post + _aksrt_is_resource)
|
||||
// ============================================================
|
||||
|
||||
// 注册 /resources 虚拟归档
|
||||
add_action('init', function () {
|
||||
add_rewrite_rule('^resources/?$', 'index.php?aksrt_is_resource_archive=1', 'top');
|
||||
add_rewrite_rule('^resources/page/([0-9]+)/?$', 'index.php?aksrt_is_resource_archive=1&paged=$matches[1]', 'top');
|
||||
|
||||
// 兼容历史 /resource/{slug}:301 到 /{slug}(默认 post 永久链接)
|
||||
add_rewrite_rule('^resource/([^/]+)/?$', 'index.php?aksrt_legacy_resource=$matches[1]', 'top');
|
||||
});
|
||||
|
||||
add_filter('query_vars', function ($vars) {
|
||||
$vars[] = 'aksrt_is_resource_archive';
|
||||
$vars[] = 'aksrt_legacy_resource';
|
||||
$vars[] = 'aksrt_search_type';
|
||||
return $vars;
|
||||
});
|
||||
|
||||
// 旧资源链接 301 跳转
|
||||
add_action('template_redirect', function () {
|
||||
$slug = get_query_var('aksrt_legacy_resource');
|
||||
if (!$slug) return;
|
||||
// 先按 post 查
|
||||
$page = get_page_by_path((string) $slug, OBJECT, 'post');
|
||||
if (!$page && post_type_exists('aksrt_resource')) {
|
||||
$page = get_page_by_path((string) $slug, OBJECT, 'aksrt_resource');
|
||||
}
|
||||
if ($page) {
|
||||
wp_redirect(get_permalink($page->ID), 301);
|
||||
exit;
|
||||
}
|
||||
});
|
||||
|
||||
add_action('pre_get_posts', function ($query) {
|
||||
if (is_admin() || !$query->is_main_query()) return;
|
||||
|
||||
$is_resource_archive = (bool) $query->get('aksrt_is_resource_archive')
|
||||
|| (post_type_exists('aksrt_resource') && $query->is_post_type_archive('aksrt_resource'));
|
||||
|
||||
// 资源归档页:把查询锁定到「post + _aksrt_is_resource = 1」(含历史 CPT 兼容)
|
||||
if ($is_resource_archive) {
|
||||
$query->set('post_type', function_exists('aksrt_resource_post_types') ? aksrt_resource_post_types() : ['post']);
|
||||
$query->set('post_status', 'publish');
|
||||
|
||||
$orderby = isset($_GET['orderby']) ? sanitize_key((string) $_GET['orderby']) : 'date';
|
||||
if ($orderby === 'downloads') {
|
||||
$query->set('meta_key', AKSRT_Domain_Model::RESOURCE_DOWNLOAD_COUNT_KEY);
|
||||
$query->set('orderby', 'meta_value_num');
|
||||
$query->set('order', 'DESC');
|
||||
} elseif ($orderby === 'views') {
|
||||
$query->set('meta_key', AKSRT_Domain_Model::RESOURCE_VIEW_COUNT_KEY);
|
||||
$query->set('orderby', 'meta_value_num');
|
||||
$query->set('order', 'DESC');
|
||||
}
|
||||
|
||||
// 价格筛选:?price=free | paid | all
|
||||
// 价格区间:?price_min=0&price_max=99
|
||||
$price_filter = isset($_GET['price']) ? sanitize_key((string) $_GET['price']) : '';
|
||||
$price_min = isset($_GET['price_min']) && $_GET['price_min'] !== '' ? (float) $_GET['price_min'] : null;
|
||||
$price_max = isset($_GET['price_max']) && $_GET['price_max'] !== '' ? (float) $_GET['price_max'] : null;
|
||||
|
||||
// 「是资源」基础约束:_aksrt_is_resource=1(兼容旧 CPT 时由 post_type 兜底)
|
||||
$meta_query = [
|
||||
'relation' => 'AND',
|
||||
[
|
||||
'relation' => 'OR',
|
||||
// 新形态:post + meta=1
|
||||
[
|
||||
'key' => AKSRT_Domain_Model::RESOURCE_MARKER_KEY,
|
||||
'value' => '1',
|
||||
'compare' => '=',
|
||||
],
|
||||
// 历史 CPT 兼容:通过 post_type 已被包含,meta 缺失也算资源
|
||||
[
|
||||
'key' => AKSRT_Domain_Model::RESOURCE_MARKER_KEY,
|
||||
'compare' => 'NOT EXISTS',
|
||||
],
|
||||
],
|
||||
];
|
||||
if ($price_filter === 'free') {
|
||||
$meta_query[] = [
|
||||
'relation' => 'OR',
|
||||
[
|
||||
'key' => AKSRT_Domain_Model::PAY_PRICE_KEY,
|
||||
'value' => 0,
|
||||
'compare' => '=',
|
||||
'type' => 'NUMERIC',
|
||||
],
|
||||
[
|
||||
'key' => AKSRT_Domain_Model::PAY_PRICE_KEY,
|
||||
'compare' => 'NOT EXISTS',
|
||||
],
|
||||
];
|
||||
} elseif ($price_filter === 'paid') {
|
||||
$meta_query[] = [
|
||||
'key' => AKSRT_Domain_Model::PAY_PRICE_KEY,
|
||||
'value' => 0,
|
||||
'compare' => '>',
|
||||
'type' => 'NUMERIC',
|
||||
];
|
||||
}
|
||||
|
||||
if ($price_min !== null || $price_max !== null) {
|
||||
if ($price_min !== null && $price_max !== null) {
|
||||
$meta_query[] = [
|
||||
'key' => AKSRT_Domain_Model::PAY_PRICE_KEY,
|
||||
'value' => [$price_min, $price_max],
|
||||
'compare' => 'BETWEEN',
|
||||
'type' => 'NUMERIC',
|
||||
];
|
||||
} elseif ($price_min !== null) {
|
||||
$meta_query[] = [
|
||||
'key' => AKSRT_Domain_Model::PAY_PRICE_KEY,
|
||||
'value' => $price_min,
|
||||
'compare' => '>=',
|
||||
'type' => 'NUMERIC',
|
||||
];
|
||||
} elseif ($price_max !== null) {
|
||||
$meta_query[] = [
|
||||
'key' => AKSRT_Domain_Model::PAY_PRICE_KEY,
|
||||
'value' => $price_max,
|
||||
'compare' => '<=',
|
||||
'type' => 'NUMERIC',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 仅在新形态(post)下加 _aksrt_is_resource=1 强约束;
|
||||
// 旧 CPT 仍在站点时,post_type 已含 aksrt_resource,配合上面 OR 兼容逻辑即可。
|
||||
if (!post_type_exists('aksrt_resource')) {
|
||||
// 替换 OR 兼容片段为强等于
|
||||
$meta_query[0] = [
|
||||
'key' => AKSRT_Domain_Model::RESOURCE_MARKER_KEY,
|
||||
'value' => '1',
|
||||
'compare' => '=',
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($meta_query)) {
|
||||
$existing = $query->get('meta_query');
|
||||
if (!is_array($existing)) $existing = [];
|
||||
$query->set('meta_query', array_merge($existing, $meta_query));
|
||||
}
|
||||
|
||||
// 资源归档不要分类/标签限制
|
||||
$query->set('cat', 0);
|
||||
$query->set('tag', '');
|
||||
}
|
||||
|
||||
// 站内搜索:post 已默认覆盖(资源就是 post),仅在仍有旧 CPT 时合并
|
||||
if ($query->is_search() && empty($query->get('post_type'))) {
|
||||
$search_type = sanitize_key((string) $query->get('aksrt_search_type'));
|
||||
|
||||
if (in_array($search_type, ['category', 'tag'], true)) {
|
||||
$taxonomy = $search_type === 'category' ? 'category' : 'post_tag';
|
||||
$term_ids = get_terms([
|
||||
'taxonomy' => $taxonomy,
|
||||
'hide_empty' => false,
|
||||
'fields' => 'ids',
|
||||
'number' => 20,
|
||||
'search' => (string) $query->get('s'),
|
||||
]);
|
||||
|
||||
$query->set('s', '');
|
||||
|
||||
if (is_wp_error($term_ids) || empty($term_ids)) {
|
||||
$query->set('post__in', [0]);
|
||||
} else {
|
||||
$query->set('tax_query', [[
|
||||
'taxonomy' => $taxonomy,
|
||||
'field' => 'term_id',
|
||||
'terms' => array_map('absint', $term_ids),
|
||||
]]);
|
||||
}
|
||||
}
|
||||
|
||||
if (post_type_exists('aksrt_resource')) {
|
||||
// 单一数据选择策略:搜索的内容类型与索引/推送共用同一 helper。
|
||||
$search_types = function_exists('aksrt_searchable_post_types')
|
||||
? aksrt_searchable_post_types()
|
||||
: ['post'];
|
||||
if (count($search_types) > 1) {
|
||||
$query->set('post_type', $search_types);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分类 / 标签归档:post 已自然包含资源(meta 标记),仅当历史 CPT 仍在时才需合并 post_type
|
||||
if (($query->is_category() || $query->is_tag()) && post_type_exists('aksrt_resource')) {
|
||||
$existing = $query->get('post_type');
|
||||
if (empty($existing)) {
|
||||
$query->set('post_type', ['post', 'aksrt_resource']);
|
||||
}
|
||||
}
|
||||
|
||||
// v4 起主题统一为 CMS / 资源站形态,所有归档都允许包含资源帖。
|
||||
// 历史的 blog/cms 双流分流(按 site_profile + term flow 排除资源)已移除。
|
||||
});
|
||||
|
||||
// 资源归档页:套 archive-aksrt_resource.php 模板(v3.4 起作为「资源虚拟归档」复用)
|
||||
add_filter('template_include', function ($template) {
|
||||
if (!get_query_var('aksrt_is_resource_archive')) return $template;
|
||||
$candidate = locate_template(['archive-aksrt_resource.php']);
|
||||
return $candidate ?: $template;
|
||||
});
|
||||
|
||||
// 标记为资源的 post:单页改用 single-aksrt_resource.php 模板
|
||||
add_filter('single_template', function ($template) {
|
||||
if (!is_singular('post')) return $template;
|
||||
$post = get_queried_object();
|
||||
if (!($post instanceof WP_Post)) return $template;
|
||||
if (!function_exists('aksrt_is_resource_post')) return $template;
|
||||
if (!aksrt_is_resource_post($post)) return $template;
|
||||
$candidate = locate_template(['single-aksrt_resource.php']);
|
||||
return $candidate ?: $template;
|
||||
});
|
||||
|
||||
// 资源归档页:标题
|
||||
add_filter('document_title_parts', function ($parts) {
|
||||
if (get_query_var('aksrt_is_resource_archive')) {
|
||||
$parts['title'] = '资源';
|
||||
}
|
||||
return $parts;
|
||||
});
|
||||
|
||||
// ============================================================␍
|
||||
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
// EnlighterJS 代码高亮 — 白名单 data-enlighter-* 属性
|
||||
// ============================================================
|
||||
|
||||
add_filter('wp_kses_allowed_html', function ($allowed, $context) {
|
||||
if ($context !== 'post') {
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
// Allow data-enlighter-* attributes on <pre> and <code>
|
||||
$enlighter_attrs = [
|
||||
'data-enlighter-language' => true,
|
||||
'data-enlighter-theme' => true,
|
||||
'data-enlighter-group' => true,
|
||||
'data-enlighter-title' => true,
|
||||
'data-enlighter-linenumbers' => true,
|
||||
'data-enlighter-highlight' => true,
|
||||
'data-enlighter-lineoffset' => true,
|
||||
];
|
||||
|
||||
if (isset($allowed['pre'])) {
|
||||
$allowed['pre'] = array_merge($allowed['pre'], $enlighter_attrs);
|
||||
}
|
||||
if (isset($allowed['code'])) {
|
||||
$allowed['code'] = array_merge($allowed['code'], $enlighter_attrs);
|
||||
}
|
||||
|
||||
return $allowed;
|
||||
}, 10, 2);
|
||||
|
||||
// ============================================================
|
||||
// WP 后台文章列表增强列 — 浏览/点赞/收藏/下载
|
||||
// ============================================================
|
||||
|
||||
add_filter('manage_post_posts_columns', function ($columns) {
|
||||
$new_columns = [];
|
||||
foreach ($columns as $key => $label) {
|
||||
$new_columns[$key] = $label;
|
||||
if ($key === 'title') {
|
||||
$new_columns['aksrt_stats'] = __('互动数据', 'aksrt');
|
||||
}
|
||||
}
|
||||
return $new_columns;
|
||||
});
|
||||
|
||||
add_action('admin_enqueue_scripts', function ($hook) {
|
||||
if ($hook !== 'edit.php') return;
|
||||
wp_enqueue_style('font-awesome-5', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css', [], '5.15.4');
|
||||
});
|
||||
|
||||
add_action('manage_post_posts_custom_column', function ($column, $post_id) {
|
||||
if ($column !== 'aksrt_stats') return;
|
||||
|
||||
$views = (int) get_post_meta($post_id, 'views', true);
|
||||
$likes = (int) get_post_meta($post_id, 'like', true);
|
||||
$favorites = (int) get_post_meta($post_id, 'favorite', true);
|
||||
$downloads = (int) get_post_meta($post_id, 'download_count', true);
|
||||
|
||||
$format = function (int $n): string {
|
||||
if ($n >= 10000) return round($n / 10000, 1) . '万';
|
||||
if ($n >= 1000) return round($n / 1000, 1) . 'k';
|
||||
return (string) $n;
|
||||
};
|
||||
|
||||
$parts = [];
|
||||
$parts[] = '<span title="' . esc_attr__('浏览', 'aksrt') . '" style="margin-right:4px;"><i class="fas fa-eye" style="color:#8a909c;font-size:12px;"></i> ' . esc_html($format($views)) . '</span>';
|
||||
$parts[] = '<span title="' . esc_attr__('点赞', 'aksrt') . '" style="margin-right:4px;"><i class="fas fa-thumbs-up" style="color:#1890ff;font-size:12px;"></i> ' . esc_html($format($likes)) . '</span>';
|
||||
$parts[] = '<span title="' . esc_attr__('收藏', 'aksrt') . '" style="margin-right:4px;"><i class="fas fa-star" style="color:#f39c12;font-size:12px;"></i> ' . esc_html($format($favorites)) . '</span>';
|
||||
|
||||
if ($downloads > 0) {
|
||||
$parts[] = '<span title="' . esc_attr__('下载', 'aksrt') . '"><i class="fas fa-download" style="color:#52c41a;font-size:12px;"></i> ' . esc_html($format($downloads)) . '</span>';
|
||||
}
|
||||
|
||||
echo implode(' · ', $parts);
|
||||
}, 10, 2);
|
||||
|
||||
// Support sorting by views/likes/favorites in admin
|
||||
add_action('pre_get_posts', function ($query) {
|
||||
if (!is_admin() || !$query->is_main_query()) return;
|
||||
|
||||
$orderby = $query->get('orderby');
|
||||
$allowed = ['views', 'like', 'favorite', 'download_count'];
|
||||
|
||||
if (in_array($orderby, $allowed, true)) {
|
||||
$query->set('meta_key', $orderby);
|
||||
$query->set('orderby', 'meta_value_num');
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// 评论提交:单一合同
|
||||
// ------------------------------------------------------------
|
||||
// 评论提交统一走 WordPress 原生 wp-comments-post.php,由前端
|
||||
// main.js initCommentSystem() 以 AJAX 拦截:它负责人机验证、频率
|
||||
// 限制、审核管线,并在成功后通过 reloadCommentList() 重新拉取,
|
||||
// 列表仍由 aksrt_comment_callback 这一规范渲染器输出。
|
||||
// 不再保留并行的 aksrt_submit_comment 动作(避免绕过验证码的第二套提交合同)。
|
||||
// 详见 comment-contract.md。
|
||||
// ============================================================
|
||||
|
||||
// ============================================================
|
||||
// Gutenberg 自定义块注册
|
||||
// ============================================================
|
||||
|
||||
add_action('enqueue_block_editor_assets', function () {
|
||||
$base_uri = get_template_directory_uri();
|
||||
$version = wp_get_theme()->get('Version');
|
||||
|
||||
$blocks_js = get_template_directory() . '/assets/js/gutenberg-blocks.js';
|
||||
if (file_exists($blocks_js)) {
|
||||
wp_enqueue_script(
|
||||
'aksrt-gutenberg-blocks',
|
||||
$base_uri . '/assets/js/gutenberg-blocks.js',
|
||||
['wp-blocks', 'wp-element', 'wp-components', 'wp-block-editor', 'wp-hooks'],
|
||||
(string) filemtime($blocks_js),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$blocks_css = get_template_directory() . '/assets/css/gutenberg-blocks.css';
|
||||
if (file_exists($blocks_css)) {
|
||||
wp_enqueue_style(
|
||||
'aksrt-gutenberg-blocks',
|
||||
$base_uri . '/assets/css/gutenberg-blocks.css',
|
||||
[],
|
||||
(string) filemtime($blocks_css)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Front-end styles for Gutenberg blocks
|
||||
add_action('enqueue_block_assets', function () {
|
||||
if (is_admin()) return; // Already loaded in editor
|
||||
|
||||
$base_uri = get_template_directory_uri();
|
||||
$blocks_css = get_template_directory() . '/assets/css/gutenberg-blocks.css';
|
||||
if (file_exists($blocks_css)) {
|
||||
wp_enqueue_style(
|
||||
'aksrt-gutenberg-blocks-front',
|
||||
$base_uri . '/assets/css/gutenberg-blocks.css',
|
||||
[],
|
||||
(string) filemtime($blocks_css)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Gutenberg Carousel Block 渲染回调
|
||||
// ============================================================
|
||||
add_action('init', function () {
|
||||
if (!function_exists('register_block_type')) return;
|
||||
|
||||
register_block_type('aksrt/carousel', [
|
||||
'render_callback' => function (array $attributes): string {
|
||||
$images = $attributes['images'] ?? [];
|
||||
if (empty($images)) return '';
|
||||
|
||||
$autoplay = !empty($attributes['autoplay']) ? 'true' : 'false';
|
||||
$delay = absint($attributes['delay'] ?? 3000);
|
||||
$effect = sanitize_text_field($attributes['effect'] ?? 'slide');
|
||||
|
||||
$slides = '';
|
||||
foreach ($images as $img) {
|
||||
if (empty($img['url'])) continue;
|
||||
$alt = esc_attr($img['alt'] ?? '');
|
||||
$url = esc_url($img['url']);
|
||||
$slides .= '<div class="swiper-slide"><img src="' . $url . '" alt="' . $alt . '" loading="lazy"></div>';
|
||||
}
|
||||
|
||||
if (empty($slides)) return '';
|
||||
|
||||
return '<div class="aksrt-carousel-block swiper" data-autoplay="' . $autoplay . '" data-delay="' . $delay . '" data-effect="' . $effect . '">'
|
||||
. '<div class="swiper-wrapper">' . $slides . '</div>'
|
||||
. '<div class="swiper-pagination"></div>'
|
||||
. '<div class="swiper-button-prev"></div><div class="swiper-button-next"></div>'
|
||||
. '</div>';
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// 付费内容系统:the_content 过滤器
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 未付费内容:替换为付费墙。
|
||||
*/
|
||||
add_filter('the_content', 'aksrt_paid_content_filter', 20);
|
||||
|
||||
/**
|
||||
* 已付费内容增强:追加图库轮播/视频播放器。
|
||||
*/
|
||||
add_filter('the_content', 'aksrt_paid_content_enhance', 25);
|
||||
|
||||
/**
|
||||
* 付费文章使用统一的 single.php(不再路由到 single-aksrt_resource.php)。
|
||||
*/
|
||||
add_filter('single_template', function (string $template): string {
|
||||
return $template;
|
||||
});
|
||||
Reference in new issue
Block a user