Normalize fixed profile fields, profile actions, and the five-column capability matrix for comments, uploads, and downloads.
563 lines
22 KiB
PHP
563 lines
22 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\Core\DomainModel::default_pay_meta();
|
||
$download_count = (int) get_post_meta($p->ID, \AKSRT\Core\DomainModel::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\Core\DomainModel::RESOURCE_VIEW_COUNT_KEY, true);
|
||
$common_view_count = (int) get_post_meta($p->ID, \AKSRT\Core\DomainModel::POST_VIEW_COUNT_KEY, true);
|
||
|
||
// Normalize downloads extract_code aliases for legacy rows still stored on pay meta.
|
||
$downloads = array_values(is_array($pay_meta['downloads'] ?? null) ? $pay_meta['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)));
|
||
|
||
$virtual_sales = max(0, (int) ($pay_meta['virtual_sales'] ?? 0));
|
||
$show_sales = !isset($pay_meta['show_sales']) || !empty($pay_meta['show_sales']);
|
||
|
||
return [
|
||
'version' => (string) ($pay_meta['version'] ?? ''),
|
||
'size' => (string) ($pay_meta['size'] ?? ''),
|
||
'price' => (float) ($pay_meta['price'] ?? 0),
|
||
'points_price' => (int) ($pay_meta['points_price'] ?? 0),
|
||
'pay_modo' => (($pay_meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0',
|
||
'pay_limit' => in_array((int) ($pay_meta['pay_limit'] ?? 0), [0, 1, 2], true) ? (int) $pay_meta['pay_limit'] : 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),
|
||
'vip1_points' => (int) ($pay_meta['vip1_points'] ?? 0),
|
||
'vip2_points' => (int) ($pay_meta['vip2_points'] ?? 0),
|
||
'pay_type' => (string) ($pay_meta['pay_type'] ?? \AKSRT\Core\DomainModel::PAY_TYPE_DOWNLOAD),
|
||
'license' => (string) ($pay_meta['license'] ?? ''),
|
||
'compat' => (string) ($pay_meta['compat'] ?? ''),
|
||
'demo_url' => (string) ($pay_meta['demo_url'] ?? ''),
|
||
'downloads' => $downloads,
|
||
'download_count' => max(0, max($download_count, $legacy_download_count)),
|
||
'view_count' => max(0, max($resource_view_count, $common_view_count)),
|
||
'virtual_sales' => $virtual_sales,
|
||
'sales_count' => $show_sales ? ($virtual_sales + max(0, max($download_count, $legacy_download_count))) : 0,
|
||
'show_sales' => $show_sales,
|
||
'require_login' => !empty($pay_meta['require_login']),
|
||
'require_captcha' => !empty($pay_meta['require_captcha']),
|
||
];
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_default_resource_meta')) {
|
||
function aksrt_default_resource_meta(): array {
|
||
$meta = \AKSRT\Core\DomainModel::default_pay_meta();
|
||
|
||
return [
|
||
'version' => (string) ($meta['version'] ?? ''),
|
||
'size' => (string) ($meta['size'] ?? ''),
|
||
'price' => (float) ($meta['price'] ?? 0),
|
||
'points_price' => (int) ($meta['points_price'] ?? 0),
|
||
'pay_modo' => (($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0',
|
||
'pay_limit' => in_array((int) ($meta['pay_limit'] ?? 0), [0, 1, 2], true) ? (int) $meta['pay_limit'] : 0,
|
||
'original_price' => (float) ($meta['original_price'] ?? 0),
|
||
'vip1_price' => (float) ($meta['vip1_price'] ?? 0),
|
||
'vip2_price' => (float) ($meta['vip2_price'] ?? 0),
|
||
'vip1_points' => (int) ($meta['vip1_points'] ?? 0),
|
||
'vip2_points' => (int) ($meta['vip2_points'] ?? 0),
|
||
'pay_type' => \AKSRT\Core\DomainModel::PAY_TYPE_DOWNLOAD,
|
||
'license' => (string) ($meta['license'] ?? ''),
|
||
'compat' => (string) ($meta['compat'] ?? ''),
|
||
'demo_url' => (string) ($meta['demo_url'] ?? ''),
|
||
'downloads' => [],
|
||
'download_count' => 0,
|
||
'view_count' => 0,
|
||
'virtual_sales' => 0,
|
||
'sales_count' => 0,
|
||
'show_sales' => true,
|
||
'require_login' => !empty($meta['require_login']),
|
||
'require_captcha' => !empty($meta['require_captcha']),
|
||
];
|
||
}
|
||
}
|
||
|
||
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')) {
|
||
/**
|
||
* List-card pay badge (Zibll zib_get_posts_list_pay_tags equivalent).
|
||
*
|
||
* Renders for any paid post type, not only download resources.
|
||
* Returns plain text; card template wraps with link + class.
|
||
*
|
||
* @param int|WP_Post|null $post
|
||
* @return string
|
||
*/
|
||
function aksrt_resource_card_badge_text($post = null): string {
|
||
$p = get_post($post);
|
||
if (!($p instanceof WP_Post)) {
|
||
return '';
|
||
}
|
||
|
||
$meta = function_exists('aksrt_get_pay_meta') ? aksrt_get_pay_meta($p) : null;
|
||
if (!is_array($meta)) {
|
||
return '';
|
||
}
|
||
|
||
$pay_type = (string) ($meta['pay_type'] ?? 'no');
|
||
if ($pay_type === '' || $pay_type === 'no') {
|
||
return '';
|
||
}
|
||
|
||
$pay_modo = (($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
|
||
$pay_limit = (int) ($meta['pay_limit'] ?? 0);
|
||
$type_labels = function_exists('aksrt_get_pay_types') ? aksrt_get_pay_types() : [];
|
||
$type_name = $type_labels[$pay_type] ?? __('付费内容', 'aksrt');
|
||
|
||
// VIP-only / purchase limit (Zibll pay_limit).
|
||
if ($pay_type === 'vip' || $pay_limit > 0) {
|
||
return __('会员专属', 'aksrt');
|
||
}
|
||
|
||
$priced = function_exists('aksrt_get_user_pay_price')
|
||
? aksrt_get_user_pay_price($p)
|
||
: [
|
||
'amount' => $pay_modo === 'points' ? (float) ($meta['points_price'] ?? 0) : (float) ($meta['price'] ?? 0),
|
||
'modo' => $pay_modo,
|
||
];
|
||
$price = (float) ($priced['amount'] ?? 0);
|
||
$pay_modo = (($priced['modo'] ?? $pay_modo) === 'points') ? 'points' : '0';
|
||
|
||
// Free paid-type (price 0).
|
||
if ($price <= 0) {
|
||
if ($pay_type === 'download') {
|
||
return __('免费资源', 'aksrt');
|
||
}
|
||
return str_replace(__('付费', 'aksrt'), __('免费', 'aksrt'), (string) $type_name);
|
||
}
|
||
|
||
if ($pay_modo === 'points') {
|
||
$currency = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_currency_name() : __('积分', 'aksrt');
|
||
$amount = function_exists('aksrt_resource_price_amount')
|
||
? aksrt_resource_price_amount($price)
|
||
: (string) (int) $price;
|
||
return sprintf('%s %s%s', $type_name, $amount, $currency);
|
||
}
|
||
|
||
$symbol = '¥';
|
||
if (class_exists('\AKSRT\Settings\Settings')) {
|
||
$paid = \AKSRT\Settings\Settings::get_paid_content_settings();
|
||
$symbol = (string) ($paid['display']['currency_symbol'] ?? '¥');
|
||
}
|
||
$amount = function_exists('aksrt_format_price')
|
||
? aksrt_format_price($price)
|
||
: (string) $price;
|
||
return sprintf('%s %s%s', $type_name, $symbol, $amount);
|
||
}
|
||
}
|
||
|
||
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\Core\PostMetaBox')) {
|
||
$cover_images = (string) \AKSRT\Core\PostMetaBox::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\Settings')) {
|
||
return false;
|
||
}
|
||
|
||
$paid_settings = \AKSRT\Settings\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')) {
|
||
/**
|
||
* 是否可下载。
|
||
*
|
||
* 单一合同:委托 \AKSRT\Content\Visibility(收银台订单解锁 / VIP / 登录 / 日限额)。
|
||
* 不再用 cms_features.download_credit 做「按次扣积分」门禁。
|
||
*
|
||
* @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)) {
|
||
return new WP_Error('aksrt_not_resource', __('该内容不是可下载资源。', 'aksrt'));
|
||
}
|
||
|
||
$uid = $user_id > 0 ? $user_id : get_current_user_id();
|
||
if (!function_exists('aksrt_user_can') || !aksrt_user_can('resource_download', $uid, (int) $p->ID)) {
|
||
return new WP_Error('aksrt_need_login', __('请先登录后再下载。', 'aksrt'), [
|
||
'status' => 401,
|
||
'login_url' => wp_login_url(get_permalink($p)),
|
||
]);
|
||
}
|
||
|
||
// Without Content_Visibility, only login gate remains.
|
||
return true;
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_download_cost')) {
|
||
/**
|
||
* 下载侧展示用「未解锁积分价」。
|
||
*
|
||
* 现金 pay_modo:永远 0(走订单解锁,不按次扣积分)。
|
||
* 积分 pay_modo:未购时返回积分价(用于 UI);已购订单后 0。
|
||
* 实际扣费只在收银台创建 resource 订单时发生,下载 token 不再扣积分。
|
||
*/
|
||
function aksrt_resource_download_cost($post = null): int {
|
||
$p = get_post($post);
|
||
$uid = function_exists('get_current_user_id') ? (int) get_current_user_id() : 0;
|
||
|
||
// Paid order → unlocked.
|
||
if ($p instanceof WP_Post && $uid > 0 && class_exists('\AKSRT\Payment\Order')) {
|
||
if (\AKSRT\Payment\Order::get_instance()->has_paid_access(
|
||
$uid,
|
||
\AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
|
||
(int) $p->ID
|
||
)) {
|
||
return 0;
|
||
}
|
||
}
|
||
if ($p instanceof WP_Post && $uid <= 0 && function_exists('aksrt_guest_has_paid_access') && aksrt_guest_has_paid_access((int) $p->ID)) {
|
||
return 0;
|
||
}
|
||
|
||
$priced = function_exists('aksrt_get_user_pay_price')
|
||
? aksrt_get_user_pay_price($post, $uid)
|
||
: null;
|
||
|
||
$pay_modo = is_array($priced) && (($priced['modo'] ?? '0') === 'points') ? 'points' : '0';
|
||
if (!is_array($priced) && function_exists('aksrt_get_pay_meta')) {
|
||
$pay = aksrt_get_pay_meta($post);
|
||
$pay_modo = (($pay['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
|
||
}
|
||
|
||
// Cash mode: order unlock only.
|
||
if ($pay_modo !== 'points') {
|
||
return 0;
|
||
}
|
||
|
||
if ($uid > 0 && function_exists('aksrt_is_download_credit_exempt_user') && aksrt_is_download_credit_exempt_user($uid)) {
|
||
return 0;
|
||
}
|
||
|
||
if (is_array($priced)) {
|
||
$price = (float) ($priced['amount'] ?? 0);
|
||
return $price > 0 ? (int) ceil($price) : 0;
|
||
}
|
||
|
||
$meta = function_exists('aksrt_get_pay_meta') ? aksrt_get_pay_meta($post) : [];
|
||
$price = (float) ($meta['points_price'] ?? $meta['price'] ?? 0);
|
||
return $price > 0 ? (int) ceil($price) : 0;
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_meta_query')) {
|
||
/**
|
||
* 「是资源」WP_Query meta_query 片段:post + _aksrt_is_resource = 1。
|
||
*
|
||
* @return array
|
||
*/
|
||
function aksrt_resource_meta_query(): array {
|
||
return [
|
||
'key' => '_aksrt_is_resource',
|
||
'value' => '1',
|
||
'compare' => '=',
|
||
];
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_resource_archive_url')) {
|
||
/**
|
||
* 资源列表页 URL(/resources/)。
|
||
*/
|
||
function aksrt_resource_archive_url(): string {
|
||
return home_url('/resources/');
|
||
}
|
||
}
|
||
|
||
if (!function_exists('aksrt_is_resource_archive')) {
|
||
/**
|
||
* 当前请求是否为资源列表(/resources 虚拟归档)。
|
||
*/
|
||
function aksrt_is_resource_archive(): bool {
|
||
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';
|
||
}
|
||
}
|