From e4745d501e0593ce7c73c51900e35e6eeb48ebb0 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 6 Sep 2026 12:59:44 +0800 Subject: [PATCH] refactor(icons): converge every icon render on aksrt_icon_markup aksrt_get_comment_icon(), aksrt_renderer_svg_icon() and the widget renderer's private icon_markup() all delegate to the unified helper, and the duplicated 24px empty-state SVGs in user-center/user-home now come from one aksrt_empty_state_svgs(). Contract tests follow the delegation (sprite markup asserted in the helper). --- inc/helpers/aksrt-user-center.php | 7 +- inc/helpers/aksrt-user-home.php | 10 +- inc/helpers/comments/icons.php | 2 +- inc/helpers/posts-renderer/post-data.php | 2 +- .../Renderers/GeneralRenderer.php | 13 +- tests/widget-system/bootstrap.php | 210 ++++++++++++++++++ .../post-visual-contract.test.cjs | 3 +- .../zibll-modern-widgets-contract.test.cjs | 4 +- 8 files changed, 228 insertions(+), 23 deletions(-) create mode 100644 tests/widget-system/bootstrap.php diff --git a/inc/helpers/aksrt-user-center.php b/inc/helpers/aksrt-user-center.php index 914c8b97..a25480e6 100644 --- a/inc/helpers/aksrt-user-center.php +++ b/inc/helpers/aksrt-user-center.php @@ -274,10 +274,11 @@ if (!function_exists('aksrt_user_center_empty_svgs')) { * @return array{post:string,comment:string,favorite:string} */ function aksrt_user_center_empty_svgs(): array { + $all = aksrt_empty_state_svgs(); return [ - 'post' => '', - 'comment' => '', - 'favorite' => '', + 'post' => $all['post'], + 'comment' => $all['comment'], + 'favorite' => $all['favorite'], ]; } } diff --git a/inc/helpers/aksrt-user-home.php b/inc/helpers/aksrt-user-home.php index 37c55f14..709f1730 100644 --- a/inc/helpers/aksrt-user-home.php +++ b/inc/helpers/aksrt-user-home.php @@ -75,6 +75,8 @@ if (!function_exists('aksrt_get_user_home_page_context')) { $display_tabs = $is_mobile ? $enabled_tabs_mobile : $enabled_tabs_pc; $default_tab = !empty($display_tabs) ? $display_tabs[0] : $enabled_tabs[0]; + $empty_svgs = aksrt_empty_state_svgs(); + $follow_count = 0; if (class_exists('\AKSRT\User\Follow')) { $follow_count = (int) \AKSRT\User\Follow::get_instance()->get_follower_count($user_id); @@ -133,10 +135,10 @@ if (!function_exists('aksrt_get_user_home_page_context')) { 'favorites_page' => 1, 'follow_sub' => 'followers', 'follow_page' => 1, - 'svg_empty_post' => '', - 'svg_empty_comment' => '', - 'svg_empty_favorite' => '', - 'svg_empty_follow' => '', + 'svg_empty_post' => $empty_svgs['post'], + 'svg_empty_comment' => $empty_svgs['comment'], + 'svg_empty_favorite' => $empty_svgs['favorite'], + 'svg_empty_follow' => $empty_svgs['follow'], ]; } } diff --git a/inc/helpers/comments/icons.php b/inc/helpers/comments/icons.php index f95246c6..6bec4825 100644 --- a/inc/helpers/comments/icons.php +++ b/inc/helpers/comments/icons.php @@ -20,6 +20,6 @@ if (!function_exists('aksrt_get_comment_icon')) : * @return string */ function aksrt_get_comment_icon(string $name, string $class = 'icon'): string { - return ''; + return aksrt_icon_markup('zibsvg-' . $name, $class); } endif; diff --git a/inc/helpers/posts-renderer/post-data.php b/inc/helpers/posts-renderer/post-data.php index 4a34ec66..05075b3a 100644 --- a/inc/helpers/posts-renderer/post-data.php +++ b/inc/helpers/posts-renderer/post-data.php @@ -241,7 +241,7 @@ if (!function_exists('aksrt_renderer_meta_number')) { if (!function_exists('aksrt_renderer_svg_icon')) { function aksrt_renderer_svg_icon(string $name): string { - return ''; + return aksrt_icon_markup('zibsvg-' . $name); } } diff --git a/src/WidgetSystem/Renderers/GeneralRenderer.php b/src/WidgetSystem/Renderers/GeneralRenderer.php index abfd7251..2e2c3684 100644 --- a/src/WidgetSystem/Renderers/GeneralRenderer.php +++ b/src/WidgetSystem/Renderers/GeneralRenderer.php @@ -543,17 +543,6 @@ final class GeneralRenderer { } private static function icon_markup(string $icon): string { - $icon = trim($icon); - if ($icon === '') return ''; - if (str_starts_with($icon, 'customsvg-')) { - return wp_kses(substr($icon, 10), [ - 'svg' => ['class' => true, 'viewbox' => true, 'viewBox' => true, 'width' => true, 'height' => true, 'fill' => true, 'xmlns' => true, 'aria-hidden' => true], - 'use' => ['href' => true, 'xlink:href' => true], - 'path' => ['d' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true], - ]); - } - if (str_starts_with($icon, 'zibsvg-')) return ''; - if (!str_contains($icon, 'fa ') && str_contains($icon, 'fa-')) $icon = 'fa ' . $icon; - return ''; + return aksrt_icon_markup($icon); } } diff --git a/tests/widget-system/bootstrap.php b/tests/widget-system/bootstrap.php new file mode 100644 index 00000000..1b708de2 --- /dev/null +++ b/tests/widget-system/bootstrap.php @@ -0,0 +1,210 @@ + [], + 'sidebars' => [], + 'routes' => [], + 'query_args' => [], + 'current_post' => null, + 'current_id' => 0, + 'singular' => false, + 'pay_meta' => ['pay_type' => 'no', 'price' => 0], + 'paid_access' => false, + 'logged_in' => false, + ]; + $GLOBALS['wp_registered_sidebars'] = []; +} + +aksrt_test_reset_state(); + +class WP_Error { + public function __construct(private string $code = '', private string $message = '', private array $data = []) {} + public function get_error_code(): string { return $this->code; } + public function get_error_message(): string { return $this->message; } + public function get_error_data(): array { return $this->data; } +} + +class WP_REST_Controller { + public string $namespace = ''; + public string $rest_base = ''; + public function get_items($request) {} +} + +class WP_REST_Server { + public const READABLE = 'GET'; +} + +class WP_REST_Request { + public function __construct(private array $params = []) {} + public function get_params(): array { return $this->params; } + public function get_param(string $key) { return $this->params[$key] ?? null; } +} + +class WP_REST_Response { + public function __construct(private $data) {} + public function get_data() { return $this->data; } +} + +class WP_Post { + public int $ID; + public int $post_author; + public function __construct(int $id = 1, int $author = 1) { + $this->ID = $id; + $this->post_author = $author; + } +} + +class WP_Query { + public array $posts = []; + public int $max_num_pages = 1; + public int $found_posts = 0; + public function __construct(array $args = []) { + $GLOBALS['aksrt_test_state']['query_args'][] = $args; + } + public function have_posts(): bool { return false; } + public function the_post(): void {} +} + +class WP_Widget { + public string $id_base = ''; + public string $id = ''; + public int $number = 0; + public function __construct(string $id_base = '', string $name = '', array $widget_options = [], array $control_options = []) { + unset($name, $widget_options, $control_options); + $this->id_base = $id_base; + } + public function get_settings(): array { + $value = get_option('widget_' . $this->id_base, []); + return is_array($value) ? $value : []; + } + public function get_field_id(string $field): string { return 'widget-' . $this->id_base . '-' . $this->number . '-' . $field; } + public function get_field_name(string $field): string { return 'widget-' . $this->id_base . '[' . $this->number . '][' . $field . ']'; } + public function _set(int $number): void { + $this->number = $number; + $this->id = $this->id_base . '-' . $number; + } +} + +function __($text): string { return (string) $text; } +function esc_html__($text): string { return esc_html((string) $text); } +function esc_attr__($text): string { return esc_attr((string) $text); } +function esc_html_e($text): void { echo esc_html((string) $text); } +function esc_attr_e($text): void { echo esc_attr((string) $text); } +function esc_html($value): string { return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } +function esc_attr($value): string { return esc_html((string) $value); } +function esc_textarea($value): string { return esc_html((string) $value); } +function esc_url_raw($value): string { + $value = trim((string) $value); + return preg_match('#^(?:https?://|/)#', $value) ? $value : ''; +} +function esc_url($value): string { return esc_attr(esc_url_raw($value)); } +function sanitize_text_field($value): string { return trim(preg_replace('/[\r\n\t]+/', ' ', strip_tags((string) $value)) ?? ''); } +function sanitize_textarea_field($value): string { return trim(strip_tags((string) $value)); } +function sanitize_key($value): string { return preg_replace('/[^a-z0-9_\-]/', '', strtolower((string) $value)) ?? ''; } +function sanitize_html_class($value): string { return preg_replace('/[^A-Za-z0-9_-]/', '', (string) $value) ?? ''; } +function sanitize_hex_color($value): string { + return preg_match('/^#(?:[0-9a-fA-F]{3}){1,2}$/', (string) $value) ? strtolower((string) $value) : ''; +} +function sanitize_textarea($value): string { return sanitize_textarea_field($value); } +function wp_kses_post($value): string { return strip_tags((string) $value, '