diff --git a/inc/bootstrap.php b/inc/bootstrap.php index aa2e6c2d..b19a0bea 100644 --- a/inc/bootstrap.php +++ b/inc/bootstrap.php @@ -48,6 +48,7 @@ require_once AKSRT_DIR . '/inc/helpers/aksrt-header-userbox.php'; require_once AKSRT_DIR . '/inc/helpers/aksrt-header-menu-buttons.php'; require_once AKSRT_DIR . '/inc/helpers/aksrt-runtime-win.php'; require_once AKSRT_DIR . '/inc/helpers/aksrt-identity.php'; +require_once AKSRT_DIR . '/inc/helpers/aksrt-graphic-card.php'; require_once AKSRT_DIR . '/inc/helpers/aksrt-user-card.php'; require_once AKSRT_DIR . '/inc/helpers/aksrt-rewards.php'; require_once AKSRT_DIR . '/inc/helpers/menu-decoration.php'; diff --git a/inc/helpers/aksrt-graphic-card.php b/inc/helpers/aksrt-graphic-card.php new file mode 100644 index 00000000..93952de6 --- /dev/null +++ b/inc/helpers/aksrt-graphic-card.php @@ -0,0 +1,276 @@ + $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 aksrt-lazy data-src. + * @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 aksrt_graphic_card(array $args = [], bool $echo = false): string { + $defaults = [ + 'type' => '', + 'hide' => '', + 'class' => 'mb10', + 'img' => '', + 'video' => '', + 'alt' => __('图片', 'aksrt'), + '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']); + $placeholder = get_template_directory_uri() . '/assets/img/placeholder.svg'; + $media = ''; + if ($video_url !== '' && !(function_exists('wp_is_mobile') && wp_is_mobile())) { + $poster = $img_url !== '' ? ' poster="' . esc_url($img_url) . '"' : ''; + if ($lazy) { + $media = ''; + } else { + $media = ''; + } + } elseif ($img_url !== '') { + $alt = (string) ($args['alt'] !== '' ? $args['alt'] : __('图片', 'aksrt')); + if ($lazy) { + $media = '' . esc_attr($alt) . ''; + } else { + $media = '' . esc_attr($alt) . ''; + } + } + if ($media === '') { + return ''; + } + + $mask_opacity = max(0, min(100, (int) $args['mask_opacity'])); + $mask = $mask_opacity > 0 + ? '
' + : ''; + + // 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], + ])) : ''; + + $text = ''; + if ($type === 'style-2') { + $text = '
'; + $text .= $text1_safe !== '' ? '
' . $text1_safe . '
' : ''; + $text .= $text2_safe !== '' ? '
' . $text2_safe . '
' : ''; + $text .= '
'; + if ($text3_safe !== '') { + $text .= '
' . $text3_safe . '
'; + } + } elseif ($type === 'style-3') { + $text = $text1_safe !== '' ? '
' . $text1_safe . '
' : ''; + $text .= '
'; + $text .= $text2_safe !== '' ? '
' . $text2_safe . '
' : ''; + $text .= $text3_safe !== '' ? '
' . $text3_safe . '
' : ''; + $text .= '
'; + } elseif ($type === 'style-4') { + if ($text3_safe !== '') { + $text = '
' . $text3_safe . '
'; + } + } else { + // style-1 / default. + $inner = $text1_safe !== '' ? '
' . $text1_safe . '
' : ''; + $inner .= $text3_safe !== '' ? '
' . $text3_safe . '
' : ''; + $inner .= $text2_safe !== '' ? '
' . $text2_safe . '
' : ''; + $text = $inner !== '' ? '
' . $inner . '
' : ''; + } + $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="padding-bottom:' . esc_attr((string) $height_scale) . '%!important;"' + : ''; + + $html = ''; + if ($link_url !== '') { + $tgt = $link_target !== '' ? ' target="' . esc_attr($link_target) . '" rel="noopener noreferrer"' : ''; + $html .= ''; + } + if ($type === 'style-4') { + $html .= '
'; + } + $html .= '
'; + $html .= $media; + $html .= $mask; + $html .= $text; + if ($type === 'style-4') { + $html .= '
'; // close .graphic early for style-4 body. + $html .= '
'; + $html .= $text1_safe !== '' ? '
' . $text1_safe . '
' : ''; + $html .= $text2_safe !== '' ? '
' . $text2_safe . '
' : ''; + $html .= '
'; // padding + main-shadow + } else { + $html .= ''; + } + if ($link_url !== '') { + $html .= '
'; + } + + if ($echo) { + echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + return ''; + } + return $html; + } +endif; + +if (!function_exists('aksrt_author_minicard')) : + /** + * Author mini card for user lists (zibll zib_author_card). + * + * @param int $user_id + * @param string $class + * @param bool $blur_bg + */ + function aksrt_author_minicard(int $user_id, string $class = '', bool $blur_bg = false): string { + if ($user_id <= 0) { + return ''; + } + $user = get_userdata($user_id); + if (!$user) { + return ''; + } + + $avatar_url = function_exists('aksrt_get_avatar_url') + ? aksrt_get_avatar_url($user_id, ['size' => 96]) + : get_avatar_url($user_id, ['size' => 96]); + $home = function_exists('aksrt_get_user_home_url') + ? aksrt_get_user_home_url($user_id) + : get_author_posts_url($user_id); + + $avatar_box = '
'; + + $name = function_exists('aksrt_get_user_name') + ? aksrt_get_user_name([ + 'id' => $user_id, + 'class' => 'flex ac flex1', + 'follow' => false, + 'medal' => true, + 'auth' => true, + 'level' => true, + ]) + : '' . esc_html($user->display_name) . ''; + + // Follow control (separate from name, zibll places both in dt). + $follow = ''; + $current = get_current_user_id(); + if ($current !== $user_id) { + if (is_user_logged_in()) { + $follow = ''; + } else { + $login = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(); + $follow = ' ' . esc_html__('关注', 'aksrt') . ''; + } + } + + $desc = trim((string) get_user_meta($user_id, 'description', true)); + if ($desc === '') { + $desc = __('这家伙很懒,什么都没有写…', 'aksrt'); + } + + $blur = ''; + if ($blur_bg) { + $blur = '
'; + } + + return '
' + . $blur + . '
'; + } +endif;