Files
wordpress-theme-aksrt/inc/helpers/jio-graphic-card.php
T
kate522andClaude Opus 5 35bb96e82f refactor: rename the theme brand and every identifier from AKSRT to Jio
Full-project rename. `git grep -i aksrt` is now empty apart from the
DBMigrator 3.3.0 changelog note that documents the rename itself.

Code identifiers
- PHP namespace AKSRT\ -> Jio\ (composer PSR-4 + 378 declarations)
- global constants AKSRT_* -> JIO_* (VERSION/DIR/URI, PAY_TYPE_*, CAPTCHA_*)
- procedural functions, hooks, options, meta keys, table names,
  cookies, query vars, ajax actions and nonces: aksrt_ -> jio_
- text domain aksrt -> jio; Theme Name -> Jio
- JS globals: aksrtData/aksrtAdminData/... -> jioData/jioAdminData/...,
  window.AKSRTCaptcha & friends -> window.JioCaptcha, Aksrt* -> Jio*
- Vue components Aks*.vue -> Jio*.vue (15 files renamed + imports)
- CSS classes/data-attrs/custom properties: aksrt- -> jio-
- REST namespace aksrt/v1 -> jio/v1 (incl. payment gateway callbacks)

Storage layer
- DB tables {prefix}aksrt_* -> {prefix}jio_*; SCHEMA_VERSION 3.2.0 -> 3.3.0
  so dbDelta creates the new names on install
- widget id_base aksrt_widget_* -> jio_widget_*
- uninstall.php drop list rebuilt from the actual migrator tables
  (dropped 3 stale entries, added the 17 missing ones)

Removed
- hardcoded https://api.aksrt.com/version.json default update endpoint;
  get_endpoint() now reads the 「更新端点」 setting and do_check() no-ops
  when it is empty

Files renamed: inc/helpers/aksrt-*.php -> jio-*.php (54),
assets/admin/src/components/form/Aks*.vue -> Jio*.vue (15).
Build artifacts regenerated: assets/css/build, assets/js/runtime,
assets/admin/build.

Verified: audit-psr4-paths errors=0, audit-admin-contracts errors=0
(warnings=56, unchanged baseline), 813/813 widget-system tests,
44/44 phpunit, php -l clean across all PHP.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-11-01 20:05:04 +08:00

273 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Shared graphic / cover card (legacy parity).
*
* Used by term cards, cover cards, term aggregation thumbs, etc.
*
* @package Jio
*/
defined('ABSPATH') || exit;
if (!function_exists('jio_graphic_card')) :
/**
* Render a graphic cover card.
*
* @param array<string,mixed> $args {
* @type string $type style-1|style-2|style-3|style-4|''.
* @type string $class Extra classes on .graphic.
* @type string $img Image URL.
* @type string $video Optional video URL (desktop).
* @type string $alt Image alt.
* @type array{url?:string,target?:string}|string $link Link.
* @type string $text1 Primary text.
* @type string $text2 Secondary text.
* @type string $text3 Tertiary / badge text (HTML allowed for icon+count).
* @type string $more Extra absolute HTML (badge etc).
* @type bool $lazy Use the legacy lazySizes contract.
* @type int|float $height_scale Padding-bottom % (0 = default CSS).
* @type int|float $mask_opacity 0–100 overlay opacity.
* @type string $hide pc|m|'' hide on device.
* }
* @param bool $echo Echo instead of return.
*/
function jio_graphic_card(array $args = [], bool $echo = false): string {
$defaults = [
'type' => '',
'hide' => '',
'class' => 'mb10',
'img' => '',
'video' => '',
'alt' => __('图片', 'jio'),
'link' => [
'url' => '',
'target' => '',
],
'text1' => '',
'text2' => '',
'text3' => '',
'more' => '',
'lazy' => true,
'height_scale' => 0,
'mask_opacity' => 0,
];
$args = wp_parse_args($args, $defaults);
$img_url = trim((string) $args['img']);
$video_url = trim((string) $args['video']);
if ($img_url === '' && $video_url === '') {
return '';
}
// Device visibility.
$hide = sanitize_key((string) $args['hide']);
if ($hide === 'pc' || $hide === 'm') {
$is_mobile = function_exists('wp_is_mobile') ? wp_is_mobile() : false;
if ((!$is_mobile && $hide === 'pc') || ($is_mobile && $hide === 'm')) {
return '';
}
}
$type = sanitize_key((string) $args['type']);
if ($type !== '' && !in_array($type, ['style-1', 'style-2', 'style-3', 'style-4'], true)) {
// Accept bare "1"–"4".
if (preg_match('/^[1-4]$/', $type)) {
$type = 'style-' . $type;
} else {
$type = '';
}
}
$link = $args['link'];
if (is_string($link)) {
$link = ['url' => $link, 'target' => ''];
}
if (!is_array($link)) {
$link = ['url' => '', 'target' => ''];
}
$link_url = esc_url(trim((string) ($link['url'] ?? '')));
$link_target = sanitize_text_field((string) ($link['target'] ?? ''));
$lazy = !empty($args['lazy']);
$media = '';
if ($video_url !== '' && !(function_exists('wp_is_mobile') && wp_is_mobile())) {
if ($lazy && jio_is_lazy('lazy_other')) {
$poster = $img_url !== '' ? ' data-poster="' . esc_url($img_url) . '"' : '';
$media = '<video autoplay loop muted playsinline class="fit-cover lazyload" data-src="' . esc_url($video_url) . '" src=""' . $poster . '></video>';
} else {
$poster = $img_url !== '' ? ' poster="' . esc_url($img_url) . '"' : '';
$media = '<video autoplay loop muted playsinline class="fit-cover" src="' . esc_url($video_url) . '"' . $poster . '></video>';
}
} elseif ($img_url !== '') {
$alt = (string) ($args['alt'] !== '' ? $args['alt'] : __('图片', 'jio'));
if ($lazy) {
$media = '<img' . jio_get_lazy_attr('lazy_other', $img_url, 'fit-cover') . ' alt="' . esc_attr($alt) . '">';
} else {
$media = '<img class="fit-cover" src="' . esc_url($img_url) . '" alt="' . esc_attr($alt) . '">';
}
}
if ($media === '') {
return '';
}
$mask_opacity = max(0, min(100, (int) $args['mask_opacity']));
$mask = $mask_opacity > 0
? '<div class="absolute graphic-mask" style="opacity:' . esc_attr((string) ($mask_opacity / 100)) . '"></div>'
: '';
// text1/2/3 may contain small trusted HTML (icons); sanitize lightly.
$text1 = (string) $args['text1'];
$text2 = (string) $args['text2'];
$text3 = (string) $args['text3'];
$allow = [
'i' => ['class' => true, 'aria-hidden' => true],
'span' => ['class' => true, 'title' => true],
'item' => ['class' => true, 'data-toggle' => true, 'title' => true],
'b' => [],
'strong'=> [],
'em' => [],
'badge' => ['class' => true],
];
$text1_safe = $text1 !== '' ? wp_kses($text1, $allow) : '';
$text2_safe = $text2 !== '' ? wp_kses($text2, $allow) : '';
$text3_safe = $text3 !== '' ? wp_kses($text3, $allow) : '';
$more = (string) $args['more'];
$more_safe = $more !== '' ? wp_kses($more, array_merge($allow, [
'div' => ['class' => true, 'style' => true],
'badge' => ['class' => true],
'svg' => ['class' => true, 'viewbox' => true, 'aria-hidden' => true],
'use' => ['href' => true, 'xlink:href' => true],
])) : '';
$text = '';
if ($type === 'style-2') {
$text = '<div class="abs-center conter-conter graphic-text">';
$text .= $text1_safe !== '' ? '<div class="title-h-center"><b>' . $text1_safe . '</b></div>' : '';
$text .= $text2_safe !== '' ? '<div class="em09 opacity8">' . $text2_safe . '</div>' : '';
$text .= '</div>';
if ($text3_safe !== '') {
$text .= '<div class="abs-center right-top"><badge class="b-black opacity8">' . $text3_safe . '</badge></div>';
}
} elseif ($type === 'style-3') {
$text = $text1_safe !== '' ? '<div class="abs-center left-bottom graphic-text text-ellipsis">' . $text1_safe . '</div>' : '';
$text .= '<div class="abs-center left-bottom graphic-text">';
$text .= $text2_safe !== '' ? '<div class="em09 opacity8">' . $text2_safe . '</div>' : '';
$text .= $text3_safe !== '' ? '<div class="px12 opacity8 mt6">' . $text3_safe . '</div>' : '';
$text .= '</div>';
} elseif ($type === 'style-4') {
if ($text3_safe !== '') {
$text = '<div class="abs-center right-top"><badge class="b-black opacity8 mr6 mt6">' . $text3_safe . '</badge></div>';
}
} else {
// style-1 / default.
$inner = $text1_safe !== '' ? '<div class="title-h-left"><b>' . $text1_safe . '</b></div>' : '';
$inner .= $text3_safe !== '' ? '<div class="em09 opacity8">' . $text3_safe . '</div>' : '';
$inner .= $text2_safe !== '' ? '<div class="em09">' . $text2_safe . '</div>' : '';
$text = $inner !== '' ? '<div class="abs-center left-bottom graphic-text">' . $inner . '</div>' : '';
}
$text .= $more_safe;
$class = trim('graphic hover-zoom-img ' . (string) $args['class'] . ' ' . $type);
$height_scale = max(0, (int) $args['height_scale']);
$scale_attr = $height_scale > 0
? ' style="--cover-height-scale:' . esc_attr((string) $height_scale) . '%;"'
: '';
$html = '';
if ($link_url !== '') {
$tgt = $link_target !== '' ? ' target="' . esc_attr($link_target) . '" rel="noopener noreferrer"' : '';
$html .= '<a href="' . esc_url($link_url) . '"' . $tgt . '>';
}
if ($type === 'style-4') {
$html .= '<div class="main-shadow radius8 main-bg mb10">';
}
$html .= '<div class="' . esc_attr($class) . '"' . $scale_attr . '>';
$html .= $media;
$html .= $mask;
$html .= $text;
if ($type === 'style-4') {
$html .= '</div>'; // close .graphic early for style-4 body.
$html .= '<div class="padding-10">';
$html .= $text1_safe !== '' ? '<div class="text-ellipsis">' . $text1_safe . '</div>' : '';
$html .= $text2_safe !== '' ? '<div class="muted-2-color em09 text-ellipsis mt6">' . $text2_safe . '</div>' : '';
$html .= '</div></div>'; // padding + main-shadow
} else {
$html .= '</div>';
}
if ($link_url !== '') {
$html .= '</a>';
}
if ($echo) {
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return '';
}
return $html;
}
endif;
if (!function_exists('jio_author_minicard')) :
/**
* Author mini card for user lists (legacy).
*
* @param int $user_id
* @param string $class
* @param bool $blur_bg
*/
function jio_author_minicard(int $user_id, string $class = '', bool $blur_bg = false, string $highlight_query = ''): string {
if ($user_id <= 0) {
return '';
}
$user = get_userdata($user_id);
if (!$user) {
return '';
}
$avatar_url = function_exists('jio_get_avatar_url')
? jio_get_avatar_url($user_id, ['size' => 96])
: get_avatar_url($user_id, ['size' => 96]);
$home = function_exists('jio_get_user_home_url')
? jio_get_user_home_url($user_id)
: get_author_posts_url($user_id);
$avatar_box = '<div class="avatar-img"><a href="' . esc_url($home) . '"><img' . jio_get_lazy_attr('lazy_avatar', $avatar_url, 'avatar', jio_get_lazy_thumb('sm')) . ' alt="" width="42" height="42"></a></div>';
$name = function_exists('jio_get_user_name')
? jio_get_user_name([
'id' => $user_id,
'class' => 'flex ac flex1',
'follow' => false,
'medal' => true,
'auth' => true,
'level' => true,
'highlight_query' => $highlight_query,
])
: '<a href="' . esc_url($home) . '">' . esc_html($user->display_name) . '</a>';
// Follow control (separate from name, legacy places both in dt).
$follow = function_exists('jio_get_user_follow')
? jio_get_user_follow('focus-color px12 ml10 follow flex0 but', $user_id)
: '';
$blur = '';
if ($blur_bg) {
$blur = '<div class="abs-blur-bg blur"><img' . jio_get_lazy_attr('lazy_avatar', $avatar_url, '', jio_get_lazy_thumb('sm')) . ' alt=""></div>';
}
$description = function_exists('jio_get_user_description') ? jio_get_user_description($user_id) : trim((string) get_user_meta($user_id, 'description', true));
$description_html = $highlight_query !== '' && function_exists('jio_renderer_highlight_text')
? jio_renderer_highlight_text($description, $highlight_query)
: esc_html($description);
return '<div class="author-minicard radius8 relative-h ' . esc_attr($class) . '">'
. $blur
. '<ul class="list-inline relative">'
. '<li>' . $avatar_box . '</li>'
. '<li><dl>'
. '<dt class="flex ac">' . $name . $follow . '</dt>'
. '<dd class="mt6 em09 muted-color text-ellipsis">' . $description_html . '</dd>'
. '</dl></li>'
. '</ul></div>';
}
endif;