*/ public static function sanitize_video_episodes($raw): array { if (!is_array($raw)) { return []; } $out = []; foreach ($raw as $row) { if (!is_array($row)) { continue; } $url = esc_url_raw((string) ($row['url'] ?? '')); if ($url === '') { continue; } $out[] = [ 'url' => $url, 'title' => sanitize_text_field((string) ($row['title'] ?? '')), ]; if (count($out) >= 50) { break; } } return $out; } /** * Get a single post meta value. */ public static function get_meta_value(int $post_id, string $key, $default = '') { $meta = self::get_meta($post_id); return $meta[$key] ?? $default; } /** * Register the meta box. */ public function register_meta_box(): void { add_meta_box( 'aksrt_post_meta', __('AKSRT 文章设置', 'aksrt'), [$this, 'render_meta_box'], 'post', 'side', 'default' ); add_meta_box( 'aksrt_page_meta', __('AKSRT 页面设置', 'aksrt'), [$this, 'render_page_meta_box'], 'page', 'side', 'default' ); // §3.8 custom filter metabox (side) $filter_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_post_filter_settings() : ['custom_filter' => []]; if (!empty($filter_settings['custom_filter'])) { add_meta_box( 'aksrt_custom_filter_meta', __('高级筛选', 'aksrt'), [$this, 'render_custom_filter_meta_box'], 'post', 'side', 'default' ); } } /** * Render the page meta box (page_header_style / cover override). */ public function render_page_meta_box(WP_Post $post): void { $header_style = get_post_meta($post->ID, 'page_header_style', true); $cover_img = get_post_meta($post->ID, 'page_header_cover_img', true); wp_nonce_field('aksrt_page_meta', 'aksrt_page_meta_nonce'); ?>

ID); wp_nonce_field('aksrt_post_meta', 'aksrt_post_meta_nonce'); ?>

ID, '_aksrt_show_layout', true); if (!in_array($show_layout, ['no_sidebar', 'sidebar_left', 'sidebar_right'], true)) { $show_layout = ''; } ?>

__('阅读进度条', 'aksrt'), 'enable_lightbox' => __('图片灯箱', 'aksrt'), 'show_related' => __('相关推荐', 'aksrt'), 'enable_like' => __('点赞按钮', 'aksrt'), 'enable_favorite' => __('收藏按钮', 'aksrt'), 'enable_share' => __('分享按钮', 'aksrt'), 'enable_print' => __('打印按钮', 'aksrt'), 'enable_pdf' => __('PDF 导出按钮', 'aksrt'), ]; foreach ($toggle_fields as $field_key => $field_label) : ?>



[]]; $dimensions = $filter_settings['custom_filter']; if (empty($dimensions)) { echo '

' . esc_html__('尚未定义筛选维度,请前往 文章设置 → 高级筛选 添加。', 'aksrt') . '

'; return; } foreach ($dimensions as $dim) : $meta_key = '_aksrt_cf_' . $dim['key']; $current = get_post_meta($post->ID, $meta_key, true); ?>

save_quick_edit($post_id); return; } $raw = $_POST['aksrt_post_meta'] ?? []; $sanitized = [ 'cover_images' => isset($raw['cover_images']) ? sanitize_text_field($raw['cover_images']) : '', 'custom_excerpt' => isset($raw['custom_excerpt']) ? sanitize_textarea_field($raw['custom_excerpt']) : '', 'layout_override' => isset($raw['layout_override']) ? sanitize_key($raw['layout_override']) : '', 'header_image_mode' => isset($raw['header_image_mode']) ? sanitize_key($raw['header_image_mode']) : '', // New route: '' follow | '1' force on | '0' force off. 'show_toc' => isset($raw['show_toc']) && in_array((string) $raw['show_toc'], ['', '0', '1'], true) ? (string) $raw['show_toc'] : '', 'show_reading_progress' => isset($raw['show_reading_progress']) ? sanitize_key((string) $raw['show_reading_progress']) : '', 'enable_lightbox' => isset($raw['enable_lightbox']) ? sanitize_key((string) $raw['enable_lightbox']) : '', 'show_related' => isset($raw['show_related']) ? sanitize_key((string) $raw['show_related']) : '', 'related_count' => isset($raw['related_count']) ? (int) $raw['related_count'] : 0, 'enable_like' => isset($raw['enable_like']) ? sanitize_key((string) $raw['enable_like']) : '', 'enable_favorite' => isset($raw['enable_favorite']) ? sanitize_key((string) $raw['enable_favorite']) : '', 'enable_share' => isset($raw['enable_share']) ? sanitize_key((string) $raw['enable_share']) : '', 'enable_print' => isset($raw['enable_print']) ? sanitize_key((string) $raw['enable_print']) : '', 'enable_pdf' => isset($raw['enable_pdf']) ? sanitize_key((string) $raw['enable_pdf']) : '', 'copyright_text' => isset($raw['copyright_text']) ? sanitize_textarea_field($raw['copyright_text']) : '', 'is_featured' => !empty($raw['is_featured']), // §3.8 文章扩展字段 'thumbnail_url' => isset($raw['thumbnail_url']) ? esc_url_raw((string) $raw['thumbnail_url']) : '', 'featured_slide' => isset($raw['featured_slide']) ? sanitize_text_field($raw['featured_slide']) : '', 'featured_video' => isset($raw['featured_video']) ? esc_url_raw((string) $raw['featured_video']) : '', 'featured_video_episode' => self::sanitize_video_episodes($raw['featured_video_episode'] ?? []), 'subtitle' => isset($raw['subtitle']) ? sanitize_text_field($raw['subtitle']) : '', 'views' => isset($raw['views']) ? max(0, (int) $raw['views']) : 0, 'likes' => isset($raw['likes']) ? max(0, (int) $raw['likes']) : 0, 'maxheight' => isset($raw['maxheight']) ? max(0, (int) $raw['maxheight']) : 0, ]; $valid_modes = ['', 'card', 'list', 'mini', 'grid-cms']; if (!in_array($sanitized['layout_override'], $valid_modes, true)) { $sanitized['layout_override'] = ''; } $valid_header_modes = ['', 'featured', 'auto', 'none']; if (!in_array($sanitized['header_image_mode'], $valid_header_modes, true)) { $sanitized['header_image_mode'] = ''; } foreach (['show_reading_progress', 'enable_lightbox', 'show_related', 'enable_like', 'enable_favorite', 'enable_share', 'enable_print', 'enable_pdf'] as $toggle_key) { if (!in_array($sanitized[$toggle_key], ['', '0', '1'], true)) { $sanitized[$toggle_key] = ''; } } $sanitized['related_count'] = max(0, min(20, (int) $sanitized['related_count'])); update_post_meta($post_id, self::META_KEY, $sanitized); // §3.8 Save custom filter dimension values as individual post meta if (isset($_POST['aksrt_custom_filter_meta_nonce']) && wp_verify_nonce($_POST['aksrt_custom_filter_meta_nonce'], 'aksrt_custom_filter_meta')) { if (!defined('DOING_AUTOSAVE') && current_user_can('edit_post', $post_id)) { $cf_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_post_filter_settings() : ['custom_filter' => []]; foreach ($cf_settings['custom_filter'] as $dim) { $meta_key = '_aksrt_cf_' . $dim['key']; $value = isset($_POST[$meta_key]) ? sanitize_key((string) $_POST[$meta_key]) : ''; if ($value !== '') { update_post_meta($post_id, $meta_key, $value); } else { delete_post_meta($post_id, $meta_key); } } } } } /** * §3.8 Add custom columns to the posts list table. */ public function add_columns(array $columns): array { $columns['aksrt_views'] = __('阅读量', 'aksrt'); $columns['aksrt_likes'] = __('点赞数', 'aksrt'); $columns['aksrt_sales'] = __('销售数据', 'aksrt'); return $columns; } /** * §3.8 Render custom column content. */ public function render_column(string $column, int $post_id): void { $meta = self::get_meta($post_id); if ($column === 'aksrt_views') { $views = (int) ($meta['views'] ?? 0); echo esc_html($views > 0 ? (string) $views : '—'); } elseif ($column === 'aksrt_likes') { $likes = (int) ($meta['likes'] ?? 0); $layout = esc_attr($meta['layout_override'] ?? ''); $toc = esc_attr($meta['show_toc'] ?? ''); $mh = (int) ($meta['maxheight'] ?? 0); echo '' . esc_html($likes > 0 ? (string) $likes : '—') . ''; } elseif ($column === 'aksrt_sales') { $this->render_sales_column($post_id); } } /** * Content-pay sales summary for posts list (zibll 销售数据 column parity). */ private function render_sales_column(int $post_id): void { if (!function_exists('aksrt_get_pay_meta') || !class_exists('AKSRT_Domain_Model')) { echo '—'; return; } $pay = aksrt_get_pay_meta($post_id); $pay_type = AKSRT_Domain_Model::normalize_pay_type((string) ($pay['pay_type'] ?? AKSRT_Domain_Model::PAY_TYPE_NO)); if ($pay_type === AKSRT_Domain_Model::PAY_TYPE_NO) { echo '' . esc_html__('免费', 'aksrt') . ''; return; } $labels = AKSRT_Domain_Model::pay_type_labels(); $type_label = $labels[$pay_type] ?? $pay_type; $modo = (($pay['pay_modo'] ?? '0') === 'points') ? 'points' : '0'; if ($modo === 'points') { $price_text = sprintf(__('%d 积分', 'aksrt'), (int) ceil((float) ($pay['points_price'] ?? $pay['price'] ?? 0))); } else { $price_text = '¥' . number_format((float) ($pay['price'] ?? 0), 2); } $meta_sales = (int) get_post_meta($post_id, AKSRT_Domain_Model::RESOURCE_SALES_VOLUME_KEY, true); $db_sales = 0; $revenue = 0.0; if (class_exists('AKSRT_Order_Repository')) { $map = AKSRT_Order_Repository::get_instance()->get_content_sales_map( [$post_id], AKSRT_Domain_Model::ORDER_PRODUCT_RESOURCE ); if (isset($map[$post_id])) { $db_sales = (int) ($map[$post_id]['sales_count'] ?? 0); $revenue = (float) ($map[$post_id]['revenue'] ?? 0); } } $orders_url = admin_url('admin.php?page=aksrt_orders&product_type=resource&product_id=' . $post_id); $products_url = admin_url('admin.php?page=aksrt_pay_products&s=' . $post_id); echo '
'; echo '' . esc_html((string) $type_label) . ''; echo '
' . esc_html($price_text); echo '
' . esc_html(sprintf(__('Meta销量 %d', 'aksrt'), max(0, $meta_sales))); if ($db_sales > 0) { printf( '
%s', esc_url($orders_url), esc_attr__('查看销售明细', 'aksrt'), esc_html(sprintf(__('真实销量 %d · ¥%s', 'aksrt'), $db_sales, number_format($revenue, 2))) ); } else { echo '
' . esc_html__('暂无订单', 'aksrt') . ''; } echo '
' . esc_html__('付费文章', 'aksrt') . ''; echo '
'; } /** * §3.8 Render quick edit and bulk edit fields. */ public function render_quick_edit(string $column_name, string $post_type): void { if ($column_name !== 'aksrt_views' || $post_type !== 'post') { return; } wp_nonce_field('aksrt_post_meta', 'aksrt_post_meta_nonce_qe'); ?>


base !== 'edit' || $screen->post_type !== 'post') { return; } ?>