[], 'posts_per_page' => 6, ]; if (!class_exists('AKSRT_Settings')) { return $config; } foreach (AKSRT_Settings::get_homepage_modules() as $module) { if (!is_array($module) || ($module['type'] ?? '') !== 'tabs') { continue; } $module_config = isset($module['config']) && is_array($module['config']) ? $module['config'] : []; $term_ids = isset($module_config['cat_ids']) && is_array($module_config['cat_ids']) ? array_values(array_filter(array_map('intval', $module_config['cat_ids']))) : []; if ($term_ids) { $config['term_ids'] = $term_ids; } if (!empty($module_config['count'])) { $config['posts_per_page'] = max(4, min(12, (int) $module_config['count'])); } break; } return $config; } } if (!function_exists('aksrt_homepage_get_tab_terms')) { /** * Homepage category tabs with full config. * * Returns enabled tabs in config order, each with 'term', 'title', 'orderby'. * Uses homepage_tab_limit from settings. * * @return array */ function aksrt_homepage_get_tab_configs(): array { $limit = class_exists('AKSRT_Settings') ? AKSRT_Settings::homepage_tab_limit() : 4; if (!class_exists('AKSRT_Settings')) { return []; } $structured_tabs = AKSRT_Settings::homepage_tabs(); if (empty($structured_tabs)) { return []; } $excluded_cat_ids = array_flip(AKSRT_Settings::home_exclude_category_ids()); $configs = []; foreach ($structured_tabs as $tab) { if (empty($tab['enabled']) || $tab['term_id'] <= 0) { continue; } if (count($configs) >= $limit) { break; } // Skip excluded categories if (isset($excluded_cat_ids[$tab['term_id']])) { continue; } $term = get_term($tab['term_id'], 'category'); if (!$term || is_wp_error($term)) { continue; } $configs[] = [ 'term' => $term, 'term_id' => (int) $tab['term_id'], 'title' => $tab['title'] !== '' ? $tab['title'] : $term->name, 'orderby' => $tab['orderby'] ?: 'date', ]; } return $configs; } /** * Homepage category tabs — returns WP_Term objects for backward compat. * * @param int $limit Unused, reads from settings. * @return WP_Term[] */ function aksrt_homepage_get_tab_terms(int $limit = 4): array { $configs = aksrt_homepage_get_tab_configs(); return array_column($configs, 'term'); } } if (!function_exists('aksrt_homepage_get_tab_posts_per_page')) { /** * Per-tab homepage post count. * * Reads from AKSRT_Settings::homepage_tab_posts_per_page() first; * falls back to the legacy module config bridge for old installs * that haven't saved the new setting yet. */ function aksrt_homepage_get_tab_posts_per_page(): int { if (class_exists('AKSRT_Settings')) { $count = AKSRT_Settings::homepage_tab_posts_per_page(); if ($count > 0) { return max(1, min(20, $count)); } } // Legacy fallback for sites that haven't migrated yet $legacy = aksrt_homepage_get_legacy_tabs_config(); $count = (int) apply_filters('aksrt_homepage_tab_posts_per_page', $legacy['posts_per_page']); return max(4, min(12, $count)); } } if (!function_exists('aksrt_homepage_get_default_view_mode')) { /** * Default homepage view mode. */ function aksrt_homepage_get_default_view_mode(): string { if (class_exists('AKSRT_Settings')) { return AKSRT_Settings::homepage_default_view(); } return 'list'; } } if (!function_exists('aksrt_homepage_sticky_tabs_enabled')) { /** * Whether homepage tabs should stick below the primary nav. */ function aksrt_homepage_sticky_tabs_enabled(): bool { if (class_exists('AKSRT_Settings')) { return AKSRT_Settings::homepage_sticky_tabs_enabled(); } return true; } } if (!function_exists('aksrt_homepage_module_hero_enabled')) { /** * Whether the fixed homepage should render the built-in hero section. */ function aksrt_homepage_module_hero_enabled(): bool { if (class_exists('AKSRT_Settings')) { return AKSRT_Settings::homepage_module_hero_enabled(); } return true; } } if (!function_exists('aksrt_homepage_module_banner_enabled')) { /** * Whether the fixed homepage should render the built-in banner section. */ function aksrt_homepage_module_banner_enabled(): bool { if (class_exists('AKSRT_Settings')) { return AKSRT_Settings::homepage_module_banner_enabled(); } return true; } } 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') ? AKSRT_Settings::homepage_allowed_sorts() : ['modified', 'date', 'views', 'likes', 'comments', 'favorites', 'downloads', 'rand']; $default_sort = class_exists('AKSRT_Settings') ? AKSRT_Settings::homepage_default_sort() : 'modified'; $override_sort = get_query_var('aksrt_homepage_sort_override'); $sort = is_string($override_sort) && $override_sort !== '' ? sanitize_key($override_sort) : (isset($_GET['home_sort']) ? sanitize_key(wp_unslash((string) $_GET['home_sort'])) : $default_sort); return in_array($sort, $allowed, true) ? $sort : $default_sort; } } if (!function_exists('aksrt_homepage_get_sort_items')) { /** * Configured sort bar items for the main stream. * * @return array */ function aksrt_homepage_get_sort_items(): array { $all_labels = class_exists('AKSRT_Settings') ? AKSRT_Settings::homepage_sort_labels() : [ 'modified' => '更新', 'date' => '发布', 'views' => '浏览', 'likes' => '点赞', 'comments' => '评论', 'favorites' => '收藏', 'downloads' => '下载', 'rand' => '随机', ]; $enabled_keys = class_exists('AKSRT_Settings') ? AKSRT_Settings::home_list_sort_options() : array_keys($all_labels); $items = []; foreach ($enabled_keys as $key) { if (isset($all_labels[$key])) { $items[$key] = $all_labels[$key]; } } return !empty($items) ? $items : ['modified' => '更新', 'date' => '发布']; } } if (!function_exists('aksrt_homepage_apply_sort_args')) { /** * Apply sort args to a query configuration. * Supports all 8 homepage sort modes. * * @param array $args * @return array */ function aksrt_homepage_apply_sort_args(array $args): array { $sort_mode = aksrt_homepage_get_sort_mode(); switch ($sort_mode) { case 'date': $args['orderby'] = 'date'; $args['order'] = 'DESC'; break; case 'downloads': $args['meta_key'] = '_aksrt_res_download_count'; $args['orderby'] = 'meta_value_num'; $args['order'] = 'DESC'; break; case 'views': $args['meta_key'] = 'aksrt_post_views'; $args['orderby'] = 'meta_value_num'; $args['order'] = 'DESC'; break; case 'likes': $args['meta_key'] = '_aksrt_like_count'; $args['orderby'] = 'meta_value_num'; $args['order'] = 'DESC'; break; case 'favorites': $args['meta_key'] = '_aksrt_favorite_count'; $args['orderby'] = 'meta_value_num'; $args['order'] = 'DESC'; break; case 'comments': $args['orderby'] = 'comment_count'; $args['order'] = 'DESC'; break; case 'rand': $args['orderby'] = 'rand'; unset($args['order']); break; case 'modified': default: $args['orderby'] = 'modified'; $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). * * @param array $args * @param string $sort_mode * @return array */ function aksrt_homepage_apply_named_sort_args(array $args, string $sort_mode): array { $allowed = class_exists('AKSRT_Settings') ? AKSRT_Settings::homepage_allowed_sorts() : ['modified', 'date', 'views', 'likes', 'comments', 'favorites', 'downloads', 'rand']; if (!in_array($sort_mode, $allowed, true)) { $sort_mode = 'date'; } // Temporarily override the global sort mode $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_sortbar')) { /** * Render the main-stream sort bar. * Only renders when home_list_sort_enabled is true. * Supports inline links or dropdown mode. */ function aksrt_homepage_render_sortbar(): void { if (class_exists('AKSRT_Settings') && !AKSRT_Settings::home_list_sort_enabled()) { return; } $current = aksrt_homepage_get_sort_mode(); $sort_ajax_enabled = class_exists('AKSRT_Settings') ? AKSRT_Settings::homepage_sort_ajax_enabled() : true; $is_dropdown = class_exists('AKSRT_Settings') ? AKSRT_Settings::home_list_sort_dropdown() : false; $base_url = remove_query_arg('home_sort', get_pagenum_link(aksrt_homepage_get_current_page())); $sort_items = aksrt_homepage_get_sort_items(); $all_labels = class_exists('AKSRT_Settings') ? AKSRT_Settings::homepage_sort_labels() : $sort_items; ?>
aksrt_homepage_get_post_types(), 'post_status' => 'publish', 'posts_per_page' => (int) get_option('posts_per_page'), 'paged' => aksrt_homepage_get_current_page(), 'ignore_sticky_posts' => false, 'orderby' => 'date', 'order' => 'DESC', ]; // Exclude specific posts (both main stream and tabs) $exclude_ids = class_exists('AKSRT_Settings') ? AKSRT_Settings::home_exclude_post_ids() : []; if (!empty($exclude_ids)) { $query_args['post__not_in'] = $exclude_ids; } // Exclude specific categories (main stream only) $exclude_cat_ids = class_exists('AKSRT_Settings') ? AKSRT_Settings::home_exclude_category_ids() : []; if (!empty($exclude_cat_ids)) { $query_args['category__not_in'] = $exclude_cat_ids; } $query = new WP_Query(aksrt_homepage_apply_sort_args($query_args)); return $query; } } if (!function_exists('aksrt_homepage_get_tab_query')) { /** * Build a category-tab query. * Uses the tab's own orderby instead of the main stream sort. * Applies post exclusion but NOT category exclusion (tabs bind to specific categories). * * @param int $term_id Category term ID. * @param string $orderby Per-tab orderby override. */ function aksrt_homepage_get_tab_query(int $term_id, string $orderby = 'date'): WP_Query { static $queries = []; $cache_key = $term_id . '_' . $orderby; if (isset($queries[$cache_key]) && $queries[$cache_key] instanceof WP_Query) { return $queries[$cache_key]; } $query_args = [ 'post_type' => aksrt_homepage_get_post_types(), 'post_status' => 'publish', 'posts_per_page' => class_exists('AKSRT_Settings') ? AKSRT_Settings::homepage_tab_posts_per_page() : 6, 'ignore_sticky_posts' => true, 'orderby' => 'date', 'order' => 'DESC', 'cat' => $term_id, 'no_found_rows' => true, ]; // Exclude specific posts (shared with main stream) $exclude_ids = class_exists('AKSRT_Settings') ? AKSRT_Settings::home_exclude_post_ids() : []; if (!empty($exclude_ids)) { $query_args['post__not_in'] = $exclude_ids; } // Apply per-tab orderby (NOT the main stream sort) $queries[$cache_key] = new WP_Query( aksrt_homepage_apply_named_sort_args($query_args, $orderby) ); return $queries[$cache_key]; } } if (!function_exists('aksrt_homepage_has_active_sidebars')) { /** * Check whether any sidebar in the given stack is active. * * @param string[] $sidebar_ids */ function aksrt_homepage_has_active_sidebars(array $sidebar_ids): bool { foreach ($sidebar_ids as $sidebar_id) { if (is_active_sidebar($sidebar_id)) { return true; } } return false; } } if (!function_exists('aksrt_homepage_render_widget_zone')) { /** * Render a stacked widget zone. * * @param string[] $sidebar_ids * @param string $wrapper_class */ function aksrt_homepage_render_widget_zone(array $sidebar_ids, string $wrapper_class = ''): void { if (!aksrt_homepage_has_active_sidebars($sidebar_ids)) { wp_reset_postdata(); return; } echo '
'; foreach ($sidebar_ids as $sidebar_id) { if (is_active_sidebar($sidebar_id)) { dynamic_sidebar($sidebar_id); } } echo '
'; } } if (!function_exists('aksrt_homepage_has_sidebar')) { /** * Whether the fixed homepage should render an aside column. */ function aksrt_homepage_has_sidebar(): bool { return aksrt_homepage_has_active_sidebars([ 'all_sidebar_top', 'home_sidebar', 'all_sidebar_bottom', 'sidebar-blog', ]); } } if (!function_exists('aksrt_homepage_render_sidebar')) { /** * Render the homepage aside column. */ function aksrt_homepage_render_sidebar(): void { if (!aksrt_homepage_has_sidebar()) { return; } echo ''; } } if (!function_exists('aksrt_homepage_render_pagination')) { /** * Render pagination for the fixed homepage latest stream. */ function aksrt_homepage_render_pagination(WP_Query $query): void { $max_pages = (int) $query->max_num_pages; if ($max_pages < 2) { return; } $query_page = (int) $query->get('paged'); $current_page = min(max(1, $query_page > 0 ? $query_page : aksrt_homepage_get_current_page()), $max_pages); $pagination_mode = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_post_pagination_mode() : 'numbered'; if ($pagination_mode === 'numbered') { $base_url = (string) get_query_var('aksrt_homepage_pagination_base_url'); $base_args = [ 'format' => '', 'current' => $current_page, 'total' => $max_pages, 'mid_size' => 2, 'prev_text' => '', 'next_text' => '', 'type' => 'array', ]; if ($base_url !== '') { $base_args['base'] = add_query_arg( 'paged', '%#%', remove_query_arg(['paged', 'page'], $base_url) ); } else { $base_args['base'] = str_replace(999999999, '%#%', esc_url(get_pagenum_link(999999999))); } $links = paginate_links($base_args); if (!$links || !is_array($links)) { return; } ?> ]+src=["\x27"]([^"\x27"]+)["\x27"]/i', $content, $html_matches) && !empty($html_matches[1])) { foreach ($html_matches[1] as $raw_url) { $images[] = esc_url_raw((string) $raw_url); } } if (preg_match_all('/"url"\s*:\s*"([^"]+)"/i', $content, $block_matches) && !empty($block_matches[1])) { foreach ($block_matches[1] as $raw_url) { $images[] = esc_url_raw((string) $raw_url); } } } $images = array_values(array_unique(array_filter($images, static function ($url) { return is_string($url) && $url !== ''; }))); set_transient($transient_key, $images, DAY_IN_SECONDS); $request_cache[$post_id] = $images; return array_slice($images, 0, $limit); } } if (!function_exists('aksrt_homepage_render_post_card')) { /** * Render a homepage post card inline. * * Thin wrapper over the unified shared renderer (aksrt_render_post). */ function aksrt_homepage_render_post_card(): void { if (!function_exists('aksrt_render_post')) { return; } $config = [ 'mode' => 'list', 'context' => 'home', ]; echo aksrt_render_post($config); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } if (!function_exists('aksrt_homepage_render_posts_grid')) { /** * Render a card-grid post block for the fixed homepage. * * Delegates to the unified shared renderer via aksrt_render_post_list. */ function aksrt_homepage_render_posts_grid(?WP_Query $query = null, bool $with_pagination = false): void { $query = $query instanceof WP_Query ? $query : aksrt_homepage_get_latest_query(); if (function_exists('aksrt_render_post_list')) { aksrt_render_post_list($query, ['mode' => 'list', 'context' => 'home'], true); } else { // Fallback: simple loop if shared renderer is unavailable if (!$query->have_posts()) { echo '

' . esc_html__('暂无文章', 'aksrt') . '

'; } else { echo '
'; while ($query->have_posts()) { $query->the_post(); aksrt_homepage_render_post_card(); } echo '
'; } wp_reset_postdata(); } if ($with_pagination) { aksrt_homepage_render_pagination($query); } } } if (!function_exists('aksrt_homepage_render_system_module')) { /** * Render a legacy homepage module inside the fixed homepage layout. */ function aksrt_homepage_render_system_module(string $type, string $wrapper_class = 'home-modules', array $config = []): void { $type = sanitize_key($type); if ($type === '') { return; } set_query_var('aksrt_module_config', $config); ob_start(); get_template_part('templates/parts/home-modules/module', $type); set_query_var('aksrt_module_config', null); $module_html = trim((string) ob_get_clean()); if ($module_html === '') { return; } echo '
'; echo $module_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo '
'; } } if (!function_exists('aksrt_homepage_get_featured_modules')) { /** * Resolve non-core homepage modules that should render alongside the fixed * hero/banner/main-stream skeleton. * * Hero, banner, and tabs are now owned by dedicated settings surfaces, so * the legacy modules list only contributes featured content modules here. * * @return array */ function aksrt_homepage_get_featured_modules(): array { if (!class_exists('AKSRT_Settings')) { return []; } $allowed_types = [ 'category', 'recent', 'ranking', 'hotspot', 'category_recommend_cards', 'tag_cloud', 'friend_links', 'html', ]; $modules = []; foreach (AKSRT_Settings::get_homepage_modules() as $module) { if (!is_array($module)) { continue; } $type = sanitize_key((string) ($module['type'] ?? '')); if (!in_array($type, $allowed_types, true)) { continue; } $modules[] = [ 'type' => $type, 'config' => isset($module['config']) && is_array($module['config']) ? $module['config'] : [], ]; } return $modules; } } if (!function_exists('aksrt_homepage_render_featured_modules')) { /** * Render featured homepage modules in configured order. * * @param array $modules * @param string $wrapper_class */ function aksrt_homepage_render_featured_modules(array $modules, string $wrapper_class = 'home-modules'): void { if (empty($modules)) { return; } echo '
'; foreach ($modules as $idx => $module) { $type = sanitize_key((string) ($module['type'] ?? '')); if ($type === '') { continue; } set_query_var('aksrt_module_config', isset($module['config']) && is_array($module['config']) ? $module['config'] : []); set_query_var('aksrt_module_index', $idx); get_template_part('templates/parts/home-modules/module', $type); } set_query_var('aksrt_module_config', null); set_query_var('aksrt_module_index', null); echo '
'; } } if (!function_exists('aksrt_homepage_render_layout')) { /** * Render the fixed homepage layout directly. * * Keeping the markup here avoids silent empty homepages when a template * part file is missing or not synced on the target server. */ function aksrt_homepage_render_layout(): void { $current_page = aksrt_homepage_get_current_page(); $show_tabs = $current_page === 1; $tab_configs = $show_tabs ? aksrt_homepage_get_tab_configs() : []; $featured_modules = $show_tabs ? aksrt_homepage_get_featured_modules() : []; $has_sidebar = aksrt_homepage_has_sidebar(); $hero_on = $show_tabs && aksrt_homepage_module_hero_enabled(); $banner_on = $show_tabs && aksrt_homepage_module_banner_enabled(); $main_list_enabled = !class_exists('AKSRT_Settings') || AKSRT_Settings::home_posts_list_enabled(); $list_title = class_exists('AKSRT_Settings') ? AKSRT_Settings::home_list_title() : __('最新发布', 'aksrt'); ?>
1) : ?>