feat: rewrite schema-driven widget system

This commit is contained in:
2026-08-17 17:29:54 +08:00
parent 6c6c462df8
commit ad99ab53ce
28 changed files with 3489 additions and 0 deletions
+94
View File
@@ -0,0 +1,94 @@
<?php
namespace AKSRT\WidgetSystem;
defined('ABSPATH') || exit;
/**
* Builds post queries exclusively from normalized, saved widget settings.
*/
final class PostQuery {
private const PAY_TYPES = ['reading', 'download', 'gallery', 'video', 'vip'];
public static function build(array $instance, int $page = 1, array $segment = []): \WP_Query {
return new \WP_Query(self::arguments($instance, $page, $segment));
}
/** @return array<string,mixed> */
public static function arguments(array $instance, int $page = 1, array $segment = []): array {
$config = array_merge($instance, $segment);
$count = max(1, min(50, (int) ($config['count'] ?? 8)));
$args = [
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => $count,
'paged' => max(1, $page),
'ignore_sticky_posts' => true,
'no_found_rows' => false,
];
$categories = RendererHelpers::ids((string) ($config['category_ids'] ?? ''));
if (!empty($config['category_id'])) {
$categories = [(int) $config['category_id']];
}
if ($categories) {
$args['category__in'] = $categories;
}
$tags = RendererHelpers::ids((string) ($config['tag_ids'] ?? ''));
if ($tags) {
$args['tag__in'] = $tags;
}
$days = max(0, (int) ($config['limit_day'] ?? 0));
if ($days > 0) {
$args['date_query'] = [['after' => gmdate('Y-m-d', time() - ($days * DAY_IN_SECONDS)), 'inclusive' => true]];
}
self::apply_order($args, (string) ($config['orderby'] ?? 'date'), (string) ($config['order'] ?? 'DESC'));
self::apply_pay_type($args, (string) ($config['pay_type'] ?? ''));
return $args;
}
public static function segment(array $instance, string $segment): array {
$tabs = array_values((array) ($instance['tabs'] ?? []));
if (!$tabs) {
return [];
}
$index = ctype_digit($segment) ? (int) $segment : 0;
return isset($tabs[$index]) && is_array($tabs[$index]) ? $tabs[$index] : $tabs[0];
}
private static function apply_order(array &$args, string $orderby, string $order): void {
$args['order'] = strtoupper($order) === 'ASC' ? 'ASC' : 'DESC';
$meta = [
'views' => class_exists('AKSRT\\Core\\DomainModel') ? \AKSRT\Core\DomainModel::POST_VIEW_COUNT_KEY : 'aksrt_post_views',
'likes' => '_aksrt_like_count',
'favorites' => '_aksrt_favorite_count',
'downloads' => class_exists('AKSRT\\Core\\DomainModel') ? \AKSRT\Core\DomainModel::RESOURCE_DOWNLOAD_COUNT_KEY : '_aksrt_res_download_count',
];
if (isset($meta[$orderby])) {
$args['meta_key'] = $meta[$orderby];
$args['orderby'] = 'meta_value_num';
return;
}
if ($orderby === 'comments') {
$args['orderby'] = 'comment_count';
} elseif (in_array($orderby, ['date', 'modified', 'rand'], true)) {
$args['orderby'] = $orderby;
} else {
$args['orderby'] = 'date';
}
}
private static function apply_pay_type(array &$args, string $pay_type): void {
if (!in_array($pay_type, self::PAY_TYPES, true)) {
return;
}
$type_key = class_exists('AKSRT\\Core\\DomainModel') ? \AKSRT\Core\DomainModel::PAY_TYPE_KEY : '_aksrt_pay_type';
$meta_key = class_exists('AKSRT\\Core\\DomainModel') ? \AKSRT\Core\DomainModel::PAY_META_KEY : '_aksrt_pay';
$args['meta_query'] = [[
'relation' => 'OR',
['key' => $type_key, 'value' => $pay_type, 'compare' => '='],
['key' => $meta_key, 'value' => '"pay_type";s:' . strlen($pay_type) . ':"' . $pay_type . '"', 'compare' => 'LIKE'],
]];
}
}