580 lines
23 KiB
PHP
580 lines
23 KiB
PHP
<?php
|
||
/**
|
||
* AKSRT Resource Helper
|
||
*
|
||
* 资源(CMS)相关的顶层辅助函数。
|
||
*
|
||
* 提供给模板层调用,将原始 post meta 转成视图友好的结构,
|
||
* 同时承担"显示策略"判定(是否显示价格/版本/下载按钮等)。
|
||
*
|
||
* @package AKSRT
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
if (!function_exists('aksrt_get_resource_meta')) {
|
||
/**
|
||
* 一次性取齐资源的全部元数据,已带默认值。
|
||
*
|
||
* 单次 get_post_meta($id, '', true) 调用 + WordPress 内部 meta 缓存命中,
|
||
* 避免 11 次单独查询。
|
||
*
|
||
* @param int|WP_Post|null $post
|
||
* @return array
|
||
*/
|
||
function aksrt_get_resource_meta($post = null): array {
|
||
$p = get_post($post);
|
||
if (!($p instanceof WP_Post)) {
|
||
return aksrt_default_resource_meta();
|
||
}
|
||
|
||
$pay_meta = function_exists('aksrt_get_pay_meta')
|
||
? aksrt_get_pay_meta($p)
|
||
: AKSRT_Domain_Model::default_pay_meta();
|
||
$download_count = (int) get_post_meta($p->ID, AKSRT_Domain_Model::RESOURCE_DOWNLOAD_COUNT_KEY, true);
|
||
$legacy_download_count = (int) get_post_meta($p->ID, 'download_count', true);
|
||
$resource_view_count = (int) get_post_meta($p->ID, AKSRT_Domain_Model::RESOURCE_VIEW_COUNT_KEY, true);
|
||
$common_view_count = (int) get_post_meta($p->ID, AKSRT_Domain_Model::POST_VIEW_COUNT_KEY, true);
|
||
|
||
return [
|
||
'version' => (string) ($pay_meta['version'] ?? ''),
|
||
'size' => (string) ($pay_meta['size'] ?? ''),
|
||
'price' => (float) ($pay_meta['price'] ?? 0),
|
||
'original_price' => (float) ($pay_meta['original_price'] ?? 0),
|
||
'vip1_price' => (float) ($pay_meta['vip1_price'] ?? 0),
|
||
'vip2_price' => (float) ($pay_meta['vip2_price'] ?? 0),
|
||
'pay_type' => (string) ($pay_meta['pay_type'] ?? AKSRT_Domain_Model::PAY_TYPE_DOWNLOAD),
|
||
'license' => (string) ($pay_meta['license'] ?? ''),
|
||
'compat' => (string) ($pay_meta['compat'] ?? ''),
|
||
'demo_url' => (string) ($pay_meta['demo_url'] ?? ''),
|
||
'downloads' => array_values(is_array($pay_meta['downloads'] ?? null) ? $pay_meta['downloads'] : []),
|
||
'download_count' => max(0, max($download_count, $legacy_download_count)),
|
||
'view_count' => max(0, max($resource_view_count, $common_view_count)),
|
||
'require_login' => !empty($pay_meta['require_login']),
|
||
'require_captcha' => !empty($pay_meta['require_captcha']),
|
||
];
|
||
|
||
// 一次取出全部 post meta(WP 已缓存到 object cache)
|
||
$all = get_post_meta($p->ID);
|
||
if (!is_array($all)) $all = [];
|
||
|
||
$get = static function ($key) use ($all) {
|
||
if (!isset($all[$key]) || !is_array($all[$key]) || empty($all[$key])) return null;
|
||
return maybe_unserialize($all[$key][0]);
|
||
};
|
||
|
||
$downloads = $get('_aksrt_res_downloads');
|
||
if (!is_array($downloads)) $downloads = [];
|
||
$downloads = array_values(array_filter(array_map(static function ($row) {
|
||
if (!is_array($row)) return null;
|
||
$extract_keys = [
|
||
'extract_code', 'extractCode', 'extract', 'extract_key',
|
||
'extraction_code', 'extractionCode',
|
||
'code', 'password', 'pwd',
|
||
'pan_code', 'panCode', 'pan_password', 'panPassword',
|
||
'access_code', 'accessCode',
|
||
];
|
||
if (!array_key_exists('extract_code', $row)) {
|
||
foreach ($extract_keys as $alias) {
|
||
if (isset($row[$alias]) && !is_array($row[$alias]) && trim((string) $row[$alias]) !== '') {
|
||
$row['extract_code'] = (string) $row[$alias];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
$row['extract_code'] = isset($row['extract_code']) ? trim((string) $row['extract_code']) : '';
|
||
return $row;
|
||
}, $downloads)));
|
||
$resource_download_count = (int) ($get('_aksrt_res_download_count') ?? 0);
|
||
$legacy_download_count = (int) ($get('download_count') ?? 0);
|
||
$resource_view_count = (int) ($get('_aksrt_res_view_count') ?? 0);
|
||
$common_view_count = (int) ($get('aksrt_post_views') ?? 0);
|
||
|
||
$allowed_pay_types = ['download', 'reading', 'gallery', 'video', 'vip'];
|
||
$pay_type = (string) ($get('_aksrt_res_pay_type') ?? 'download');
|
||
if (!in_array($pay_type, $allowed_pay_types, true)) {
|
||
$pay_type = 'download';
|
||
}
|
||
|
||
return [
|
||
'version' => (string) ($get('_aksrt_res_version') ?? ''),
|
||
'size' => (string) ($get('_aksrt_res_size') ?? ''),
|
||
'price' => (float) ($get('_aksrt_res_price') ?? 0),
|
||
'original_price' => (float) ($get('_aksrt_res_original_price') ?? 0),
|
||
'vip1_price' => (float) ($get('_aksrt_res_vip1_price') ?? 0),
|
||
'vip2_price' => (float) ($get('_aksrt_res_vip2_price') ?? 0),
|
||
'pay_type' => $pay_type,
|
||
'license' => (string) ($get('_aksrt_res_license') ?? ''),
|
||
'compat' => (string) ($get('_aksrt_res_compat') ?? ''),
|
||
'demo_url' => (string) ($get('_aksrt_res_demo_url') ?? ''),
|
||
'downloads' => array_values($downloads),
|
||
'download_count' => max(0, max($resource_download_count, $legacy_download_count)),
|
||
'view_count' => max(0, max($resource_view_count, $common_view_count)),
|
||
'require_login' => (bool) ($get('_aksrt_res_require_login') ?? false),
|
||
'require_captcha' => (bool) ($get('_aksrt_res_require_captcha') ?? false),
|
||
];
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_default_resource_meta')) {
|
||
function aksrt_default_resource_meta(): array {
|
||
$meta = AKSRT_Domain_Model::default_pay_meta();
|
||
|
||
return [
|
||
'version' => (string) ($meta['version'] ?? ''),
|
||
'size' => (string) ($meta['size'] ?? ''),
|
||
'price' => (float) ($meta['price'] ?? 0),
|
||
'original_price' => (float) ($meta['original_price'] ?? 0),
|
||
'vip1_price' => (float) ($meta['vip1_price'] ?? 0),
|
||
'vip2_price' => (float) ($meta['vip2_price'] ?? 0),
|
||
'pay_type' => AKSRT_Domain_Model::PAY_TYPE_DOWNLOAD,
|
||
'license' => (string) ($meta['license'] ?? ''),
|
||
'compat' => (string) ($meta['compat'] ?? ''),
|
||
'demo_url' => (string) ($meta['demo_url'] ?? ''),
|
||
'downloads' => [],
|
||
'download_count' => 0,
|
||
'view_count' => 0,
|
||
'require_login' => !empty($meta['require_login']),
|
||
'require_captcha' => !empty($meta['require_captcha']),
|
||
];
|
||
|
||
return [
|
||
'version' => '',
|
||
'size' => '',
|
||
'price' => 0.0,
|
||
'original_price' => 0.0,
|
||
'vip1_price' => 0.0,
|
||
'vip2_price' => 0.0,
|
||
'pay_type' => 'download',
|
||
'license' => '',
|
||
'compat' => '',
|
||
'demo_url' => '',
|
||
'downloads' => [],
|
||
'download_count' => 0,
|
||
'view_count' => 0,
|
||
'require_login' => false,
|
||
'require_captcha' => false,
|
||
];
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_price_label')) {
|
||
/**
|
||
* 把价格数字渲染成展示徽章文案。
|
||
*
|
||
* @param float $price
|
||
* @return array { text:string, free:bool }
|
||
*/
|
||
function aksrt_resource_price_label(float $price): array {
|
||
if ($price <= 0) {
|
||
return [
|
||
'text' => __('免费', 'aksrt'),
|
||
'free' => true,
|
||
];
|
||
}
|
||
$n = (fmod($price, 1.0) === 0.0) ? (string) (int) $price : rtrim(rtrim(number_format($price, 2, '.', ''), '0'), '.');
|
||
return [
|
||
'text' => sprintf(__('%s 积分', 'aksrt'), $n),
|
||
'free' => false,
|
||
];
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_price_amount')) {
|
||
/**
|
||
* Format the raw resource price number for compact UI labels.
|
||
*
|
||
* @param float $price
|
||
* @return string
|
||
*/
|
||
function aksrt_resource_price_amount(float $price): string {
|
||
if (fmod($price, 1.0) === 0.0) {
|
||
return (string) (int) $price;
|
||
}
|
||
|
||
return rtrim(rtrim(number_format($price, 2, '.', ''), '0'), '.');
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_card_badge_text')) {
|
||
/**
|
||
* Resource badge text used in mixed post cards.
|
||
*
|
||
* Only resource-type posts should render this badge.
|
||
*
|
||
* @param int|WP_Post|null $post
|
||
* @return string
|
||
*/
|
||
function aksrt_resource_card_badge_text($post = null): string {
|
||
if (!function_exists('aksrt_is_resource_post') || !aksrt_is_resource_post($post)) {
|
||
return '';
|
||
}
|
||
|
||
$meta = aksrt_get_resource_meta($post);
|
||
$price = (float) $meta['price'];
|
||
|
||
if ($price <= 0) {
|
||
// 免费资源不在卡片上显示价格 chip。
|
||
return '';
|
||
}
|
||
|
||
$currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt');
|
||
return sprintf(__('付费 %s %s', 'aksrt'), aksrt_resource_price_amount($price), $currency);
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_pay_type_badge')) {
|
||
/**
|
||
* 根据付费类型返回徽章 HTML。
|
||
*
|
||
* @param string $pay_type
|
||
* @return string HTML 或空字符串
|
||
*/
|
||
function aksrt_resource_pay_type_badge(string $pay_type): string {
|
||
$badges = [
|
||
'reading' => ['label' => __('付费阅读', 'aksrt'), 'color' => '#EF4444', 'icon' => 'fa-lock'],
|
||
'download'=> ['label' => __('付费下载', 'aksrt'), 'color' => '#F97316', 'icon' => 'fa-download'],
|
||
'gallery' => ['label' => __('付费图库', 'aksrt'), 'color' => '#10B981', 'icon' => 'fa-images'],
|
||
'video' => ['label' => __('付费视频', 'aksrt'), 'color' => '#8B5CF6', 'icon' => 'fa-play-circle'],
|
||
'vip' => ['label' => __('VIP 专属', 'aksrt'), 'color' => '#3B82F6', 'icon' => 'fa-crown'],
|
||
];
|
||
|
||
if ($pay_type === 'download' || !isset($badges[$pay_type])) {
|
||
return '';
|
||
}
|
||
|
||
$b = $badges[$pay_type];
|
||
return sprintf(
|
||
'<span class="resource-pay-type-badge" style="background:%s"><i class="fas %s"></i> %s</span>',
|
||
esc_attr($b['color']),
|
||
esc_attr($b['icon']),
|
||
esc_html($b['label'])
|
||
);
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_preview_images')) {
|
||
/**
|
||
* Collect preview images for resource cards and archive thumbnails.
|
||
*
|
||
* Priority: curated cover_images meta -> featured image -> gallery/content images.
|
||
*
|
||
* @param int|WP_Post|null $post
|
||
* @param int $limit
|
||
* @return string[]
|
||
*/
|
||
function aksrt_resource_preview_images($post = null, int $limit = 4): array {
|
||
$p = get_post($post);
|
||
if (!($p instanceof WP_Post) || !function_exists('aksrt_is_resource_post') || !aksrt_is_resource_post($p)) {
|
||
return [];
|
||
}
|
||
|
||
$limit = max(1, min(8, $limit));
|
||
$images = [];
|
||
|
||
if (class_exists('AKSRT_Post_Meta_Box')) {
|
||
$cover_images = (string) AKSRT_Post_Meta_Box::get_meta_value($p->ID, 'cover_images', '');
|
||
if ($cover_images !== '') {
|
||
$cover_ids = array_filter(array_map('absint', preg_split('/[\s,]+/', $cover_images) ?: []));
|
||
foreach ($cover_ids as $attachment_id) {
|
||
$url = (string) wp_get_attachment_image_url($attachment_id, 'medium_large');
|
||
if ($url !== '') {
|
||
$images[] = esc_url_raw($url);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (has_post_thumbnail($p)) {
|
||
$featured = (string) get_the_post_thumbnail_url($p, 'medium_large');
|
||
if ($featured !== '') {
|
||
$images[] = esc_url_raw($featured);
|
||
}
|
||
}
|
||
|
||
if (function_exists('aksrt_get_post_gallery_images')) {
|
||
$images = array_merge($images, aksrt_get_post_gallery_images($p->ID, $limit));
|
||
}
|
||
|
||
if (function_exists('aksrt_get_first_content_image_url')) {
|
||
$content_image = (string) aksrt_get_first_content_image_url($p->ID);
|
||
if ($content_image !== '') {
|
||
$images[] = esc_url_raw($content_image);
|
||
}
|
||
}
|
||
|
||
$images = array_values(array_unique(array_filter($images, static function ($url): bool {
|
||
return is_string($url) && $url !== '';
|
||
})));
|
||
|
||
return array_slice($images, 0, $limit);
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_primary_image_url')) {
|
||
/**
|
||
* Primary preview image for a resource post.
|
||
*
|
||
* @param int|WP_Post|null $post
|
||
* @return string
|
||
*/
|
||
function aksrt_resource_primary_image_url($post = null): string {
|
||
$images = aksrt_resource_preview_images($post, 1);
|
||
return $images[0] ?? '';
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_meta_strip')) {
|
||
/**
|
||
* 卡片用的紧凑元数据条 [v1.0 · 210MB · ↓1234]。
|
||
*
|
||
* @param array $meta aksrt_get_resource_meta 返回值
|
||
* @return array 字符串数组
|
||
*/
|
||
function aksrt_resource_meta_strip(array $meta): array {
|
||
$parts = [];
|
||
if ($meta['version'] !== '') {
|
||
$parts[] = 'v' . $meta['version'];
|
||
}
|
||
if ($meta['size'] !== '') {
|
||
$parts[] = $meta['size'];
|
||
}
|
||
if ($meta['download_count'] > 0) {
|
||
$parts[] = '↓ ' . number_format_i18n($meta['download_count']);
|
||
}
|
||
return $parts;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 是否命中下载积分免扣策略。
|
||
*/
|
||
if (!function_exists('aksrt_is_download_credit_exempt_user')) {
|
||
function aksrt_is_download_credit_exempt_user(int $user_id = 0): bool {
|
||
if ($user_id <= 0 || !class_exists('AKSRT_Settings')) {
|
||
return false;
|
||
}
|
||
|
||
$paid_settings = AKSRT_Settings::get_paid_content_settings();
|
||
if (empty($paid_settings['vip_free_download']) || empty($paid_settings['vip_exempt_roles'])) {
|
||
return false;
|
||
}
|
||
|
||
$user = get_userdata($user_id);
|
||
if (!$user || empty($user->roles) || !is_array($user->roles)) {
|
||
return false;
|
||
}
|
||
|
||
return !empty(array_intersect($user->roles, (array) $paid_settings['vip_exempt_roles']));
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_can_download')) {
|
||
/**
|
||
* 是否可下载(P3 阶段:登录 + 积分校验已接入;P5 接入验证码)。
|
||
*
|
||
* 返回 WP_Error 表示拒绝;返回 true 表示放行。
|
||
*
|
||
* @param int|WP_Post|null $post
|
||
* @param int $user_id 0 表示当前用户
|
||
* @return true|WP_Error
|
||
*/
|
||
function aksrt_can_download($post = null, int $user_id = 0) {
|
||
if (class_exists('AKSRT_Content_Visibility')) {
|
||
return AKSRT_Content_Visibility::can_download_resource($post, $user_id);
|
||
}
|
||
|
||
$p = get_post($post);
|
||
if (!($p instanceof WP_Post) || !aksrt_is_resource_post($p)) {
|
||
return new WP_Error('aksrt_not_resource', __('该内容不是可下载资源。', 'aksrt'));
|
||
}
|
||
|
||
$meta = aksrt_get_resource_meta($p);
|
||
$paid_settings = class_exists('AKSRT_Settings')
|
||
? AKSRT_Settings::get_paid_content_settings()
|
||
: [
|
||
'download_login' => true,
|
||
'download_credit' => true,
|
||
];
|
||
|
||
// 登录门槛:全局开关 OR 单条覆盖
|
||
$need_login = !empty($paid_settings['download_login']) || !empty($meta['require_login']);
|
||
$uid = $user_id > 0 ? $user_id : get_current_user_id();
|
||
|
||
if ($need_login && $uid <= 0) {
|
||
return new WP_Error('aksrt_need_login', __('请先登录后再下载。', 'aksrt'), [
|
||
'status' => 401,
|
||
'login_url' => wp_login_url(get_permalink($p)),
|
||
]);
|
||
}
|
||
|
||
// 积分门槛:仅在 cms_features.download_credit 开启 + 实际成本 > 0 + 登录态时才校验
|
||
$credit_enabled = !empty($paid_settings['download_credit']);
|
||
|
||
if ($credit_enabled) {
|
||
$cost = (int) aksrt_resource_download_cost($p);
|
||
if ($cost > 0) {
|
||
if ($uid <= 0) {
|
||
return new WP_Error('aksrt_need_login', __('请先登录后再下载。', 'aksrt'), [
|
||
'status' => 401,
|
||
'login_url' => wp_login_url(get_permalink($p)),
|
||
]);
|
||
}
|
||
$balance = class_exists('AKSRT_Credits') ? AKSRT_Credits::balance($uid) : 0;
|
||
if ($balance < $cost) {
|
||
return new WP_Error('aksrt_credits_insufficient', __('积分不足,无法下载。', 'aksrt'), [
|
||
'status' => 402,
|
||
'balance' => $balance,
|
||
'cost' => $cost,
|
||
]);
|
||
}
|
||
}
|
||
}
|
||
|
||
// P5 阶段:验证码校验(在请求时校验,不在 can_download 静态判定中拦截)
|
||
return true;
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_download_cost')) {
|
||
/**
|
||
* 取实际需要扣除的积分(向上取整),未启用积分门槛时返回 0。
|
||
*
|
||
* 优先级:单条 _aksrt_res_price > 全局 download_default_cost。
|
||
*/
|
||
function aksrt_resource_download_cost($post = null): int {
|
||
$meta = aksrt_get_resource_meta($post);
|
||
$paid_settings = class_exists('AKSRT_Settings')
|
||
? AKSRT_Settings::get_paid_content_settings()
|
||
: [
|
||
'download_credit' => true,
|
||
'default_cost' => 0,
|
||
];
|
||
if (empty($paid_settings['download_credit'])) return 0;
|
||
if (function_exists('get_current_user_id') && aksrt_is_download_credit_exempt_user((int) get_current_user_id())) {
|
||
return 0;
|
||
}
|
||
$price = (float) $meta['price'];
|
||
if ($price > 0) {
|
||
return (int) ceil($price);
|
||
}
|
||
// 单条未设价格 → 回退到全局默认价
|
||
return max(0, (int) ($paid_settings['default_cost'] ?? 0));
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_meta_query')) {
|
||
/**
|
||
* 「是资源」WP_Query meta_query 片段。
|
||
*
|
||
* v3.4: 资源 = post + _aksrt_is_resource = 1。
|
||
* 兼容历史 aksrt_resource CPT 时由调用方决定是否额外加 post_type。
|
||
*
|
||
* @return array
|
||
*/
|
||
function aksrt_resource_meta_query(): array {
|
||
return [
|
||
'key' => '_aksrt_is_resource',
|
||
'value' => '1',
|
||
'compare' => '=',
|
||
];
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_post_types')) {
|
||
/**
|
||
* 资源查询使用的 post_type 数组。
|
||
*
|
||
* 当历史 aksrt_resource CPT 仍在站点中存在(未迁移完成)时,会自动包含。
|
||
*
|
||
* @return array
|
||
*/
|
||
function aksrt_resource_post_types(): array {
|
||
$types = ['post'];
|
||
if (post_type_exists('aksrt_resource')) {
|
||
$types[] = 'aksrt_resource';
|
||
}
|
||
return $types;
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_archive_url')) {
|
||
/**
|
||
* 取资源归档页 URL(v3.4 起统一为 /resources/)。
|
||
*/
|
||
function aksrt_resource_archive_url(): string {
|
||
return home_url('/resources/');
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_is_resource_archive')) {
|
||
/**
|
||
* 当前请求是否为资源归档(/resources)。
|
||
*
|
||
* 兼容历史 aksrt_resource CPT 归档。
|
||
*/
|
||
function aksrt_is_resource_archive(): bool {
|
||
if (function_exists('post_type_exists') && post_type_exists('aksrt_resource')
|
||
&& function_exists('is_post_type_archive') && is_post_type_archive('aksrt_resource')) {
|
||
return true;
|
||
}
|
||
return (bool) get_query_var('aksrt_is_resource_archive');
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_detect_cloud_service')) {
|
||
/**
|
||
* 从下载链接自动识别云盘服务商。
|
||
*
|
||
* @param string $url 下载链接
|
||
* @return array { key:string, name:string, color:string }
|
||
*/
|
||
function aksrt_detect_cloud_service(string $url): array {
|
||
$url_lower = strtolower($url);
|
||
|
||
$services = [
|
||
'baidu' => ['name' => '百度网盘', 'color' => '#1578f8', 'pattern' => ['pan.baidu.com', 'yun.baidu.com']],
|
||
'lanzou' => ['name' => '蓝奏云', 'color' => '#f37526', 'pattern' => ['lanzouf.com', 'lanzoui.com', 'lanzoux.com', 'lanzouw.com', 'lanzoup.com', 'lanzout.com', 'lanzou']],
|
||
'aliyun' => ['name' => '阿里云盘', 'color' => '#6666ff', 'pattern' => ['alipan.com', 'aliyundrive.com']],
|
||
'weiyun' => ['name' => '微云', 'color' => '#4facfe', 'pattern' => ['share.weiyun.com', 'weiyun.com']],
|
||
'onedrive' => ['name' => 'OneDrive', 'color' => '#0078d4', 'pattern' => ['1drv.ms', 'onedrive.live.com']],
|
||
'tianyi' => ['name' => '天翼云盘', 'color' => '#0099ff', 'pattern' => ['cloud.189.cn']],
|
||
'123pan' => ['name' => '123云盘', 'color' => '#2b7bff', 'pattern' => ['123pan.com', '123684.com']],
|
||
'quark' => ['name' => '夸克网盘', 'color' => '#6a5acd', 'pattern' => ['pan.quark.cn']],
|
||
'xunlei' => ['name' => '迅雷云盘', 'color' => '#00a4ff', 'pattern' => ['pan.xunlei.com']],
|
||
'mega' => ['name' => 'MEGA', 'color' => '#d92323', 'pattern' => ['mega.nz', 'mega.co.nz']],
|
||
'gofile' => ['name' => 'GoFile', 'color' => '#4caf50', 'pattern' => ['gofile.io']],
|
||
'mediafire' => ['name' => 'MediaFire', 'color' => '#1294f2', 'pattern' => ['mediafire.com']],
|
||
'github' => ['name' => 'GitHub', 'color' => '#333333', 'pattern' => ['github.com', 'raw.githubusercontent.com']],
|
||
];
|
||
|
||
foreach ($services as $key => $svc) {
|
||
foreach ($svc['pattern'] as $p) {
|
||
if (strpos($url_lower, $p) !== false) {
|
||
return ['key' => $key, 'name' => $svc['name'], 'color' => $svc['color']];
|
||
}
|
||
}
|
||
}
|
||
|
||
return ['key' => 'other', 'name' => __('下载', 'aksrt'), 'color' => '#6b7280'];
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_meta_icon')) {
|
||
/**
|
||
* 根据元信息字段返回对应的 Font Awesome 图标类。
|
||
*/
|
||
function aksrt_resource_meta_icon(string $field): string {
|
||
$icons = [
|
||
'version' => 'fas fa-code-branch',
|
||
'size' => 'fas fa-hdd',
|
||
'compat' => 'fas fa-laptop',
|
||
'license' => 'fas fa-shield-alt',
|
||
'demo_url' => 'fas fa-external-link-alt',
|
||
'download' => 'fas fa-download',
|
||
'views' => 'fas fa-eye',
|
||
];
|
||
return $icons[$field] ?? 'fas fa-info-circle';
|
||
}
|
||
}
|