Move category/forum/product tab lazy load into widget-set.js with skeletons; MainPosts gains load_mode=ajax first-paint placeholders.
202 lines
8.7 KiB
PHP
202 lines
8.7 KiB
PHP
<?php
|
|
/**
|
|
* @package AKSRT
|
|
*/
|
|
|
|
namespace AKSRT\Widgets;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
/**
|
|
* 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 '<section class="aksrt-home-widget aksrt-home-widget--tabs widget-tab-posts" data-aksrt-home-cat-tabs data-aksrt-tabs="1" data-rest="' . esc_url(rest_url('aksrt/v1/widgets/category-tabs')) . '" data-count="' . esc_attr((string) $count) . '" data-layout="' . esc_attr($layout) . '" data-columns="' . esc_attr((string) $columns) . '" data-context="' . esc_attr($context) . '" data-show-more="' . (!empty($show_more) ? '1' : '0') . '">';
|
|
|
|
if (empty($tabs)) {
|
|
echo function_exists('aksrt_get_widget_null') ? aksrt_get_widget_null(__('暂无可用分类', 'aksrt')) : '<p class="widget-empty">' . esc_html__('暂无可用分类', 'aksrt') . '</p>';
|
|
echo '</section>';
|
|
echo $args['after_widget'];
|
|
return;
|
|
}
|
|
|
|
?>
|
|
<header class="aksrt-home-widget__header aksrt-home-widget__header--tabs">
|
|
<h3 class="aksrt-home-widget__title"><?php echo esc_html($title); ?></h3>
|
|
<ul class="widget-tab-posts__nav aksrt-home-widget__tab-nav" role="tablist">
|
|
<?php foreach ($tabs as $index => $tab) : ?>
|
|
<li role="presentation">
|
|
<button
|
|
type="button"
|
|
role="tab"
|
|
class="widget-tab-posts__tab<?php echo 0 === $index ? ' active' : ''; ?>"
|
|
data-tab="cat-<?php echo (int) $tab['id']; ?>"
|
|
aria-selected="<?php echo 0 === $index ? 'true' : 'false'; ?>"
|
|
>
|
|
<?php echo esc_html($tab['name']); ?>
|
|
</button>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</header>
|
|
<?php
|
|
|
|
foreach ($tabs as $index => $tab) {
|
|
?>
|
|
<div class="widget-tab-posts__panel<?php echo 0 === $index ? ' active' : ''; ?>"
|
|
data-tab-panel="cat-<?php echo (int) $tab['id']; ?>"
|
|
data-loaded="<?php echo 0 === $index ? '1' : '0'; ?>"
|
|
data-cat="<?php echo (int) $tab['id']; ?>"
|
|
data-more="<?php echo esc_url($tab['link']); ?>"
|
|
role="tabpanel"<?php echo 0 === $index ? '' : ' hidden'; ?>>
|
|
<?php if (0 === $index) :
|
|
$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'],
|
|
]);
|
|
aksrt_home_widget_render_post_grid($query, $layout, $columns, $context);
|
|
wp_reset_postdata();
|
|
if ($show_more) : ?>
|
|
<div class="aksrt-home-widget__footer">
|
|
<a class="aksrt-home-widget__more" href="<?php echo esc_url($tab['link']); ?>">
|
|
<?php esc_html_e('查看更多', 'aksrt'); ?>
|
|
</a>
|
|
</div>
|
|
<?php endif;
|
|
else : ?>
|
|
<div class="post_ajax_loader" data-aksrt-ajax-loader>
|
|
<?php for ($si = 0; $si < $count; $si++) : ?>
|
|
<div class="posts-mini placeholder-row"><div class="placeholder radius thumb-placeholder"></div><div class="flex1"><div class="placeholder k1"></div><div class="placeholder s1 mt6"></div></div></div>
|
|
<?php endfor; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
echo '</section>';
|
|
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();
|
|
?>
|
|
<p>
|
|
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php esc_html_e('标题:', 'aksrt'); ?></label>
|
|
<input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>" name="<?php echo esc_attr($this->get_field_name('title')); ?>" type="text" value="<?php echo esc_attr($title); ?>">
|
|
</p>
|
|
<p>
|
|
<label for="<?php echo esc_attr($this->get_field_id('category_ids')); ?>"><?php esc_html_e('分类(可多选):', 'aksrt'); ?></label>
|
|
<select class="widefat" id="<?php echo esc_attr($this->get_field_id('category_ids')); ?>" name="<?php echo esc_attr($this->get_field_name('category_ids')); ?>[]" multiple size="6">
|
|
<?php foreach ($categories as $category) : ?>
|
|
<option value="<?php echo (int) $category->term_id; ?>" <?php selected(in_array((int) $category->term_id, $category_ids, true)); ?>>
|
|
<?php echo esc_html($category->name); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<small><?php esc_html_e('留空时自动选择热门分类。', 'aksrt'); ?></small>
|
|
</p>
|
|
<p>
|
|
<label for="<?php echo esc_attr($this->get_field_id('count')); ?>"><?php esc_html_e('每个 Tab 的文章数量:', 'aksrt'); ?></label>
|
|
<input class="tiny-text" id="<?php echo esc_attr($this->get_field_id('count')); ?>" name="<?php echo esc_attr($this->get_field_name('count')); ?>" type="number" min="1" max="12" value="<?php echo (int) $count; ?>">
|
|
</p>
|
|
<p>
|
|
<label for="<?php echo esc_attr($this->get_field_id('columns')); ?>"><?php esc_html_e('桌面列数:', 'aksrt'); ?></label>
|
|
<input class="tiny-text" id="<?php echo esc_attr($this->get_field_id('columns')); ?>" name="<?php echo esc_attr($this->get_field_name('columns')); ?>" type="number" min="1" max="4" value="<?php echo (int) $columns; ?>">
|
|
</p>
|
|
<p>
|
|
<label for="<?php echo esc_attr($this->get_field_id('layout')); ?>"><?php esc_html_e('布局:', 'aksrt'); ?></label>
|
|
<select class="widefat" id="<?php echo esc_attr($this->get_field_id('layout')); ?>" name="<?php echo esc_attr($this->get_field_name('layout')); ?>">
|
|
<?php foreach (aksrt_home_widget_allowed_layouts() as $value => $label) : ?>
|
|
<option value="<?php echo esc_attr($value); ?>" <?php selected($layout, $value); ?>>
|
|
<?php echo esc_html($label); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</p>
|
|
<p>
|
|
<input class="checkbox" type="checkbox" <?php checked($show_more); ?> id="<?php echo esc_attr($this->get_field_id('show_more')); ?>" name="<?php echo esc_attr($this->get_field_name('show_more')); ?>" value="1">
|
|
<label for="<?php echo esc_attr($this->get_field_id('show_more')); ?>"><?php esc_html_e('显示“查看更多”链接', 'aksrt'); ?></label>
|
|
</p>
|
|
<?php if (function_exists('aksrt_widget_render_location_help')) { aksrt_widget_render_location_help('hybrid'); } ?>
|
|
<?php
|
|
}
|
|
|
|
public function update($new_instance, $old_instance): array {
|
|
return [
|
|
'title' => 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<int, array{id:int,name:string,link:string}>
|
|
*/
|
|
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;
|
|
}
|
|
}
|