esc_html__('展示开启付费/积分可见的文章(支持 AJAX)。', 'aksrt'), 'classname' => 'widget_aksrt_paid_posts', ] ); } public static function build_query_args(array $instance, int $paged = 1): array { $count = max(1, min(20, (int) ($instance['count'] ?? 6))); $orderby = sanitize_key((string) ($instance['orderby'] ?? 'date')); $query = [ 'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => $count, 'paged' => max(1, $paged), 'order' => 'DESC', 'meta_query' => [ 'relation' => 'OR', [ 'key' => '_aksrt_pay_price', 'value' => 0, 'compare' => '>', 'type' => 'NUMERIC', ], [ 'key' => '_aksrt_credits_cost', 'value' => 0, 'compare' => '>', 'type' => 'NUMERIC', ], [ 'key' => '_aksrt_visibility', 'value' => ['pay', 'credits'], 'compare' => 'IN', ], ], ]; if ($orderby === 'views') { $query['meta_key'] = 'aksrt_post_views'; $query['orderby'] = 'meta_value_num'; } elseif ($orderby === 'price') { $query['meta_key'] = '_aksrt_pay_price'; $query['orderby'] = 'meta_value_num'; } else { $query['orderby'] = 'date'; } $cat = max(0, (int) ($instance['cat'] ?? 0)); if ($cat > 0) { $query['cat'] = $cat; } $limit_day = max(0, (int) ($instance['limit_day'] ?? 0)); if ($limit_day > 0) { $query['date_query'] = [['after' => $limit_day . ' days ago']]; } return $query; } public static function render_items_html(\WP_Query $q, string $style = 'mini'): string { if (!$q->have_posts()) { return ''; } $placeholder = get_template_directory_uri() . '/assets/img/placeholder.svg'; ob_start(); while ($q->have_posts()) { $q->the_post(); $pid = get_the_ID(); $price = (float) get_post_meta($pid, '_aksrt_pay_price', true); $credits = (int) get_post_meta($pid, '_aksrt_credits_cost', true); $thumb = get_the_post_thumbnail_url($pid, 'thumbnail'); if ($price > 0) { $badge = '¥' . number_format($price, 2, '.', ''); } elseif ($credits > 0) { $badge = sprintf(__('%d 积分', 'aksrt'), $credits); } else { $badge = __('付费', 'aksrt'); } $mode = in_array($style, ['list', 'card', 'mini'], true) ? $style : 'mini'; if (function_exists('aksrt_render_post')) { $item = aksrt_render_post([ 'mode' => $mode, 'context' => 'widget', 'show_thumb' => true, 'show_meta' => true, 'show_excerpt' => $mode === 'list', 'extra_class' => 'ajax-item aksrt-paid-posts__' . $mode, ]); if ($item !== '') { echo '
'; echo $item; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo '' . esc_html($badge) . ''; echo '
'; continue; } } echo '
  • '; if ($thumb) { echo ''; } echo '
    '; echo '' . esc_html(get_the_title()) . ''; echo '
    ' . esc_html($badge) . '
    '; echo '
  • '; } wp_reset_postdata(); return (string) ob_get_clean(); } public static function query_payload(array $instance, int $page = 1): array { $page = max(1, $page); $paginate = sanitize_key((string) ($instance['paginate'] ?? 'ajax')); $count = max(1, min(20, (int) ($instance['count'] ?? 6))); $q = new \WP_Query(self::build_query_args($instance, $page)); $style = sanitize_key((string) ($instance['style'] ?? 'mini')); if (!in_array($style, ['mini', 'list', 'card'], true)) { $style = 'mini'; } $items = self::render_items_html($q, $style); $wrap_tag = (strpos($items, 'posts-mini') !== false || strpos($items, 'aksrt-paid-posts__mini') !== false) ? 'div' : 'ul'; $html = $items !== '' ? '<' . $wrap_tag . ' class="aksrt-paid-posts style-' . esc_attr($style) . '">' . $items . '' : ''; if ($html === '' && $page === 1) { $html = function_exists('aksrt_get_ajax_null') ? aksrt_get_ajax_null(__('暂无付费内容', 'aksrt')) : '

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

    '; } $max_pages = max(1, (int) $q->max_num_pages); $total = (int) $q->found_posts; $has_more = $page < $max_pages; $base_qs = array_filter([ 'count' => $count, 'orderby' => sanitize_key((string) ($instance['orderby'] ?? 'date')), 'cat' => max(0, (int) ($instance['cat'] ?? 0)), 'limit_day' => max(0, (int) ($instance['limit_day'] ?? 0)), 'style' => $style, 'paginate' => $paginate, ], static function ($v) { return $v !== '' && $v !== null; }); $rest_base = add_query_arg($base_qs, rest_url('aksrt/v1/widgets/paid-posts')); $paginate_html = ''; if ($paginate === 'ajax' && $has_more) { $next = add_query_arg(['page' => $page + 1], $rest_base); $paginate_html = function_exists('aksrt_get_ajax_next_paginate') ? aksrt_get_ajax_next_paginate($total, $page, $count, $next) : '
    ' . esc_html__('加载更多', 'aksrt') . '
    '; } elseif ($paginate === 'number' && $max_pages > 1) { $paginate_html = function_exists('aksrt_get_ajax_number_paginate') ? aksrt_get_ajax_number_paginate($total, $page, $count, $rest_base) : '
    '; } else { $paginate_html = '
    '; } return [ 'html' => $html, 'paginate_html' => $paginate_html, 'has_more' => $has_more, 'page' => $page, 'max_pages' => $max_pages, 'total' => $total, ]; } public function widget($args, $instance): void { $paginate = sanitize_key((string) ($instance['paginate'] ?? 'ajax')); $instance['paginate'] = $paginate; $payload = self::query_payload($instance, 1); echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base); if ($title !== '') { echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } $affix = function_exists('aksrt_widget_affix_attrs') ? aksrt_widget_affix_attrs($instance) : ['class' => '', 'attr' => '']; $rest = rest_url('aksrt/v1/widgets/paid-posts'); $wrap = 'aksrt-paid-posts-wrap ajaxpager' . $affix['class']; echo '
    '; echo $payload['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo $payload['paginate_html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo ''; echo '
    '; echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } public function form($instance): void { ?>

    render_common_form_section($instance); ?> update_common_fields($new_instance, $old_instance, [ 'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')), 'count' => max(1, min(20, (int) ($new_instance['count'] ?? 6))), 'orderby' => $orderby, 'style' => in_array(sanitize_key((string) ($new_instance['style'] ?? 'mini')), ['mini', 'list', 'card'], true) ? sanitize_key((string) ($new_instance['style'] ?? 'mini')) : 'mini', 'cat' => max(0, (int) ($new_instance['cat'] ?? 0)), 'limit_day' => max(0, (int) ($new_instance['limit_day'] ?? 0)), 'paginate' => in_array(sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')), ['none', 'ajax', 'number'], true) ? sanitize_key((string) ($new_instance['paginate'] ?? 'ajax')) : 'ajax', ]); } }