esc_html__('图标 + 标题 + 标签 + 描述 + CTA 的多列信息卡。', 'aksrt'), 'classname' => 'widget_aksrt_combo_info', ] ); } public function widget($args, $instance): void { $cards = $this->normalize_cards($instance['cards'] ?? []); if (!$cards) { return; } $pc_row = max(1, min(6, (int) ($instance['pc_row'] ?? 4))); $m_row = max(1, min(3, (int) ($instance['m_row'] ?? 1))); $radius = max(0, min(40, (int) ($instance['card_radius'] ?? 12))); $top_band = !empty($instance['top_band']) || !isset($instance['top_band']); $band_h = max(20, min(160, (int) ($instance['top_band_height'] ?? 70))); $cta_default = (string) ($instance['cta_text'] ?? __('立即体验', 'aksrt')); $go_link = !empty($instance['go_link']); echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base); if ($title !== '') { echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } $style = sprintf('--aksrt-zci-radius:%dpx;--aksrt-zci-band-h:%dpx;--aksrt-zci-pc:%d;--aksrt-zci-m:%d;', $radius, $band_h, $pc_row, $m_row); $wrap = 'aksrt-combo-info' . ($top_band ? ' has-band' : ''); echo '
'; $auto_idx = 0; foreach ($cards as $card) { $html = $this->render_card($card, $cta_default, $auto_idx, $go_link, $top_band); if ($html !== '') { echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } echo '
'; echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * @param array $card */ private function render_card(array $card, string $default_cta, int &$auto_idx, bool $go_link, bool $top_band): string { $title = trim((string) ($card['title'] ?? '')); $desc = trim((string) ($card['desc'] ?? '')); if ($title === '' && $desc === '') { return ''; } $band = sanitize_key((string) ($card['band_color'] ?? 'auto')); if ($band === '' || $band === 'auto' || !in_array($band, self::BANDS, true)) { $band = self::BANDS[$auto_idx % count(self::BANDS)]; $auto_idx++; } $icon_html = ''; $icon_img = (string) ($card['icon_image'] ?? ''); $icon_fa = (string) ($card['icon'] ?? ''); if ($icon_img !== '') { $icon_html = '
'; } elseif ($icon_fa !== '') { $icon_html = '
'; } $tags_html = ''; $tags = $card['tags'] ?? []; if (is_string($tags)) { $tags = array_filter(array_map('trim', explode(',', $tags))); $tags = array_map(static fn($t) => ['text' => $t, 'color' => ''], $tags); } if (is_array($tags) && $tags) { $tags_html .= '
'; foreach ($tags as $tag) { if (is_string($tag)) { $tag = ['text' => $tag, 'color' => '']; } if (!is_array($tag)) { continue; } $tt = trim((string) ($tag['text'] ?? '')); if ($tt === '') { continue; } $color = sanitize_html_class((string) ($tag['color'] ?? '')); $tags_html .= '' . esc_html($tt) . ''; } $tags_html .= '
'; } $cta_text = trim((string) ($card['cta_text'] ?? '')); if ($cta_text === '') { $cta_text = $default_cta; } $url = (string) ($card['url'] ?? ''); if ($url === '' && is_array($card['link'] ?? null)) { $url = (string) ($card['link']['url'] ?? ''); } $target = (string) ($card['target'] ?? ''); if ($target === '' && is_array($card['link'] ?? null)) { $target = (string) ($card['link']['target'] ?? ''); } $cta_html = ''; if ($cta_text !== '' && $url !== '') { if ($go_link && function_exists('aksrt_go_link')) { $url = aksrt_go_link($url, true); } $tgt = $target !== '' ? ' target="' . esc_attr($target) . '" rel="noopener noreferrer"' : ''; $cta_html = '' . esc_html($cta_text) . ''; } $band_class = $top_band ? ' aksrt-zci-band-' . esc_attr($band) : ''; $html = '
'; $html .= $icon_html; if ($title !== '') { $html .= '
' . esc_html($title) . '
'; } $html .= $tags_html; if ($desc !== '') { $html .= '
' . esc_html($desc) . '
'; } $html .= $cta_html; $html .= '
'; return $html; } /** * @param mixed $raw * @return array> */ private function normalize_cards($raw): array { if (is_string($raw)) { $decoded = json_decode($raw, true); $raw = is_array($decoded) ? $decoded : []; } if (!is_array($raw)) { return []; } $out = []; foreach ($raw as $row) { if (!is_array($row)) { continue; } $title = sanitize_text_field((string) ($row['title'] ?? '')); $desc = sanitize_text_field((string) ($row['desc'] ?? '')); if ($title === '' && $desc === '') { continue; } $out[] = [ 'title' => $title, 'desc' => $desc, 'icon' => sanitize_text_field((string) ($row['icon'] ?? '')), 'icon_image' => esc_url_raw(trim((string) ($row['icon_image'] ?? ''))), 'url' => esc_url_raw(trim((string) ($row['url'] ?? (is_array($row['link'] ?? null) ? ($row['link']['url'] ?? '') : '')))), 'target' => sanitize_text_field((string) ($row['target'] ?? '_blank')), 'cta_text' => sanitize_text_field((string) ($row['cta_text'] ?? '')), 'band_color' => sanitize_key((string) ($row['band_color'] ?? 'auto')), 'tags' => $row['tags'] ?? [], ]; if (count($out) >= 12) { break; } } return $out; } public function form($instance): void { $title = (string) ($instance['title'] ?? ''); $cards = is_string($instance['cards'] ?? null) ? (string) $instance['cards'] : wp_json_encode($this->normalize_cards($instance['cards'] ?? []), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>


sanitize_text_field((string) ($new_instance['title'] ?? '')), 'cards' => $this->normalize_cards($new_instance['cards'] ?? []), 'pc_row' => max(1, min(6, (int) ($new_instance['pc_row'] ?? 4))), 'm_row' => max(1, min(3, (int) ($new_instance['m_row'] ?? 1))), 'card_radius' => max(0, min(40, (int) ($new_instance['card_radius'] ?? 12))), 'top_band' => !empty($new_instance['top_band']) ? 1 : 0, 'top_band_height' => max(20, min(160, (int) ($new_instance['top_band_height'] ?? 70))), 'cta_text' => sanitize_text_field((string) ($new_instance['cta_text'] ?? '')), 'go_link' => !empty($new_instance['go_link']) ? 1 : 0, ]; } }