post_type !== 'post') { return; } if (!class_exists('\AKSRT\Settings\Settings')) { return; } $page = \AKSRT\Settings\Settings::get_post_page_settings(); $views_min = max(0, (int) ($page['default_views_min'] ?? 20)); $views_max = max($views_min, (int) ($page['default_views_max'] ?? 50)); $likes_min = max(0, (int) ($page['default_likes_min'] ?? 5)); $likes_max = max($likes_min, (int) ($page['default_likes_max'] ?? 15)); if ('' === (string) get_post_meta($post_id, \AKSRT\Core\DomainModel::POST_VIEW_COUNT_KEY, true)) { update_post_meta($post_id, \AKSRT\Core\DomainModel::POST_VIEW_COUNT_KEY, wp_rand($views_min, $views_max)); } if ('' === (string) get_post_meta($post_id, '_aksrt_like_count', true)) { update_post_meta($post_id, '_aksrt_like_count', wp_rand($likes_min, $likes_max)); } }, 10, 2); // ============================================================ // 前端隐藏 WordPress Admin Bar:由 SystemTools 按「扩展&增强 → 系统工具」 // 的 hide_admin_bar 设置门控(默认开启),不再无条件注入。 // ============================================================ // ============================================================ // SMTP 邮件配置注入 // ============================================================ add_filter('wp_mail_from', function ($from) { if (!class_exists('\AKSRT\Settings\Settings')) return $from; $mail = \AKSRT\Settings\Settings::get_smtp(); if (empty($mail['enabled'])) return $from; $configured = sanitize_email((string) ($mail['from_address'] ?? '')); return $configured !== '' ? $configured : $from; }); add_filter('wp_mail_from_name', function ($from_name) { if (!class_exists('\AKSRT\Settings\Settings')) return $from_name; $mail = \AKSRT\Settings\Settings::get_smtp(); if (empty($mail['enabled'])) return $from_name; $configured = trim((string) ($mail['from_name'] ?? '')); return $configured !== '' ? $configured : $from_name; }); add_action('phpmailer_init', function ($phpmailer) { $mail = class_exists('\\AKSRT\\Settings\\Settings') ? \AKSRT\Settings\Settings::get_smtp() : []; if (empty($mail['enabled']) || empty($mail['host'])) return; $phpmailer->isSMTP(); $phpmailer->Host = $mail['host']; $phpmailer->Port = (int) ($mail['port'] ?? 465); $phpmailer->SMTPAuth = !empty($mail['auth']) && !empty($mail['username']); $phpmailer->Username = (string) ($mail['username'] ?? ''); $phpmailer->Password = (string) ($mail['password'] ?? ''); $phpmailer->SMTPSecure = (string) ($mail['encryption'] ?? 'ssl'); $phpmailer->Timeout = 10; $phpmailer->Timelimit = 15; }); // mail_title_prefix is applied by the canonical renderer and by third-party wp_mail callers. add_filter('wp_mail', function ($atts) { if (!class_exists('\AKSRT\Settings\Settings') || empty($atts['subject'])) return $atts; $branding = \AKSRT\Settings\Settings::get_mail_branding(); $subject = (string) $atts['subject']; $site = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES); $subject = preg_replace('/^\[' . preg_quote($site, '/') . '\]\s*/u', '', $subject); if ($branding['title_prefix'] !== '' && strpos($subject, $branding['title_prefix']) !== 0) { $atts['subject'] = $branding['title_prefix'] . ' ' . $subject; } else { $atts['subject'] = $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); ?>

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\Settings')) { \AKSRT\Settings\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; ?> ID), 301); exit; } }); add_action('pre_get_posts', function ($query) { if (is_admin() || !$query->is_main_query()) { return; } if ((bool) $query->get('aksrt_is_resource_archive')) { $query->set('post_type', 'post'); $query->set('post_status', 'publish'); $orderby = isset($_GET['orderby']) ? sanitize_key((string) $_GET['orderby']) : 'date'; if ($orderby === 'downloads') { $query->set('meta_key', \AKSRT\Core\DomainModel::RESOURCE_DOWNLOAD_COUNT_KEY); $query->set('orderby', 'meta_value_num'); $query->set('order', 'DESC'); } elseif ($orderby === 'views') { $query->set('meta_key', \AKSRT\Core\DomainModel::RESOURCE_VIEW_COUNT_KEY); $query->set('orderby', 'meta_value_num'); $query->set('order', 'DESC'); } $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; $meta_query = [ 'relation' => 'AND', [ 'key' => \AKSRT\Core\DomainModel::RESOURCE_MARKER_KEY, 'value' => '1', 'compare' => '=', ], ]; if ($price_filter === 'free') { $meta_query[] = [ 'relation' => 'OR', [ 'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY, 'value' => 0, 'compare' => '=', 'type' => 'NUMERIC', ], [ 'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY, 'compare' => 'NOT EXISTS', ], ]; } elseif ($price_filter === 'paid') { $meta_query[] = [ 'key' => \AKSRT\Core\DomainModel::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\Core\DomainModel::PAY_PRICE_KEY, 'value' => [$price_min, $price_max], 'compare' => 'BETWEEN', 'type' => 'NUMERIC', ]; } elseif ($price_min !== null) { $meta_query[] = [ 'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY, 'value' => $price_min, 'compare' => '>=', 'type' => 'NUMERIC', ]; } else { $meta_query[] = [ 'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY, 'value' => $price_max, 'compare' => '<=', 'type' => 'NUMERIC', ]; } } $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) if ($query->is_search() && empty($query->get('post_type'))) { $search_type = sanitize_key((string) $query->get('type')); $trem = absint($query->get('trem')); if ($trem > 0) { $query->set('cat', $trem); } 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), ]]); } } } }); add_filter('template_include', function ($template) { if (!get_query_var('aksrt_is_resource_archive')) { return $template; } $candidate = locate_template(['archive-resources.php']); return $candidate ?: $template; }); add_filter('document_title_parts', function ($parts) { if (get_query_var('aksrt_is_resource_archive')) { $parts['title'] = __('资源', 'aksrt'); } return $parts; }); // EnlighterJS 代码高亮 — 白名单 data-enlighter-* 属性 // ============================================================ add_filter('wp_kses_allowed_html', function ($allowed, $context) { if ($context !== 'post') { return $allowed; } // Allow data-enlighter-* attributes on
 and 
    $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;
    aksrt_enqueue_fontawesome();
});

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[] = ' ' . esc_html($format($views)) . '';
    $parts[] = ' ' . esc_html($format($likes)) . '';
    $parts[] = ' ' . esc_html($format($favorites)) . '';

    if ($downloads > 0) {
        $parts[] = ' ' . esc_html($format($downloads)) . '';
    }

    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');
    }
});

// ============================================================
// Gutenberg 自定义块注册
// ============================================================

// Register category server-side so it exists before JS registerBlockType runs.
// Keep untyped + defensive: some plugins pass unexpected shapes; typed params can 500 the editor.
add_filter('block_categories_all', static function ($categories, $context = null) {
    if (!is_array($categories)) {
        return $categories;
    }

    foreach ($categories as $category) {
        $slug = '';
        if (is_array($category)) {
            $slug = (string) ($category['slug'] ?? '');
        } elseif (is_object($category) && isset($category->slug)) {
            $slug = (string) $category->slug;
        }
        if ($slug === 'aksrt-blocks') {
            return $categories;
        }
    }

    $categories[] = [
        'slug'  => 'aksrt-blocks',
        'title' => 'AKSRT',
        'icon'  => null,
    ];

    return $categories;
}, 10, 2);

add_action('enqueue_block_editor_assets', function () {
    $base_uri = get_template_directory_uri();

    $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-media-utils: MediaUpload for carousel block
            ['wp-blocks', 'wp-element', 'wp-components', 'wp-block-editor', 'wp-hooks', 'wp-media-utils', 'wp-data'],
            (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

    $posts = [];
    $queried = get_queried_object();
    if ($queried instanceof \WP_Post) {
        $posts[$queried->ID] = $queried;
    }

    global $wp_query;
    if ($wp_query instanceof \WP_Query) {
        foreach ((array) $wp_query->posts as $post) {
            if ($post instanceof \WP_Post) {
                $posts[$post->ID] = $post;
            }
        }
    }

    $has_carousel = false;
    foreach ($posts as $post) {
        if (has_block('aksrt/carousel', $post)) {
            $has_carousel = true;
            break;
        }
    }
    if (!$has_carousel) return;

    $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 .= '
'; } if (empty($slides)) return ''; return ''; }, ]); }); // ============================================================ // 付费内容系统:the_content 过滤器 // ============================================================ /** * 未购买的图库/视频正文只保留公开预览;购买卡由 single 模板渲染。 */ add_filter('the_content', 'aksrt_paid_content_filter', 20);