Align homepage and category discovery, modern widgets, admin controls, quotes, and comments with the reference theme. Remove superseded paths and add rendering and behavior coverage. Update stale asset and finance contracts; all 760 Node tests and 139 widget assertions pass.
186 lines
10 KiB
PHP
186 lines
10 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'] ?? []));
|
|
$rows = array_values(array_filter($GLOBALS['discovery_posts'], static fn(array $post): bool => !$cats || in_array($post['cat'], $cats, 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 aksrt_is_lazy(string $key, bool $default = false): bool { return false; }
|
|
function aksrt_get_lazy_attr(string $type, string $url, string $class = '', string $lazy = ''): string { return ' class="' . esc_attr($class) . '" src="' . esc_url($url) . '"'; }
|
|
function aksrt_format_number($number): string { return number_format((int) $number); }
|
|
function aksrt_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 aksrt_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 aksrt_get_post_favorites(int $id): int { return 5; }
|
|
function aksrt_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 aksrt_widget_str_cut(string $text, int $length): string { return $text; }
|
|
function aksrt_render_placeholder(string $style, int $count): string { return '<div data-placeholder="' . esc_attr($style) . ':' . $count . '"></div>'; }
|
|
function aksrt_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 aksrt_homepage_get_current_url(): string { return 'https://example.test/?paged=3'; }
|
|
function aksrt_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/aksrt-graphic-card.php';
|
|
require dirname(__DIR__, 2) . '/inc/helpers/aksrt-widgets-markup.php';
|
|
require dirname(__DIR__, 2) . '/inc/helpers/aksrt-homepage.php';
|
|
require dirname(__DIR__, 2) . '/inc/helpers/aksrt-archive-filters.php';
|
|
|
|
use AKSRT\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' => 'aksrt_widget_tab_posts-4']);
|
|
$posts = ContentRenderer::render('posts', ['style' => 'list', 'count' => 2, 'paginate' => 'number'], ['widget_id' => 'aksrt_widget_posts-3']);
|
|
|
|
$filter_group = aksrt_archive_build_term_filter_group('category', [
|
|
'lists' => [7], 'dropdown' => true, 'dropdown_lists' => [9],
|
|
], '分类');
|
|
ob_start();
|
|
aksrt_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();
|
|
aksrt_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();
|
|
aksrt_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();
|
|
aksrt_archive_render_term_header([
|
|
'header_style' => 'simple', 'show_cover' => false,
|
|
'title' => '技术分类', 'description' => '简洁描述', 'post_count' => true,
|
|
]);
|
|
$term_header_simple = (string) ob_get_clean();
|
|
|
|
$home_sort = aksrt_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;
|