251 lines
16 KiB
PHP
251 lines
16 KiB
PHP
<?php
|
|
/** Render tab post widgets with the production article renderer and fixture posts. */
|
|
declare(strict_types=1);
|
|
|
|
namespace {
|
|
error_reporting(E_ALL);
|
|
set_error_handler(static function (int $severity, string $message, string $file, int $line): bool {
|
|
if (!(error_reporting() & $severity)) return false;
|
|
throw new \ErrorException($message, 0, $severity, $file, $line);
|
|
});
|
|
define('ABSPATH', dirname(__DIR__, 2) . DIRECTORY_SEPARATOR);
|
|
define('DAY_IN_SECONDS', 86400);
|
|
class WP_User { public function __construct(public int $ID, public string $display_name = '测试作者') {} }
|
|
class WP_Post { public function __construct(public int $ID, public int $post_author = 5) {} }
|
|
class WP_Widget {
|
|
public string $id_base = '';
|
|
public string $id = '';
|
|
public int $number = 1;
|
|
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;
|
|
}
|
|
}
|
|
class WP_Query {
|
|
public array $posts = [];
|
|
public int $found_posts = 0;
|
|
public int $max_num_pages = 1;
|
|
private int $cursor = 0;
|
|
|
|
public function __construct(array $args = []) {
|
|
$rows = array_values(array_filter($GLOBALS['tab_fixture_posts'], static function (array $post) use ($args): bool {
|
|
$include = array_map('intval', (array) ($args['category__in'] ?? []));
|
|
$exclude = array_map('intval', (array) ($args['category__not_in'] ?? []));
|
|
return (!$include || in_array($post['cat'], $include, true)) && !in_array($post['cat'], $exclude, true);
|
|
}));
|
|
$orderby = (string) ($args['orderby'] ?? 'date');
|
|
$order = strtoupper((string) ($args['order'] ?? 'DESC')) === 'ASC' ? 1 : -1;
|
|
if ($orderby === 'rand') {
|
|
usort($rows, static fn(array $a, array $b): int => $a['id'] <=> $b['id']);
|
|
} else {
|
|
usort($rows, static fn(array $a, array $b): int => $order * ($a[$orderby] <=> $b[$orderby]));
|
|
}
|
|
$this->found_posts = count($rows);
|
|
$per_page = max(1, (int) ($args['posts_per_page'] ?? 6));
|
|
$this->max_num_pages = (int) ceil($this->found_posts / $per_page);
|
|
$page = max(1, (int) ($args['paged'] ?? 1));
|
|
$this->posts = array_map(static fn(array $post): WP_Post => new WP_Post((int) $post['id']), array_slice($rows, ($page - 1) * $per_page, $per_page));
|
|
}
|
|
|
|
public function have_posts(): bool { return $this->cursor < count($this->posts); }
|
|
public function the_post(): void {
|
|
$GLOBALS['tab_fixture_current_post'] = $this->posts[$this->cursor++];
|
|
$GLOBALS['post'] = $GLOBALS['tab_fixture_current_post'];
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace AKSRT\Settings {
|
|
final class Settings {
|
|
public static function get_post_list_style_settings(): array {
|
|
return $GLOBALS['tab_fixture_global_style'] ?? [];
|
|
}
|
|
public static function get_post_thumb_settings(): array { return ['thumb_catimg_s' => false]; }
|
|
public static function get_post_page_settings(): array { return ['like_enabled' => true]; }
|
|
public static function get_comment_display_settings(): array { return ['close_comments' => false]; }
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
$GLOBALS['tab_fixture_posts'] = [];
|
|
foreach (range(1, 48) as $id) {
|
|
$GLOBALS['tab_fixture_posts'][] = ['id' => $id, 'cat' => $id <= 36 ? 7 : 8, 'date' => 1000 + $id, 'modified' => 2000 + $id, 'views' => 49 - $id];
|
|
}
|
|
$GLOBALS['tab_fixture_current_post'] = null;
|
|
$GLOBALS['tab_fixture_global_style'] = [];
|
|
$GLOBALS['tab_fixture_mobile'] = false;
|
|
$GLOBALS['tab_fixture_avatar_calls'] = [];
|
|
|
|
function __($text, $domain = null): string { return (string) $text; }
|
|
function esc_html__($text, $domain = null): string { return esc_html((string) $text); }
|
|
function esc_attr__($text, $domain = null): string { return 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($value); }
|
|
function esc_url($value): string { return esc_attr($value); }
|
|
function esc_url_raw($value): string { return (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 { unset($allowed); return (string) $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 sanitize_textarea_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_trim_words($value, int $num_words = 55, string $more = '...'): string { return implode(' ', array_slice(preg_split('/\s+/', trim((string) $value)) ?: [], 0, $num_words)) . $more; }
|
|
function wp_is_mobile(): bool { return (bool) $GLOBALS['tab_fixture_mobile']; }
|
|
function aksrt_is_show_sidebar(): bool { return true; }
|
|
function is_category(): bool { return false; }
|
|
function is_search(): bool { return false; }
|
|
function is_home(): bool { return false; }
|
|
function is_front_page(): bool { return false; }
|
|
function is_author(): bool { return true; }
|
|
function is_tag(): bool { return false; }
|
|
function get_the_ID(): int { return (int) ($GLOBALS['tab_fixture_current_post']->ID ?? 0); }
|
|
function strip_shortcodes(string $value): string { return $value; }
|
|
function get_the_category(int $id = 0): array { unset($id); return []; }
|
|
function get_the_tags(int $id = 0): array { unset($id); return []; }
|
|
function get_the_excerpt(int $id = 0): string { unset($id); return '首页通用文章列表的长摘要,这里只用于卡片和列表样式的内容渲染'; }
|
|
function get_post_field(string $field, int $id = 0, string $context = 'display'): string {
|
|
unset($id, $context);
|
|
if ($field === 'post_author') return '5';
|
|
if ($field === 'post_content') return '<img src="https://example.test/gallery/1.jpg"><img src="https://example.test/gallery/2.jpg"><img src="https://example.test/gallery/3.jpg">';
|
|
return 'article body';
|
|
}
|
|
function get_userdata(int $id): WP_User { return new WP_User($id); }
|
|
function get_avatar_url(int $id, array $args = []): string { unset($args); return 'https://example.test/avatar/' . $id . '.png'; }
|
|
function aksrt_get_avatar_box($subject, string $class = 'avatar-img', bool $link = true, bool $vip = true): string {
|
|
$user_id = is_numeric($subject) ? (int) $subject : 0;
|
|
$GLOBALS['tab_fixture_avatar_calls'][] = ['user_id' => $user_id, 'class' => $class, 'link' => $link, 'vip' => $vip];
|
|
$inner = '<span class="' . esc_attr($class) . '"><img class="avatar" src="https://example.test/avatar/' . $user_id . '.png" alt=""><img class="avatar-badge" src="https://example.test/vip/' . $user_id . '.svg" alt="VIP"></span>';
|
|
return $link && $user_id > 0 ? '<a href="https://example.test/author/' . $user_id . '">' . $inner . '</a>' : $inner;
|
|
}
|
|
function get_the_time(string $format = '', $post = null): string { unset($post); return $format === 'U' ? '1000' : '2026-01-01 00:00:00'; }
|
|
function get_the_modified_time(string $format = '', $post = null): string { unset($post); return $format === 'U' ? '2000' : '2026-02-01 00:00:00'; }
|
|
function current_time(string $type): int { unset($type); return 3000; }
|
|
function human_time_diff(int $from, int $to): string { unset($to); return $from === strtotime('2026-01-01 00:00:00') ? '发布' : '修改'; }
|
|
function get_permalink(int $id = 0): string { return 'https://example.test/post/' . $id; }
|
|
function get_the_title(int $id = 0): string { return '真实文章 ' . $id; }
|
|
function get_post_thumbnail_id(int $id = 0): int { return $id; }
|
|
function get_post_meta(int $id, string $key = '', bool $single = false) { unset($id, $key, $single); return []; }
|
|
function wp_get_attachment_image_url(int $id, string $size = 'medium'): string { unset($size); return 'https://example.test/image/' . $id . '.jpg'; }
|
|
function attachment_url_to_postid(string $url): int { unset($url); return 0; }
|
|
function get_post_format(int $id = 0): string|false { unset($id); return false; }
|
|
function has_post_format($format, int $id = 0): bool { unset($format, $id); return false; }
|
|
function get_comments_number(int $id = 0): int { return $id; }
|
|
function comments_open(int $id = 0): bool { unset($id); return true; }
|
|
function get_comments_link(int $id = 0): string { return 'https://example.test/post/' . $id . '#comments'; }
|
|
function get_post_type(int $id = 0): string { unset($id); return 'post'; }
|
|
function is_sticky(int $id = 0): bool { unset($id); return false; }
|
|
function aksrt_resource_card_badge_text(int $id): string { unset($id); return ''; }
|
|
function aksrt_get_pay_meta($post = null): array { unset($post); return ['pay_type' => 'no']; }
|
|
function aksrt_get_post_views(int $id): int { return $id * 10; }
|
|
function aksrt_get_post_likes(int $id): int { return $id * 2; }
|
|
function aksrt_format_number(int $number): string { return (string) $number; }
|
|
function aksrt_get_lazy_thumb(string $size = ''): string { unset($size); return 'https://example.test/placeholder.jpg'; }
|
|
function aksrt_get_lazy_attr(string $key, string $url, string $class = '', string $lazy = ''): string { unset($key, $lazy); return ' class="' . esc_attr($class) . '" src="' . esc_url($url) . '"'; }
|
|
function aksrt_icon_markup(string $key): string { return '<svg class="' . esc_attr($key) . '"></svg>'; }
|
|
function wp_reset_postdata(): void { $GLOBALS['tab_fixture_current_post'] = null; $GLOBALS['post'] = null; }
|
|
function aksrt_widget_ajax_null(string $message = ''): string { return '<div class="aksrt-widget__empty">' . esc_html($message) . '</div>'; }
|
|
function aksrt_render_placeholder(string $style, int $count): string { return '<div data-placeholder="' . esc_attr($style) . ':' . $count . '"></div>'; }
|
|
function get_template_directory(): string { return dirname(__DIR__, 2); }
|
|
function get_template_directory_uri(): string { return 'https://example.test/theme'; }
|
|
function rest_url(string $path): string { return 'https://example.test/wp-json/' . $path; }
|
|
function wp_register_style(string $handle, string $src = '', array $deps = [], $version = false): bool { return true; }
|
|
function wp_register_script(string $handle, string $src = '', array $deps = [], $version = false, $in_footer = false): bool { return true; }
|
|
function wp_enqueue_style(string $handle): void {}
|
|
function wp_enqueue_script(string $handle): void {}
|
|
function wp_add_inline_script(string $handle, string $data, string $position = 'after'): void {}
|
|
function wp_json_encode($value): string { return json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR); }
|
|
|
|
require dirname(__DIR__, 2) . '/vendor/autoload.php';
|
|
require dirname(__DIR__, 2) . '/inc/helpers/posts-renderer/config.php';
|
|
require dirname(__DIR__, 2) . '/inc/helpers/posts-renderer/post-data.php';
|
|
require dirname(__DIR__, 2) . '/inc/helpers/posts-renderer/markup.php';
|
|
|
|
$GLOBALS['tab_fixture_global_style'] = ['list_type' => 'card', 'list_show_type' => 'no_margin', 'list_list_option' => ['style' => 'style2'], 'list_card_option' => ['style' => 'style3'], 'list_orderby' => 'date', 'post_time_source' => 'modified', 'post_list_author' => true, 'post_list_time' => true];
|
|
$tabs = [
|
|
['title' => '热门', 'cat' => '7', 'orderby' => 'date'],
|
|
['title' => '', 'cat' => '7'],
|
|
['title' => '最近', 'cat' => '8', 'orderby' => 'modified'],
|
|
];
|
|
$cases = [];
|
|
$list_instance = [];
|
|
foreach (['default', 'invalid', 'mini', 'list', 'card'] as $name) {
|
|
$GLOBALS['tab_fixture_global_style']['list_type'] = $name === 'list' ? 'text' : 'card';
|
|
$instance = ['count' => 4, 'paginate' => 'number', 'mini_opt' => [], 'tabs' => $tabs];
|
|
if ($name === 'mini' || $name === 'list' || $name === 'card') $instance['style'] = $name;
|
|
if ($name === 'invalid') $instance['style'] = 'unknown';
|
|
if ($name === 'default' || $name === 'invalid') {
|
|
$cases['raw_' . $name] = [
|
|
'tab_markup' => \AKSRT\WidgetSystem\Renderers\ContentRenderer::render('tab_posts', $instance, ['widget_id' => 'aksrt_widget_tab_posts-4']),
|
|
'first' => \AKSRT\WidgetSystem\PostRenderer::payload($instance, 'tab_posts', 1, '0')['html'],
|
|
];
|
|
}
|
|
$instance = \AKSRT\WidgetSystem\FieldSchema::normalize(\AKSRT\WidgetSystem\WidgetSchemas::for('tab_posts'), $instance);
|
|
if ($name === 'list') $list_instance = $instance;
|
|
$avatar_start = count($GLOBALS['tab_fixture_avatar_calls']);
|
|
$first_page = \AKSRT\WidgetSystem\PostRenderer::payload($instance, 'tab_posts', 1, '0');
|
|
$second_page = \AKSRT\WidgetSystem\PostRenderer::payload($instance, 'tab_posts', 2, '0');
|
|
$cases[$name] = [
|
|
'instance_style' => $instance['style'],
|
|
'tab_markup' => \AKSRT\WidgetSystem\Renderers\ContentRenderer::render('tab_posts', $instance, ['widget_id' => 'aksrt_widget_tab_posts-4']),
|
|
'first' => $first_page['html'],
|
|
'second' => $second_page['html'],
|
|
'pagination' => $first_page['paginate_html'],
|
|
'last_pagination' => \AKSRT\WidgetSystem\PostRenderer::payload($instance, 'tab_posts', 9, '0')['paginate_html'],
|
|
'avatar_calls' => array_slice($GLOBALS['tab_fixture_avatar_calls'], $avatar_start),
|
|
];
|
|
}
|
|
$mini_instance = ['style' => 'mini', 'mini_opt' => ['show_thumb', 'show_number', 'show_meta'], 'count' => 4, 'paginate' => '', 'tabs' => $tabs];
|
|
$mini_instance = \AKSRT\WidgetSystem\FieldSchema::normalize(\AKSRT\WidgetSystem\WidgetSchemas::for('tab_posts'), $mini_instance);
|
|
$avatar_start = count($GLOBALS['tab_fixture_avatar_calls']);
|
|
$mini_first = \AKSRT\WidgetSystem\PostRenderer::payload($mini_instance, 'tab_posts', 1, '0')['html'];
|
|
$mini_second = \AKSRT\WidgetSystem\PostRenderer::payload($mini_instance, 'tab_posts', 2, '0')['html'];
|
|
$cases['mini_all_options'] = [
|
|
'first' => $mini_first,
|
|
'second' => $mini_second,
|
|
'avatar_calls' => array_slice($GLOBALS['tab_fixture_avatar_calls'], $avatar_start),
|
|
];
|
|
$GLOBALS['tab_fixture_global_style']['post_list_author'] = false;
|
|
$mini_time_instance = ['style' => 'mini', 'mini_opt' => ['show_meta'], 'count' => 4, 'paginate' => '', 'tabs' => $tabs];
|
|
$mini_time_instance = \AKSRT\WidgetSystem\FieldSchema::normalize(\AKSRT\WidgetSystem\WidgetSchemas::for('tab_posts'), $mini_time_instance);
|
|
$cases['mini_time_source'] = ['html' => \AKSRT\WidgetSystem\PostRenderer::payload($mini_time_instance, 'tab_posts', 1, '0')['html']];
|
|
$GLOBALS['tab_fixture_global_style']['post_list_author'] = true;
|
|
$ajax_instance = $instance;
|
|
$ajax_instance['style'] = 'mini';
|
|
$ajax_instance['paginate'] = 'ajax';
|
|
$ajax_instance = \AKSRT\WidgetSystem\FieldSchema::normalize(\AKSRT\WidgetSystem\WidgetSchemas::for('tab_posts'), $ajax_instance);
|
|
$cases['ajax_pagination'] = [
|
|
'first' => \AKSRT\WidgetSystem\PostRenderer::payload($ajax_instance, 'tab_posts', 1, '0')['paginate_html'],
|
|
'last' => \AKSRT\WidgetSystem\PostRenderer::payload($ajax_instance, 'tab_posts', 9, '0')['paginate_html'],
|
|
];
|
|
$GLOBALS['tab_fixture_mobile'] = true;
|
|
$cases['mobile_pagination'] = [
|
|
'middle' => \AKSRT\WidgetSystem\PostRenderer::payload($list_instance, 'tab_posts', 5, '0')['paginate_html'],
|
|
'last' => \AKSRT\WidgetSystem\PostRenderer::payload($list_instance, 'tab_posts', 9, '0')['paginate_html'],
|
|
];
|
|
$GLOBALS['tab_fixture_mobile'] = false;
|
|
$cases['context_margins'] = [
|
|
'implicit' => \aksrt_renderer_config(['type' => 'list'])['no_margin'],
|
|
'explicit_false' => \aksrt_renderer_config(['type' => 'list', 'no_margin' => false])['no_margin'],
|
|
];
|
|
$definition = \AKSRT\WidgetSystem\WidgetRegistry::get('tab_posts');
|
|
$widget = new \AKSRT\WidgetSystem\SchemaWidget($definition);
|
|
$widget->id = 'aksrt_widget_tab_posts-4';
|
|
$wrapper_instance = \AKSRT\WidgetSystem\FieldSchema::normalize($definition->fields(), [
|
|
'title' => '参考标题',
|
|
'layout_pin_pc' => ['top' => 8, 'right' => 6, 'bottom' => 18, 'left' => 4],
|
|
'layout_pin_m' => ['top' => 3, 'right' => 2, 'bottom' => 10, 'left' => 2],
|
|
'layout_bg' => [
|
|
'light' => ['color' => '#ffffff', 'image' => 'https://example.test/light.jpg'],
|
|
'dark' => ['color' => '#111111', 'image' => 'https://example.test/dark.jpg'],
|
|
],
|
|
'tabs' => $tabs,
|
|
]);
|
|
ob_start();
|
|
\AKSRT\WidgetSystem\FrontendRenderer::render($definition, ['before_widget' => '<aside>', 'after_widget' => '</aside>'], $wrapper_instance, $widget);
|
|
$cases['frontend_wrapper'] = (string) ob_get_clean();
|
|
echo json_encode(['cases' => $cases], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
|
|
}
|