Files
wordpress-theme-aksrt/tests/widget-system/discovery-reference-harness.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

191 lines
11 KiB
PHP

<?php
/** Focused render harness for homepage/category discovery widgets and filters. */
declare(strict_types=1);
define('ABSPATH', dirname(__DIR__, 2) . DIRECTORY_SEPARATOR);
define('DAY_IN_SECONDS', 86400);
class WP_Error { public function __construct(public string $code = '') {} }
class WP_Term {
public int $term_taxonomy_id;
public function __construct(public int $term_id, public string $name, public string $description = '', public string $taxonomy = 'category', public int $count = 7, public int $parent = 0) { $this->term_taxonomy_id = $term_id; }
}
class WP_Post { public function __construct(public int $ID) {} }
class WP_Query {
public array $posts = [];
public int $found_posts = 0;
public int $max_num_pages = 1;
private int $cursor = 0;
public function __construct(public array $query_args = []) {
$GLOBALS['discovery_queries'][] = $query_args;
$cats = array_map('intval', (array) ($query_args['category__in'] ?? []));
$excluded = [];
foreach (array_filter(explode(',', (string) ($query_args['cat'] ?? ''))) as $cat) {
if ((int) $cat > 0) $cats[] = (int) $cat;
if ((int) $cat < 0) $excluded[] = abs((int) $cat);
}
$rows = array_values(array_filter($GLOBALS['discovery_posts'], static fn(array $post): bool => (!$cats || in_array($post['cat'], $cats, true)) && !in_array($post['cat'], $excluded, true)));
$this->found_posts = count($rows);
$per_page = max(1, (int) ($query_args['posts_per_page'] ?? 10));
$this->max_num_pages = (int) ceil($this->found_posts / $per_page);
$page = max(1, (int) ($query_args['paged'] ?? 1));
foreach (array_slice($rows, ($page - 1) * $per_page, $per_page) as $row) $this->posts[] = new WP_Post($row['id']);
}
public function have_posts(): bool { return $this->cursor < count($this->posts); }
public function the_post(): void { $post = $this->posts[$this->cursor++]; $GLOBALS['discovery_current_post'] = $post; }
}
class wpdb {
public string $postmeta = 'wp_postmeta'; public string $posts = 'wp_posts'; public string $term_relationships = 'wp_term_relationships';
public function prepare(string $query, ...$args): string { return $query; }
public function get_var(string $query): string { return '789'; }
}
$GLOBALS['wpdb'] = new wpdb();
$GLOBALS['discovery_queries'] = [];
$GLOBALS['discovery_current_post'] = null;
$GLOBALS['discovery_terms'] = [
7 => new WP_Term(7, '技术分类', '<p>分类说明</p>'),
8 => new WP_Term(8, '空分类', ''),
9 => new WP_Term(9, '下拉分类', ''),
];
$GLOBALS['discovery_queried_term'] = null;
$GLOBALS['discovery_paged'] = 1;
$GLOBALS['discovery_posts'] = [];
for ($id = 101; $id <= 107; $id++) $GLOBALS['discovery_posts'][] = ['id' => $id, 'cat' => 7];
function __($text, $domain = null): string { return (string) $text; }
function esc_html__($text, $domain = null): string { return esc_html($text); }
function esc_attr__($text, $domain = null): string { return esc_attr($text); }
function esc_html($value): string { return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
function esc_attr($value): string { return esc_html($value); }
function esc_html_e($text, $domain = null): void { echo esc_html($text); }
function esc_attr_e($text, $domain = null): void { echo esc_attr($text); }
function esc_url_raw($value): string { return (string) $value; }
function esc_url($value): string { return esc_attr($value); }
function wp_parse_args($args, array $defaults = []): array { return array_merge($defaults, is_array($args) ? $args : []); }
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_text_field($value): string { return trim(strip_tags((string) $value)); }
function absint($value): int { return abs((int) $value); }
function wp_strip_all_tags($value): string { return trim(strip_tags((string) $value)); }
function wp_kses_post($value): string { return strip_tags((string) $value, '<a><b><strong><em><br><p><span>'); }
function wp_kses($value, array $allowed): string {
$tags = '<' . implode('><', array_keys($allowed)) . '>';
return strip_tags((string) $value, $tags);
}
function is_wp_error($value): bool { return $value instanceof WP_Error; }
function wp_is_mobile(): bool { return false; }
function wp_reset_postdata(): void { $GLOBALS['discovery_current_post'] = null; }
function jio_is_lazy(string $key, bool $default = false): bool { return false; }
function jio_get_lazy_attr(string $type, string $url, string $class = '', string $lazy = ''): string { return ' class="' . esc_attr($class) . '" src="' . esc_url($url) . '"'; }
function jio_format_number($number): string { return number_format((int) $number); }
function jio_renderer_svg_icon(string $name): string { return '<svg class="zibsvg-' . esc_attr($name) . '" viewbox="0 0 16 16" aria-hidden="true"><use href="#zibsvg-' . esc_attr($name) . '"></use></svg>'; }
function jio_renderer_collect_post_data(array $config = []): array {
$post = $GLOBALS['discovery_current_post'];
return ['post_id' => $post->ID, 'title' => '文章 ' . $post->ID, 'subtitle' => '', 'permalink' => 'https://example.test/post/' . $post->ID, 'time_ago' => '2天前', 'views' => 42, 'comments' => 3];
}
function jio_get_post_favorites(int $id): int { return 5; }
function jio_get_post_likes(int $id): int { return 6; }
function get_term(int $id, string $taxonomy = 'category') { return $GLOBALS['discovery_terms'][$id] ?? new WP_Error('missing'); }
function get_term_meta(int $id, string $key, bool $single = true): int { return $id === 7 ? 77 : 0; }
function wp_get_attachment_url(int $id): string { return $id === 77 ? 'https://example.test/category-cover.jpg' : ''; }
function get_posts(array $args): array { return []; }
function get_the_post_thumbnail_url($id = null, string $size = 'post-thumbnail'): string { return ''; }
function get_term_link(WP_Term $term) { return 'https://example.test/category/' . $term->term_id; }
function current_user_can(string $capability): bool { return false; }
function get_edit_term_link(int $id, string $taxonomy): string { return ''; }
function jio_widget_str_cut(string $text, int $length): string { return $text; }
function jio_render_placeholder(string $style, int $count): string { return '<div data-placeholder="' . esc_attr($style) . ':' . $count . '"></div>'; }
function jio_render_post_list(array $args, WP_Query $query, bool $echo = true): string { return '<div class="rendered-post-count" data-count="' . count($query->posts) . '"></div>'; }
function get_terms(array $args) {
$ids = array_map('intval', (array) ($args['include'] ?? []));
if (($args['fields'] ?? '') === 'ids') return [];
$terms = $ids ? array_intersect_key($GLOBALS['discovery_terms'], array_flip($ids)) : $GLOBALS['discovery_terms'];
return array_values($terms);
}
function get_queried_object() { return $GLOBALS['discovery_queried_term']; }
function get_query_var(string $name, $default = '') { return $name === 'paged' ? $GLOBALS['discovery_paged'] : $default; }
function get_ancestors(int $id, string $taxonomy, string $resource_type): array { return []; }
function wp_parse_args_filter($args, array $defaults): array { return array_merge($defaults, $args); }
function jio_homepage_get_current_url(): string { return 'https://example.test/?paged=3'; }
function jio_homepage_url_del_paged(string $url): string { return preg_replace('/[?&]paged=\d+/', '', $url) ?: $url; }
function add_query_arg($args, $url = false): string {
if (is_array($args)) return (string) $url . (str_contains((string) $url, '?') ? '&' : '?') . http_build_query($args);
return 'https://example.test/';
}
function remove_query_arg(array $keys, string $url): string { return $url; }
function home_url(string $path = '/'): string { return 'https://example.test' . $path; }
function get_template_directory_uri(): string { return 'https://example.test/theme'; }
function wp_unslash($value): string { return (string) $value; }
require dirname(__DIR__, 2) . '/vendor/autoload.php';
require dirname(__DIR__, 2) . '/inc/helpers/jio-graphic-card.php';
require dirname(__DIR__, 2) . '/inc/helpers/jio-widgets-markup.php';
require dirname(__DIR__, 2) . '/inc/helpers/jio-homepage.php';
require dirname(__DIR__, 2) . '/inc/helpers/jio-archive-filters.php';
use Jio\WidgetSystem\Renderers\ContentRenderer;
$aggregation = ContentRenderer::render('term_aggregation', [
'term_id' => [7, 8], 'pc_row' => 2, 'orderby' => 'modified', 'order' => 'desc', 'count' => 2,
]);
$tabs = ContentRenderer::render('tab_posts', [
'style' => 'list', 'count' => 2, 'paginate' => 'number',
'tabs' => [['title' => '技术', 'cat' => '7'], ['title' => '空栏目', 'cat' => '8']],
], ['widget_id' => 'jio_widget_tab_posts-4']);
$posts = ContentRenderer::render('posts', ['style' => 'list', 'count' => 2, 'paginate' => 'number'], ['widget_id' => 'jio_widget_posts-3']);
$filter_group = jio_archive_build_term_filter_group('category', [
'lists' => [7], 'dropdown' => true, 'dropdown_lists' => [9],
], '分类');
ob_start();
jio_archive_render_filter_bar(['groups' => [$filter_group], 'aria_label' => '分类筛选']);
$archive_filter_html = (string) ob_get_clean();
$GLOBALS['discovery_queried_term'] = $GLOBALS['discovery_terms'][7];
$GLOBALS['wp_query'] = new WP_Query();
$GLOBALS['wp_query']->found_posts = 31;
$GLOBALS['discovery_paged'] = 1;
ob_start();
jio_archive_render_term_header([
'header_style' => 'cover', 'show_cover' => true, 'cover_url' => '',
'title' => '技术分类', 'description' => '首屏描述', 'post_count' => true,
]);
$term_header_first = (string) ob_get_clean();
$GLOBALS['discovery_paged'] = 2;
ob_start();
jio_archive_render_term_header([
'header_style' => 'cover', 'show_cover' => true, 'cover_url' => '',
'title' => '技术分类', 'description' => '第二页描述', 'post_count' => true,
]);
$term_header_second = (string) ob_get_clean();
$GLOBALS['discovery_paged'] = 1;
ob_start();
jio_archive_render_term_header([
'header_style' => 'simple', 'show_cover' => false,
'title' => '技术分类', 'description' => '简洁描述', 'post_count' => true,
]);
$term_header_simple = (string) ob_get_clean();
$home_sort = jio_homepage_get_option_orderby_but(['lists' => ['date', 'views'], 'dropdown' => true]);
$result = json_encode([
'aggregation' => $aggregation,
'aggregation_queries' => $GLOBALS['discovery_queries'],
'tabs' => $tabs,
'posts' => $posts,
'filter_group' => $filter_group,
'archive_filter_html' => $archive_filter_html,
'term_header_first' => $term_header_first,
'term_header_second' => $term_header_second,
'term_header_simple' => $term_header_simple,
'home_sort' => $home_sort,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if ($result === false) {
fwrite(STDERR, json_last_error_msg());
exit(1);
}
echo $result;