*/ function aksrt_home_widget_allowed_layouts(): array { return [ 'card' => __('卡片', 'aksrt'), 'list' => __('列表', 'aksrt'), 'grid-cms' => __('资源网格', 'aksrt'), ]; } } if (!function_exists('aksrt_home_widget_post_types')) { /** * Post types used by homepage widgets. * * @return array */ function aksrt_home_widget_post_types(): array { return ['post']; } } if (!function_exists('aksrt_home_widget_available_categories')) { /** * Return categories for widget admin forms. * * @return array */ function aksrt_home_widget_available_categories(): array { $categories = get_categories([ 'taxonomy' => 'category', 'hide_empty' => false, 'orderby' => 'name', 'order' => 'ASC', ]); return is_array($categories) ? $categories : []; } } if (!function_exists('aksrt_home_widget_fallback_category_ids')) { /** * Pick top categories as fallback when widget instance has no selection. * * @param int $limit Maximum category ids to return. * @return array */ function aksrt_home_widget_fallback_category_ids(int $limit = 1): array { $limit = max(1, min(8, $limit)); $terms = get_terms([ 'taxonomy' => 'category', 'orderby' => 'count', 'order' => 'DESC', 'number' => $limit, 'hide_empty' => true, 'fields' => 'ids', ]); if (is_wp_error($terms) || !is_array($terms)) { return []; } return array_values(array_filter(array_map('absint', $terms))); } } if (!function_exists('aksrt_home_widget_normalize_category_ids')) { /** * Normalize selected category ids. * * @param mixed $raw_ids Raw ids from widget instance. * @param int $limit Maximum ids to keep. * @return array */ function aksrt_home_widget_normalize_category_ids($raw_ids, int $limit = 4): array { $ids = array_map('absint', (array) $raw_ids); $ids = array_values(array_filter($ids, static fn($id) => $id > 0)); if ($limit > 0) { $ids = array_slice($ids, 0, $limit); } return $ids; } } if (!function_exists('aksrt_home_widget_resolve_layout')) { /** * Sanitize requested widget post layout. * * @param mixed $layout Layout value. * @param string $default Default layout. * @return string */ function aksrt_home_widget_resolve_layout($layout, string $default = 'card'): string { $allowed = array_keys(aksrt_home_widget_allowed_layouts()); $layout = is_string($layout) ? $layout : $default; return in_array($layout, $allowed, true) ? $layout : $default; } } if (!function_exists('aksrt_home_widget_resolve_context')) { /** * Resolve widget area context from sidebar args. */ function aksrt_home_widget_resolve_context(array $args): string { if (function_exists('aksrt_widget_get_area_context')) { return aksrt_widget_get_area_context($args); } return 'homepage'; } } if (!function_exists('aksrt_home_widget_effective_layout')) { /** * Compact rich homepage widgets when placed into a sidebar area. */ function aksrt_home_widget_effective_layout(string $layout, string $context): string { if ($context === 'sidebar' && $layout !== 'list') { return 'list'; } return $layout; } } if (!function_exists('aksrt_home_widget_effective_columns')) { /** * Sidebar widgets should stay single-column. */ function aksrt_home_widget_effective_columns(int $columns, string $context): int { if ($context === 'sidebar') { return 1; } return max(1, min(4, $columns)); } } if (!function_exists('aksrt_home_widget_render_header')) { /** * Render a compact Zibll-like section header. * * @param string $title Section title. * @param string $more_link Optional more link. * @param string $more_text Optional more text. * @return void */ function aksrt_home_widget_render_header(string $title, string $more_link = '', string $more_text = ''): void { ?>

have_posts()) { echo function_exists('aksrt_get_widget_null') ? aksrt_get_widget_null(__('暂无内容', 'aksrt')) : '

' . esc_html__('暂无内容', 'aksrt') . '

'; wp_reset_postdata(); return; } if ($context === 'sidebar') { $use_homepage_mini = function_exists('aksrt_is_fixed_homepage_request') && aksrt_is_fixed_homepage_request() && function_exists('aksrt_render_mini_list') && (!class_exists('\AKSRT\Settings\Settings') || \AKSRT\Settings\Settings::homepage_sidebar_mini_enabled()); if ($use_homepage_mini && function_exists('aksrt_render_mini_list')) { echo '
'; aksrt_render_mini_list($query, ['context' => 'sidebar', 'show_thumb' => true]); echo '
'; return; } // Fallback: simple sidebar list echo '
    '; while ($query->have_posts()) { $query->the_post(); ?>
  • 'lazy', 'class' => 'fit-cover']); ?>
  • '; wp_reset_postdata(); return; } // Homepage / content area: delegate to shared renderer $layout = aksrt_home_widget_resolve_layout($layout, 'card'); $columns = max(1, min(4, $columns)); if (function_exists('aksrt_render_post_list')) { aksrt_render_post_list($query, [ 'mode' => $layout === 'grid-cms' ? 'grid-cms' : $layout, 'context' => 'widget', 'columns' => $columns, ], true); } else { // Fallback: use template part $previous_layout = get_query_var('aksrt_post_card_layout', ''); $previous_scene = get_query_var('aksrt_post_card_scene', ''); set_query_var('aksrt_post_card_layout', $layout); set_query_var('aksrt_post_card_scene', 'home'); $classes = [ 'aksrt-home-widget__post-grid', 'aksrt-home-widget__post-grid--' . $layout, 'post-grid', 'post-grid--' . $layout, ]; printf( '
    ', esc_attr(implode(' ', $classes)), (int) $columns ); while ($query->have_posts()) { $query->the_post(); get_template_part('templates/parts/content', 'post-card'); } echo '
    '; set_query_var('aksrt_post_card_layout', $previous_layout); set_query_var('aksrt_post_card_scene', $previous_scene); } wp_reset_postdata(); } } if (!function_exists('aksrt_home_widget_get_lazyload_args')) { /** * Lazyload settings reused by category recommend widget. * * @return array{enabled: bool, placeholder_url: string} */ function aksrt_home_widget_get_lazyload_args(): array { $config = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_lazyload_config() : ['enabled' => false, 'placeholder_url' => '']; return [ 'enabled' => ! empty($config['enabled']), 'placeholder_url' => ! empty($config['placeholder_url']) ? (string) $config['placeholder_url'] : get_template_directory_uri() . '/assets/img/placeholder.svg', ]; } } /** * Homepage category block widget. */ class CategoryBlockWidget extends \WP_Widget { public function __construct() { parent::__construct( 'aksrt_category_block', esc_html__('AKSRT 分类块', 'aksrt'), [ 'classname' => 'widget_aksrt_category_block', 'description' => esc_html__('指定分类的最新内容区块,可挂载到首页内容挂载区。', 'aksrt'), 'customize_selective_refresh' => true, ] ); } public function widget($args, $instance): void { $context = aksrt_home_widget_resolve_context($args); $category_id = $this->resolve_category_id($instance); $term = $category_id > 0 ? get_term($category_id, 'category') : null; $title = apply_filters('widget_title', $instance['title'] ?? '', $instance, $this->id_base); $title = $title !== '' ? $title : (($term && ! is_wp_error($term)) ? $term->name : __('精选分类', 'aksrt')); $count = max(1, min(12, (int) ($instance['count'] ?? 6))); $columns = aksrt_home_widget_effective_columns((int) ($instance['columns'] ?? 3), $context); $layout = aksrt_home_widget_effective_layout( aksrt_home_widget_resolve_layout($instance['layout'] ?? 'card', 'card'), $context ); $show_more = ! empty($instance['show_more']); $query_args = [ 'post_type' => aksrt_home_widget_post_types(), 'post_status' => 'publish', 'posts_per_page' => $count, 'ignore_sticky_posts' => true, 'no_found_rows' => true, ]; if ($category_id > 0) { $query_args['cat'] = $category_id; } $query = new \WP_Query($query_args); echo $args['before_widget']; echo '
    '; aksrt_home_widget_render_header( (string) $title, ($show_more && $term && ! is_wp_error($term)) ? (string) get_category_link($category_id) : '', __('查看分类', 'aksrt') ); aksrt_home_widget_render_post_grid($query, $layout, $columns, $context); echo '
    '; echo $args['after_widget']; } public function form($instance): void { $title = (string) ($instance['title'] ?? ''); $category_id = (int) ($instance['category_id'] ?? 0); $count = (int) ($instance['count'] ?? 6); $columns = (int) ($instance['columns'] ?? 3); $layout = aksrt_home_widget_resolve_layout($instance['layout'] ?? 'card', 'card'); $show_more = ! empty($instance['show_more']); $categories = aksrt_home_widget_available_categories(); ?>

    id="get_field_id('show_more')); ?>" name="get_field_name('show_more')); ?>" value="1">

    sanitize_text_field($new_instance['title'] ?? ''), 'category_id' => absint($new_instance['category_id'] ?? 0), 'count' => max(1, min(12, absint($new_instance['count'] ?? 6))), 'columns' => max(1, min(4, absint($new_instance['columns'] ?? 3))), 'layout' => aksrt_home_widget_resolve_layout($new_instance['layout'] ?? 'card', 'card'), 'show_more' => ! empty($new_instance['show_more']) ? 1 : 0, ]; } private function resolve_category_id(array $instance): int { $category_id = absint($instance['category_id'] ?? 0); if ($category_id > 0) { return $category_id; } $fallback = aksrt_home_widget_fallback_category_ids(1); return $fallback[0] ?? 0; } } /** * Homepage category tabs widget. */ class CategoryTabsWidget extends \WP_Widget { public function __construct() { parent::__construct( 'aksrt_category_tabs', esc_html__('AKSRT 分类 Tabs', 'aksrt'), [ 'classname' => 'widget_aksrt_category_tabs', 'description' => esc_html__('多分类切换内容流,可挂载到首页内容挂载区。', 'aksrt'), 'customize_selective_refresh' => true, ] ); } public function widget($args, $instance): void { $context = aksrt_home_widget_resolve_context($args); $title = apply_filters('widget_title', $instance['title'] ?? '', $instance, $this->id_base); $title = $title !== '' ? $title : __('热门分类', 'aksrt'); $count = max(1, min(12, (int) ($instance['count'] ?? 6))); $columns = aksrt_home_widget_effective_columns((int) ($instance['columns'] ?? 3), $context); $layout = aksrt_home_widget_effective_layout( aksrt_home_widget_resolve_layout($instance['layout'] ?? 'card', 'card'), $context ); $show_more = ! empty($instance['show_more']); $tabs = $this->resolve_tabs($instance); echo $args['before_widget']; echo '
    '; if (empty($tabs)) { echo function_exists('aksrt_get_widget_null') ? aksrt_get_widget_null(__('暂无可用分类', 'aksrt')) : '

    ' . esc_html__('暂无可用分类', 'aksrt') . '

    '; echo '
    '; echo $args['after_widget']; return; } ?>

      $tab) : ?>
    $tab) { $query = new \WP_Query([ 'post_type' => aksrt_home_widget_post_types(), 'post_status' => 'publish', 'posts_per_page' => $count, 'ignore_sticky_posts' => true, 'no_found_rows' => true, 'cat' => (int) $tab['id'], ]); ?>
    >
    '; echo $args['after_widget']; } public function form($instance): void { $title = (string) ($instance['title'] ?? ''); $category_ids = aksrt_home_widget_normalize_category_ids($instance['category_ids'] ?? [], 6); $count = (int) ($instance['count'] ?? 6); $columns = (int) ($instance['columns'] ?? 3); $layout = aksrt_home_widget_resolve_layout($instance['layout'] ?? 'card', 'card'); $show_more = ! empty($instance['show_more']); $categories = aksrt_home_widget_available_categories(); ?>

    id="get_field_id('show_more')); ?>" name="get_field_name('show_more')); ?>" value="1">

    sanitize_text_field($new_instance['title'] ?? ''), 'category_ids' => aksrt_home_widget_normalize_category_ids($new_instance['category_ids'] ?? [], 6), 'count' => max(1, min(12, absint($new_instance['count'] ?? 6))), 'columns' => max(1, min(4, absint($new_instance['columns'] ?? 3))), 'layout' => aksrt_home_widget_resolve_layout($new_instance['layout'] ?? 'card', 'card'), 'show_more' => ! empty($new_instance['show_more']) ? 1 : 0, ]; } /** * Resolve configured category tabs. * * @param array $instance Widget instance. * @return array */ private function resolve_tabs(array $instance): array { $category_ids = aksrt_home_widget_normalize_category_ids($instance['category_ids'] ?? [], 6); if (empty($category_ids)) { $category_ids = aksrt_home_widget_fallback_category_ids(4); } $tabs = []; foreach ($category_ids as $category_id) { $term = get_term($category_id, 'category'); if (! $term || is_wp_error($term)) { continue; } $tabs[] = [ 'id' => (int) $category_id, 'name' => $term->name, 'link' => get_category_link($category_id), ]; } return $tabs; } }