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);
?>
|
|
|
|
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;
?>
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;
});
// ============================================================