Files
wordpress-theme-aksrt/inc/helpers/aksrt-homepage.php
T
kate522 8aa116ec43 fix(theme): align reference layouts and restore passing contracts
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.
2026-10-29 19:16:03 +08:00

340 lines
9.9 KiB
PHP

<?php
/**
* AKSRT Fixed Homepage Helpers
*
* Rebuilds the homepage around a fixed legacy-like skeleton instead of the
* old freeform home modules canvas.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_is_fixed_homepage_request')) {
/**
* Whether the current request should use the fixed homepage layout.
*/
function aksrt_is_fixed_homepage_request(): bool {
if (is_admin()) {
return false;
}
return is_front_page() || is_home();
}
}
if (!function_exists('aksrt_homepage_get_current_page')) {
/**
* Resolve the current homepage page number for both blog and static-front
* pagination contexts.
*/
function aksrt_homepage_get_current_page(): int {
return max(1, (int) get_query_var('paged'), (int) get_query_var('page'));
}
}
if (!function_exists('aksrt_homepage_get_post_types')) {
/**
* Homepage latest feed post types.
* Resources are ordinary posts with meta — always post.
*
* @return string[]
*/
function aksrt_homepage_get_post_types(): array {
return ['post'];
}
}
if (!function_exists('aksrt_homepage_get_tab_configs')) {
/**
* Homepage category tabs with full config.
*
* Returns enabled tabs in config order, each with 'term', 'title', 'orderby'.
* Preserves every configured row in the saved order.
*
* @return array<int, array{term:WP_Term, title:string, orderby:string, term_id:int}>
*/
function aksrt_homepage_get_tab_configs(): array {
if (!class_exists('\AKSRT\Settings\Settings')) {
return [];
}
$structured_tabs = \AKSRT\Settings\Settings::homepage_tabs();
if (empty($structured_tabs)) {
return [];
}
$configs = [];
foreach ($structured_tabs as $tab) {
if ($tab['term_id'] <= 0) {
continue;
}
$term = get_term($tab['term_id']);
if (!$term || is_wp_error($term)) {
continue;
}
if ($term->taxonomy !== 'category' || (int) $term->count === 0) {
continue;
}
$configs[] = [
'term' => $term,
'term_id' => (int) $tab['term_id'],
'title' => $tab['title'] !== '' ? $tab['title'] : $term->name,
'orderby' => $tab['orderby'] ?: '',
];
}
return $configs;
}
}
if (!function_exists('aksrt_homepage_get_sort_mode')) {
/**
* Current homepage main-stream sort mode.
*/
function aksrt_homepage_get_sort_mode(): string {
$allowed = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::homepage_allowed_sorts()
: ['modified', 'date', 'views', 'like', 'comment_count', 'favorite', 'rand'];
$default_sort = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::homepage_default_sort()
: 'date';
$override_sort = get_query_var('aksrt_homepage_sort_override');
$sort = is_string($override_sort) && $override_sort !== ''
? sanitize_key($override_sort)
: $default_sort;
return in_array($sort, $allowed, true) ? $sort : $default_sort;
}
}
if (!function_exists('aksrt_homepage_get_request_sort')) {
/**
* Main-stream sort requested by URL (?orderby=), legacy zib_sift_posts_per_orde.
*
* 排序菜单(.ajax-option)点击后原位刷新的响应页靠它同序。
*/
function aksrt_homepage_get_request_sort(): string {
$get_sort = isset($_GET['orderby']) ? sanitize_key(wp_unslash((string) $_GET['orderby'])) : '';
if ($get_sort === '') {
return '';
}
$allowed = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::homepage_allowed_sorts()
: ['modified', 'date', 'views', 'like', 'comment_count', 'favorite', 'rand'];
return in_array($get_sort, $allowed, true) ? $get_sort : '';
}
}
if (!function_exists('aksrt_homepage_apply_sort_args')) {
/**
* Apply sort args to a query configuration.
*/
function aksrt_homepage_apply_sort_args(array $args): array {
$sort_mode = aksrt_homepage_get_sort_mode();
// Meta sorts: keep posts without the meta key via OR NOT EXISTS so lists never collapse empty.
$apply_meta_sort = static function (array $args, string $meta_key): array {
$args['meta_key'] = $meta_key;
$args['orderby'] = [
'meta_value_num' => 'DESC',
'date' => 'DESC',
];
$args['meta_query'] = [
'relation' => 'OR',
[
'key' => $meta_key,
'compare' => 'EXISTS',
],
[
'key' => $meta_key,
'compare' => 'NOT EXISTS',
],
];
return $args;
};
switch ($sort_mode) {
case 'modified':
$args['orderby'] = 'modified';
$args['order'] = 'DESC';
break;
case 'views':
// Canonical public views key (align hotspot consumers later).
$args = $apply_meta_sort($args, 'aksrt_post_views');
break;
case 'like':
$args = $apply_meta_sort($args, '_aksrt_like_count');
break;
case 'favorite':
$args = $apply_meta_sort($args, '_aksrt_favorite_count');
break;
case 'comment_count':
$args['orderby'] = 'comment_count';
$args['order'] = 'DESC';
break;
case 'rand':
$args['orderby'] = 'rand';
unset($args['order']);
break;
case 'date':
default:
$args['orderby'] = 'date';
$args['order'] = 'DESC';
break;
}
return $args;
}
}
if (!function_exists('aksrt_homepage_apply_named_sort_args')) {
/**
* Apply a specific named sort to query args (used by per-tab orderby).
*/
function aksrt_homepage_apply_named_sort_args(array $args, string $sort_mode): array {
$allowed = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::homepage_allowed_sorts()
: ['modified', 'date', 'views', 'like', 'comment_count', 'favorite', 'rand'];
if (!in_array($sort_mode, $allowed, true)) {
$sort_mode = 'modified';
}
$previous = get_query_var('aksrt_homepage_sort_override');
set_query_var('aksrt_homepage_sort_override', $sort_mode);
$result = aksrt_homepage_apply_sort_args($args);
set_query_var('aksrt_homepage_sort_override', $previous);
return $result;
}
}
if (!function_exists('aksrt_homepage_render_ajax_option_menu')) {
/**
* 首页排序菜单,1:1 zib_ajax_option_menu('home')。
*
* 输出 .ajax-option.ajax-replace[win-ajax-replace="filter"],点击 .ajax-next
* 排序链接由 runtime post_ajax 原位替换 #index-tab-main 内的列表。
*/
function aksrt_homepage_render_ajax_option_menu(): void {
if (!empty($_GET['nofilter'])) {
return;
}
if (!class_exists('\AKSRT\Settings\Settings') || !\AKSRT\Settings\Settings::home_list_sort_enabled()) {
return;
}
$con = aksrt_homepage_get_option_orderby_but([
'lists' => (array) \AKSRT\Settings\Settings::home_list_sort_options(),
'dropdown' => (bool) \AKSRT\Settings\Settings::home_list_sort_dropdown(),
]);
if (!$con) {
return;
}
echo '<div class="ajax-option ajax-replace" win-ajax-replace="filter">' . $con . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div></div>'; // 空白内容,解决css奇数偶数行
}
}
if (!function_exists('aksrt_homepage_get_option_orderby_but')) {
/**
* 排序方式按钮组,1:1 zib_get_option_orderby_but。
*
* @param array{lists?:string[],dropdown?:bool} $option Sort option config.
*/
function aksrt_homepage_get_option_orderby_but($option = []): string {
$defaults = [
'lists' => [],
'dropdown' => false,
];
$option = wp_parse_args((array) $option, $defaults);
if (!$option['lists'] && !$option['dropdown']) {
return '';
}
$labels = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::homepage_sort_labels()
: ['modified' => '更新', 'date' => '发布', 'views' => '浏览', 'like' => '点赞', 'comment_count' => '评论', 'favorite' => '收藏', 'rand' => '随机'];
$dropdown_but = '';
$but = '';
$uri = aksrt_homepage_url_del_paged(aksrt_homepage_get_current_url());
foreach ($option['lists'] as $key) {
if (!isset($labels[$key])) {
continue;
}
$_class = 'ajax-next';
if (isset($_GET['orderby']) && sanitize_key(wp_unslash((string) $_GET['orderby'])) === $key) {
$_class .= ' focus-color';
}
$href = add_query_arg(['orderby' => $key], $uri);
$but .= '<a rel="nofollow" ajax-replace="true" class="' . esc_attr($_class) . '" href="' . esc_url($href) . '">' . esc_html($labels[$key]) . '</a>';
}
if ($option['dropdown']) {
foreach ($labels as $key => $value) {
$_class = 'ajax-next';
if (isset($_GET['orderby']) && sanitize_key(wp_unslash((string) $_GET['orderby'])) === $key) {
$_class .= ' focus-color';
}
$href = add_query_arg(['orderby' => $key], $uri);
$dropdown_but .= '<li><a rel="nofollow" ajax-replace="true" class="' . esc_attr($_class) . '" href="' . esc_url($href) . '">' . esc_html($value) . '</a></li>';
}
}
if (!$but && !$dropdown_but) {
return '';
}
$is_dropdown = ($option['dropdown'] && $dropdown_but) ? true : false;
$d_but = $is_dropdown
? '<a href="javascript:;" data-toggle="dropdown"><span name="cat">' . esc_html__('排序', 'aksrt') . '</span><i class="fa fas fa-fw fa-sort opacity5" aria-hidden="true"></i></a>'
: esc_html__('排序', 'aksrt');
$html = '<div class="flex ac">';
$html .= '<div class="option-dropdown splitters-this-r dropdown flex0">';
$html .= $d_but;
$html .= $is_dropdown ? '<ul class="dropdown-menu">' . $dropdown_but . '</ul>' : '';
$html .= '</div>';
$html .= '<ul class="list-inline scroll-x mini-scrollbar option-items">' . $but . '</ul>';
$html .= '</div>';
return $html;
}
}
if (!function_exists('aksrt_homepage_get_current_url')) {
/**
* 当前页面链接,1:1 zib_get_current_url。
*/
function aksrt_homepage_get_current_url(): string {
$home_url = home_url();
$host = preg_replace('/^(http|https)(:\/\/)(?)([^\/]+).*$/im', '$1$2$3', $home_url);
return $host . add_query_arg(null, false);
}
}
if (!function_exists('aksrt_homepage_url_del_paged')) {
/**
* 移除分页参数的链接,1:1 zib_url_del_paged。
*/
function aksrt_homepage_url_del_paged(string $url): string {
$url = remove_query_arg(['paged', 'page'], $url);
global $wp_rewrite;
return preg_replace('/\/' . $wp_rewrite->pagination_base . '\/\d*/', '', $url);
}
}