Move ~94 root class shells and root *-traits into domain directories (core, auth, user, credits, content, payment/gateways, forum, shop, sms, ai, messages, extensions, widgets, settings, admin). Update bootstrap require paths, co-locate traits with owners, fix forum/user relative requires, drop duplicate shop controller requires, and wire home-modules load. Path-only; class names and init order unchanged.
867 lines
44 KiB
PHP
867 lines
44 KiB
PHP
<?php
|
||
/**
|
||
* AKSRT Post Meta Box
|
||
*
|
||
* 为文章(post)添加局部配置字段:
|
||
* - 附加封面图组(用于列表多图模式)
|
||
* - 自定义摘要
|
||
* - 列表布局覆盖
|
||
* - 文章头图模式
|
||
* - 目录树开关
|
||
* - 版权声明覆盖
|
||
*
|
||
* @package AKSRT
|
||
*/
|
||
|
||
defined('ABSPATH') || exit;
|
||
|
||
class AKSRT_Post_Meta_Box {
|
||
|
||
private static $instance = null;
|
||
|
||
const META_KEY = AKSRT_Domain_Model::POST_META_KEY;
|
||
|
||
public static function get_instance(): self {
|
||
if (null === self::$instance) self::$instance = new self();
|
||
return self::$instance;
|
||
}
|
||
|
||
public function init(): void {
|
||
add_action('add_meta_boxes', [$this, 'register_meta_box']);
|
||
add_action('save_post', [$this, 'save_meta_box']);
|
||
// §3.8 Quick / Bulk edit
|
||
add_filter('manage_post_posts_columns', [$this, 'add_columns']);
|
||
add_action('manage_post_posts_custom_column', [$this, 'render_column'], 10, 2);
|
||
add_action('quick_edit_custom_box', [$this, 'render_quick_edit'], 10, 2);
|
||
add_action('bulk_edit_custom_box', [$this, 'render_quick_edit'], 10, 2);
|
||
add_action('admin_footer-edit.php', [$this, 'admin_quick_edit_script']);
|
||
// Pay-type dropdown on posts list (zibll zibpay_type filter).
|
||
add_action('restrict_manage_posts', [$this, 'render_pay_type_filter']);
|
||
add_action('pre_get_posts', [$this, 'filter_posts_by_pay_type']);
|
||
}
|
||
|
||
/**
|
||
* Get post meta with defaults.
|
||
*/
|
||
public static function get_meta(int $post_id): array {
|
||
$defaults = AKSRT_Domain_Model::default_post_meta();
|
||
$saved = get_post_meta($post_id, self::META_KEY, true);
|
||
if (!is_array($saved)) {
|
||
$saved = [];
|
||
}
|
||
$meta = array_merge($defaults, $saved);
|
||
// New route only: episodes is always a list of {url,title}.
|
||
$meta['featured_video_episode'] = self::sanitize_video_episodes($meta['featured_video_episode'] ?? []);
|
||
if (!in_array((string) ($meta['show_toc'] ?? ''), ['', '0', '1'], true)) {
|
||
$meta['show_toc'] = '';
|
||
}
|
||
return $meta;
|
||
}
|
||
|
||
/**
|
||
* Sanitize video episode list (new route: array of url/title rows).
|
||
*
|
||
* @param mixed $raw Raw form / meta value.
|
||
* @return array<int, array{url:string,title:string}>
|
||
*/
|
||
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');
|
||
?>
|
||
<p><strong><?php esc_html_e('页面标题样式覆盖', 'aksrt'); ?></strong></p>
|
||
<select name="page_header_style" class="widefat">
|
||
<option value="" <?php selected($header_style, ''); ?>><?php esc_html_e('跟随全局', 'aksrt'); ?></option>
|
||
<option value="not" <?php selected($header_style, 'not'); ?>><?php esc_html_e('不显示', 'aksrt'); ?></option>
|
||
<option value="1" <?php selected($header_style, '1'); ?>><?php esc_html_e('简单', 'aksrt'); ?></option>
|
||
<option value="2" <?php selected($header_style, '2'); ?>><?php esc_html_e('卡片', 'aksrt'); ?></option>
|
||
<option value="3" <?php selected($header_style, '3'); ?>><?php esc_html_e('封面', 'aksrt'); ?></option>
|
||
</select>
|
||
<small class="description"><?php esc_html_e('覆盖全局「其它页面 → 统一页头」设置。', 'aksrt'); ?></small>
|
||
|
||
<p><strong><?php esc_html_e('页面封面图覆盖', 'aksrt'); ?></strong></p>
|
||
<input type="text" name="page_header_cover_img" value="<?php echo esc_attr($cover_img); ?>" class="widefat" placeholder="<?php esc_attr_e('图片 URL', 'aksrt'); ?>">
|
||
<small class="description"><?php esc_html_e('覆盖全局默认封面图,仅封面样式(样式3)生效。', 'aksrt'); ?></small>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Render the meta box.
|
||
*/
|
||
public function render_meta_box(WP_Post $post): void {
|
||
$meta = self::get_meta($post->ID);
|
||
wp_nonce_field('aksrt_post_meta', 'aksrt_post_meta_nonce');
|
||
?>
|
||
<p><strong><?php esc_html_e('附加封面图', 'aksrt'); ?></strong></p>
|
||
<p>
|
||
<input type="text" name="aksrt_post_meta[cover_images]" value="<?php echo esc_attr($meta['cover_images']); ?>" class="widefat" placeholder="<?php esc_attr_e('附件ID,逗号分隔', 'aksrt'); ?>">
|
||
<small class="description"><?php esc_html_e('用于列表多图模式,填写附件 ID(逗号分隔)。', 'aksrt'); ?></small>
|
||
</p>
|
||
|
||
<p><strong><?php esc_html_e('列表布局覆盖', 'aksrt'); ?></strong></p>
|
||
<select name="aksrt_post_meta[layout_override]" class="widefat">
|
||
<option value="" <?php selected($meta['layout_override'], ''); ?>><?php esc_html_e('跟随全局', 'aksrt'); ?></option>
|
||
<option value="card" <?php selected($meta['layout_override'], 'card'); ?>><?php esc_html_e('卡片', 'aksrt'); ?></option>
|
||
<option value="list" <?php selected($meta['layout_override'], 'list'); ?>><?php esc_html_e('列表', 'aksrt'); ?></option>
|
||
<option value="mini" <?php selected($meta['layout_override'], 'mini'); ?>><?php esc_html_e('迷你', 'aksrt'); ?></option>
|
||
</select>
|
||
|
||
<p><strong><?php esc_html_e('侧栏布局(Zibll show_layout)', 'aksrt'); ?></strong></p>
|
||
<?php
|
||
$show_layout = (string) get_post_meta($post->ID, '_aksrt_show_layout', true);
|
||
if (!in_array($show_layout, ['no_sidebar', 'sidebar_left', 'sidebar_right'], true)) {
|
||
$show_layout = '';
|
||
}
|
||
?>
|
||
<select name="aksrt_show_layout" class="widefat">
|
||
<option value="" <?php selected($show_layout, ''); ?>><?php esc_html_e('跟随全局', 'aksrt'); ?></option>
|
||
<option value="no_sidebar" <?php selected($show_layout, 'no_sidebar'); ?>><?php esc_html_e('无侧栏', 'aksrt'); ?></option>
|
||
<option value="sidebar_right" <?php selected($show_layout, 'sidebar_right'); ?>><?php esc_html_e('右侧栏', 'aksrt'); ?></option>
|
||
<option value="sidebar_left" <?php selected($show_layout, 'sidebar_left'); ?>><?php esc_html_e('左侧栏', 'aksrt'); ?></option>
|
||
</select>
|
||
<p class="description"><?php esc_html_e('覆盖全局侧栏开关与左右位置,仅影响本文/本页。', 'aksrt'); ?></p>
|
||
|
||
<p><strong><?php esc_html_e('头图模式', 'aksrt'); ?></strong></p>
|
||
<select name="aksrt_post_meta[header_image_mode]" class="widefat">
|
||
<option value="" <?php selected($meta['header_image_mode'], ''); ?>><?php esc_html_e('跟随全局', 'aksrt'); ?></option>
|
||
<option value="featured" <?php selected($meta['header_image_mode'], 'featured'); ?>><?php esc_html_e('特色图片', 'aksrt'); ?></option>
|
||
<option value="auto" <?php selected($meta['header_image_mode'], 'auto'); ?>><?php esc_html_e('自动(内容首图)', 'aksrt'); ?></option>
|
||
<option value="none" <?php selected($meta['header_image_mode'], 'none'); ?>><?php esc_html_e('不显示', 'aksrt'); ?></option>
|
||
</select>
|
||
|
||
<p>
|
||
<label for="aksrt_show_toc"><strong><?php esc_html_e('目录树', 'aksrt'); ?></strong></label>
|
||
<select name="aksrt_post_meta[show_toc]" id="aksrt_show_toc" class="widefat">
|
||
<option value="" <?php selected((string) ($meta['show_toc'] ?? ''), ''); ?>><?php esc_html_e('跟随全局', 'aksrt'); ?></option>
|
||
<option value="1" <?php selected((string) ($meta['show_toc'] ?? ''), '1'); ?>><?php esc_html_e('强制开启', 'aksrt'); ?></option>
|
||
<option value="0" <?php selected((string) ($meta['show_toc'] ?? ''), '0'); ?>><?php esc_html_e('强制关闭', 'aksrt'); ?></option>
|
||
</select>
|
||
</p>
|
||
|
||
<p><strong><?php esc_html_e('单篇交互覆盖', 'aksrt'); ?></strong></p>
|
||
<?php
|
||
$toggle_fields = [
|
||
'show_reading_progress' => __('阅读进度条', '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) :
|
||
?>
|
||
<p>
|
||
<label for="aksrt_post_meta_<?php echo esc_attr($field_key); ?>" class="screen-reader-text"><?php echo esc_html($field_label); ?></label>
|
||
<select name="aksrt_post_meta[<?php echo esc_attr($field_key); ?>]" id="aksrt_post_meta_<?php echo esc_attr($field_key); ?>" class="widefat">
|
||
<option value="" <?php selected($meta[$field_key], ''); ?>><?php esc_html_e('跟随全局', 'aksrt'); ?></option>
|
||
<option value="1" <?php selected($meta[$field_key], '1'); ?>><?php esc_html_e('强制开启', 'aksrt'); ?></option>
|
||
<option value="0" <?php selected($meta[$field_key], '0'); ?>><?php esc_html_e('强制关闭', 'aksrt'); ?></option>
|
||
</select>
|
||
<small class="description"><?php echo esc_html($field_label); ?></small>
|
||
</p>
|
||
<?php endforeach; ?>
|
||
|
||
<p><strong><?php esc_html_e('相关推荐数量覆盖', 'aksrt'); ?></strong></p>
|
||
<p>
|
||
<input type="number" name="aksrt_post_meta[related_count]" value="<?php echo esc_attr((string) (int) $meta['related_count']); ?>" class="widefat" min="0" max="20" step="1">
|
||
<small class="description"><?php esc_html_e('0 表示跟随全局设置。', 'aksrt'); ?></small>
|
||
</p>
|
||
|
||
<p>
|
||
<label>
|
||
<input type="checkbox" name="aksrt_post_meta[is_featured]" value="1" <?php checked(!empty($meta['is_featured'])); ?>>
|
||
<?php esc_html_e('标记为推荐文章', 'aksrt'); ?>
|
||
</label>
|
||
</p>
|
||
|
||
<p><strong><?php esc_html_e('自定义摘要', 'aksrt'); ?></strong></p>
|
||
<textarea name="aksrt_post_meta[custom_excerpt]" rows="3" class="widefat" placeholder="<?php esc_attr_e('留空使用自动摘要', 'aksrt'); ?>"><?php echo esc_textarea($meta['custom_excerpt']); ?></textarea>
|
||
|
||
<p><strong><?php esc_html_e('版权声明覆盖', 'aksrt'); ?></strong></p>
|
||
<textarea name="aksrt_post_meta[copyright_text]" rows="3" class="widefat" placeholder="<?php esc_attr_e('留空使用默认版权文案', 'aksrt'); ?>"><?php echo esc_textarea($meta['copyright_text']); ?></textarea>
|
||
|
||
<hr>
|
||
<p><strong><?php esc_html_e('副标题', 'aksrt'); ?></strong></p>
|
||
<input type="text" name="aksrt_post_meta[subtitle]" value="<?php echo esc_attr($meta['subtitle']); ?>" class="widefat" placeholder="<?php esc_attr_e('可选,显示在标题下方', 'aksrt'); ?>">
|
||
|
||
<p><strong><?php esc_html_e('外链特色图', 'aksrt'); ?></strong></p>
|
||
<input type="url" name="aksrt_post_meta[thumbnail_url]" value="<?php echo esc_url($meta['thumbnail_url']); ?>" class="widefat" placeholder="<?php esc_attr_e('外部图片 URL(覆盖特色图片)', 'aksrt'); ?>">
|
||
<small class="description"><?php esc_html_e('填入外部图片 URL 将替代特色图片。', 'aksrt'); ?></small>
|
||
|
||
<p><strong><?php esc_html_e('幻灯片封面', 'aksrt'); ?></strong></p>
|
||
<input type="text" name="aksrt_post_meta[featured_slide]" value="<?php echo esc_attr($meta['featured_slide']); ?>" class="widefat" placeholder="<?php esc_attr_e('图片 URL,逗号分隔', 'aksrt'); ?>">
|
||
<small class="description"><?php esc_html_e('多张图片 URL 用逗号分隔,用于封面轮播。', 'aksrt'); ?></small>
|
||
|
||
<p><strong><?php esc_html_e('特色视频', 'aksrt'); ?></strong></p>
|
||
<input type="url" name="aksrt_post_meta[featured_video]" value="<?php echo esc_url($meta['featured_video']); ?>" class="widefat" placeholder="<?php esc_attr_e('第 1 集视频 URL(直链)', 'aksrt'); ?>">
|
||
|
||
<p><strong><?php esc_html_e('视频剧集列表', 'aksrt'); ?></strong></p>
|
||
<?php
|
||
$episodes = is_array($meta['featured_video_episode'] ?? null) ? $meta['featured_video_episode'] : [];
|
||
// Always show at least 3 editable rows for new-route authoring.
|
||
$rows = max(3, count($episodes));
|
||
for ($i = 0; $i < $rows; $i++) :
|
||
$ep = is_array($episodes[$i] ?? null) ? $episodes[$i] : [];
|
||
$ep_url = (string) ($ep['url'] ?? '');
|
||
$ep_title = (string) ($ep['title'] ?? '');
|
||
?>
|
||
<p class="aksrt-episode-row">
|
||
<input type="text" name="aksrt_post_meta[featured_video_episode][<?php echo (int) $i; ?>][title]" value="<?php echo esc_attr($ep_title); ?>" class="widefat" placeholder="<?php echo esc_attr(sprintf(__('第 %d 集标题(可选)', 'aksrt'), $i + 1)); ?>" style="margin-bottom:4px;">
|
||
<input type="url" name="aksrt_post_meta[featured_video_episode][<?php echo (int) $i; ?>][url]" value="<?php echo esc_url($ep_url); ?>" class="widefat" placeholder="<?php echo esc_attr(sprintf(__('第 %d 集视频 URL', 'aksrt'), $i + 1)); ?>">
|
||
</p>
|
||
<?php endfor; ?>
|
||
<small class="description"><?php esc_html_e('新路线:每行一集(标题 + URL)。留空 URL 的行会被忽略。第 1 集可与上方「特色视频」二选一填写。', 'aksrt'); ?></small>
|
||
|
||
<hr>
|
||
<p><strong><?php esc_html_e('手动计数覆盖', 'aksrt'); ?></strong></p>
|
||
<p>
|
||
<label><?php esc_html_e('阅读量', 'aksrt'); ?></label>
|
||
<input type="number" name="aksrt_post_meta[views]" value="<?php echo esc_attr((string) (int) $meta['views']); ?>" class="widefat" min="0" step="1">
|
||
</p>
|
||
<p>
|
||
<label><?php esc_html_e('点赞数', 'aksrt'); ?></label>
|
||
<input type="number" name="aksrt_post_meta[likes]" value="<?php echo esc_attr((string) (int) $meta['likes']); ?>" class="widefat" min="0" step="1">
|
||
</p>
|
||
<small class="description"><?php esc_html_e('0 表示不覆盖,使用系统统计值。', 'aksrt'); ?></small>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Render the custom filter metabox (per-dimension value selectors).
|
||
* §3.8 — stores values as individual post meta keys (_aksrt_cf_{dim_key}).
|
||
*/
|
||
public function render_custom_filter_meta_box(WP_Post $post): void {
|
||
wp_nonce_field('aksrt_custom_filter_meta', 'aksrt_custom_filter_meta_nonce');
|
||
|
||
$filter_settings = class_exists('AKSRT_Settings')
|
||
? AKSRT_Settings::get_post_filter_settings()
|
||
: ['custom_filter' => []];
|
||
$dimensions = $filter_settings['custom_filter'];
|
||
|
||
if (empty($dimensions)) {
|
||
echo '<p class="description">' . esc_html__('尚未定义筛选维度,请前往 文章设置 → 高级筛选 添加。', 'aksrt') . '</p>';
|
||
return;
|
||
}
|
||
|
||
foreach ($dimensions as $dim) :
|
||
$meta_key = '_aksrt_cf_' . $dim['key'];
|
||
$current = get_post_meta($post->ID, $meta_key, true);
|
||
?>
|
||
<p>
|
||
<label for="<?php echo esc_attr($meta_key); ?>"><strong><?php echo esc_html($dim['name']); ?></strong></label>
|
||
<select name="<?php echo esc_attr($meta_key); ?>" id="<?php echo esc_attr($meta_key); ?>" class="widefat">
|
||
<option value=""><?php esc_html_e('未选择', 'aksrt'); ?></option>
|
||
<?php foreach ($dim['vals'] as $val) : ?>
|
||
<option value="<?php echo esc_attr($val['key']); ?>" <?php selected($current, $val['key']); ?>><?php echo esc_html($val['name']); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</p>
|
||
<?php
|
||
endforeach;
|
||
}
|
||
|
||
/**
|
||
* Save meta box data.
|
||
*/
|
||
public function save_meta_box(int $post_id): void {
|
||
// Save page meta (page_header_style / page_header_cover_img)
|
||
if (isset($_POST['aksrt_page_meta_nonce']) && wp_verify_nonce($_POST['aksrt_page_meta_nonce'], 'aksrt_page_meta')) {
|
||
if (!defined('DOING_AUTOSAVE') && current_user_can('edit_post', $post_id)) {
|
||
$style = isset($_POST['page_header_style']) ? sanitize_key((string) $_POST['page_header_style']) : '';
|
||
if (!in_array($style, ['', 'not', '1', '2', '3'], true)) {
|
||
$style = '';
|
||
}
|
||
if ($style !== '') {
|
||
update_post_meta($post_id, 'page_header_style', $style);
|
||
} else {
|
||
delete_post_meta($post_id, 'page_header_style');
|
||
}
|
||
|
||
$cover = isset($_POST['page_header_cover_img']) ? esc_url_raw((string) $_POST['page_header_cover_img']) : '';
|
||
if ($cover !== '') {
|
||
update_post_meta($post_id, 'page_header_cover_img', $cover);
|
||
} else {
|
||
delete_post_meta($post_id, 'page_header_cover_img');
|
||
}
|
||
}
|
||
}
|
||
|
||
// Save post meta (aksrt_post_meta group)
|
||
if (!isset($_POST['aksrt_post_meta_nonce'])) return;
|
||
if (!wp_verify_nonce($_POST['aksrt_post_meta_nonce'], 'aksrt_post_meta')) return;
|
||
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
|
||
if (!current_user_can('edit_post', $post_id)) return;
|
||
|
||
// Zibll show_layout (independent of list layout_override).
|
||
$show_layout = isset($_POST['aksrt_show_layout']) ? sanitize_key((string) wp_unslash($_POST['aksrt_show_layout'])) : '';
|
||
if (!in_array($show_layout, ['no_sidebar', 'sidebar_left', 'sidebar_right'], true)) {
|
||
$show_layout = '';
|
||
}
|
||
if ($show_layout !== '') {
|
||
update_post_meta($post_id, '_aksrt_show_layout', $show_layout);
|
||
} else {
|
||
delete_post_meta($post_id, '_aksrt_show_layout');
|
||
}
|
||
|
||
// §3.8 Quick / Bulk edit — separate code path (merge mode)
|
||
if (!empty($_POST['aksrt_qe_flag'])) {
|
||
$this->save_quick_edit($post_id);
|
||
// Bulk pay fields may be submitted together with QE flag on bulk form.
|
||
$this->save_bulk_pay_fields($post_id);
|
||
return;
|
||
}
|
||
|
||
// Bulk-only pay fields without aksrt_qe_flag (when only pay row used).
|
||
if (!empty($_POST['aksrt_bulk_pay_flag'])) {
|
||
$this->save_bulk_pay_fields($post_id);
|
||
// Continue only if full meta also posted; otherwise done.
|
||
if (!isset($_POST['aksrt_post_meta'])) {
|
||
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 '<span class="aksrt-col-data" data-views="' . (int) ($meta['views'] ?? 0) . '" data-likes="' . $likes . '" data-layout="' . $layout . '" data-toc="' . $toc . '" data-maxheight="' . $mh . '">' . esc_html($likes > 0 ? (string) $likes : '—') . '</span>';
|
||
} 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 '<span class="description">' . esc_html__('免费', 'aksrt') . '</span>';
|
||
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 '<div style="font-size:12px;line-height:1.5;">';
|
||
echo '<strong style="color:#0c9cc8;">' . esc_html((string) $type_label) . '</strong>';
|
||
echo '<br>' . esc_html($price_text);
|
||
echo '<br>' . esc_html(sprintf(__('Meta销量 %d', 'aksrt'), max(0, $meta_sales)));
|
||
if ($db_sales > 0) {
|
||
printf(
|
||
'<br><a href="%s" title="%s">%s</a>',
|
||
esc_url($orders_url),
|
||
esc_attr__('查看销售明细', 'aksrt'),
|
||
esc_html(sprintf(__('真实销量 %d · ¥%s', 'aksrt'), $db_sales, number_format($revenue, 2)))
|
||
);
|
||
} else {
|
||
echo '<br><span class="description">' . esc_html__('暂无订单', 'aksrt') . '</span>';
|
||
}
|
||
echo '<br><a href="' . esc_url($products_url) . '">' . esc_html__('付费文章', 'aksrt') . '</a>';
|
||
if ($pay_type === AKSRT_Domain_Model::PAY_TYPE_DOWNLOAD) {
|
||
$dl_url = admin_url('admin.php?page=aksrt_download_logs&post_id=' . $post_id);
|
||
echo ' · <a href="' . esc_url($dl_url) . '">' . esc_html__('下载记录', 'aksrt') . '</a>';
|
||
}
|
||
echo '</div>';
|
||
}
|
||
|
||
/**
|
||
* Dropdown filter for content pay_type on edit.php?post_type=post.
|
||
*/
|
||
public function render_pay_type_filter(string $post_type): void {
|
||
if ($post_type !== 'post' || !class_exists('AKSRT_Domain_Model')) {
|
||
return;
|
||
}
|
||
$current = isset($_GET['aksrt_pay_type']) ? sanitize_key((string) wp_unslash($_GET['aksrt_pay_type'])) : '';
|
||
$labels = AKSRT_Domain_Model::pay_type_labels();
|
||
echo '<select name="aksrt_pay_type">';
|
||
echo '<option value="">' . esc_html__('全部付费类型', 'aksrt') . '</option>';
|
||
foreach ($labels as $key => $label) {
|
||
printf(
|
||
'<option value="%s"%s>%s</option>',
|
||
esc_attr($key),
|
||
selected($current, $key, false),
|
||
esc_html($label)
|
||
);
|
||
}
|
||
echo '</select>';
|
||
}
|
||
|
||
/**
|
||
* Apply aksrt_pay_type filter via denormalized _aksrt_pay_type meta.
|
||
*/
|
||
public function filter_posts_by_pay_type(\WP_Query $query): void {
|
||
if (!is_admin() || !$query->is_main_query()) {
|
||
return;
|
||
}
|
||
$screen_post_type = $query->get('post_type');
|
||
if ($screen_post_type !== 'post') {
|
||
return;
|
||
}
|
||
if (empty($_GET['aksrt_pay_type'])) {
|
||
return;
|
||
}
|
||
$pay_type = sanitize_key((string) wp_unslash($_GET['aksrt_pay_type']));
|
||
if ($pay_type === '' || !class_exists('AKSRT_Domain_Model')) {
|
||
return;
|
||
}
|
||
$pay_type = AKSRT_Domain_Model::normalize_pay_type($pay_type);
|
||
$meta_query = (array) $query->get('meta_query');
|
||
if ($pay_type === AKSRT_Domain_Model::PAY_TYPE_NO) {
|
||
$meta_query[] = [
|
||
'relation' => 'OR',
|
||
[
|
||
'key' => AKSRT_Domain_Model::PAY_TYPE_KEY,
|
||
'value' => AKSRT_Domain_Model::PAY_TYPE_NO,
|
||
'compare' => '=',
|
||
],
|
||
[
|
||
'key' => AKSRT_Domain_Model::PAY_TYPE_KEY,
|
||
'compare' => 'NOT EXISTS',
|
||
],
|
||
];
|
||
} else {
|
||
$meta_query[] = [
|
||
'key' => AKSRT_Domain_Model::PAY_TYPE_KEY,
|
||
'value' => $pay_type,
|
||
'compare' => '=',
|
||
];
|
||
}
|
||
$query->set('meta_query', $meta_query);
|
||
}
|
||
|
||
/**
|
||
* §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');
|
||
?>
|
||
<fieldset class="inline-edit-col-right" id="aksrt-quick-edit">
|
||
<div class="inline-edit-col">
|
||
<h4><?php esc_html_e('AKSRT 文章设置', 'aksrt'); ?></h4>
|
||
<input type="hidden" name="aksrt_qe_flag" value="1">
|
||
<label class="alignleft">
|
||
<span class="title"><?php esc_html_e('阅读量', 'aksrt'); ?></span>
|
||
<input type="number" name="aksrt_qe_views" min="0" step="1" value="" class="aksrt-qe-views">
|
||
</label>
|
||
<label class="alignleft">
|
||
<span class="title"><?php esc_html_e('点赞数', 'aksrt'); ?></span>
|
||
<input type="number" name="aksrt_qe_likes" min="0" step="1" value="" class="aksrt-qe-likes">
|
||
</label>
|
||
<label class="alignleft">
|
||
<span class="title"><?php esc_html_e('布局', 'aksrt'); ?></span>
|
||
<select name="aksrt_qe_layout" class="aksrt-qe-layout">
|
||
<option value="-1"><?php esc_html_e('— 不更改 —', 'aksrt'); ?></option>
|
||
<option value=""><?php esc_html_e('跟随全局', 'aksrt'); ?></option>
|
||
<option value="card"><?php esc_html_e('卡片', 'aksrt'); ?></option>
|
||
<option value="list"><?php esc_html_e('列表', 'aksrt'); ?></option>
|
||
<option value="mini"><?php esc_html_e('迷你', 'aksrt'); ?></option>
|
||
<option value="grid-cms"><?php esc_html_e('CMS网格', 'aksrt'); ?></option>
|
||
</select>
|
||
</label>
|
||
<label class="alignleft">
|
||
<span class="title"><?php esc_html_e('目录树', 'aksrt'); ?></span>
|
||
<select name="aksrt_qe_toc" class="aksrt-qe-toc">
|
||
<option value="-1"><?php esc_html_e('— 不更改 —', 'aksrt'); ?></option>
|
||
<option value=""><?php esc_html_e('跟随全局', 'aksrt'); ?></option>
|
||
<option value="1"><?php esc_html_e('显示', 'aksrt'); ?></option>
|
||
<option value="0"><?php esc_html_e('隐藏', 'aksrt'); ?></option>
|
||
</select>
|
||
</label>
|
||
<label class="alignleft">
|
||
<span class="title"><?php esc_html_e('限高(px)', 'aksrt'); ?></span>
|
||
<input type="number" name="aksrt_qe_maxheight" min="0" step="100" value="" class="aksrt-qe-maxheight" placeholder="<?php esc_attr_e('0=不限', 'aksrt'); ?>">
|
||
</label>
|
||
<br class="clear">
|
||
<h4 style="margin-top:10px;"><?php esc_html_e('内容付费(批量)', 'aksrt'); ?></h4>
|
||
<input type="hidden" name="aksrt_bulk_pay_flag" value="1">
|
||
<label class="alignleft">
|
||
<span class="title"><?php esc_html_e('付费类型', 'aksrt'); ?></span>
|
||
<select name="aksrt_bulk_pay_type" class="aksrt-bulk-pay-type">
|
||
<option value="-1"><?php esc_html_e('— 不更改 —', 'aksrt'); ?></option>
|
||
<?php
|
||
$pay_labels = class_exists('AKSRT_Domain_Model') ? AKSRT_Domain_Model::pay_type_labels() : [];
|
||
foreach ($pay_labels as $k => $lab) :
|
||
?>
|
||
<option value="<?php echo esc_attr($k); ?>"><?php echo esc_html($lab); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</label>
|
||
<label class="alignleft">
|
||
<span class="title"><?php esc_html_e('支付方式', 'aksrt'); ?></span>
|
||
<select name="aksrt_bulk_pay_modo" class="aksrt-bulk-pay-modo">
|
||
<option value="-1"><?php esc_html_e('— 不更改 —', 'aksrt'); ?></option>
|
||
<option value="0"><?php esc_html_e('现金', 'aksrt'); ?></option>
|
||
<option value="points"><?php esc_html_e('积分', 'aksrt'); ?></option>
|
||
</select>
|
||
</label>
|
||
<label class="alignleft">
|
||
<span class="title"><?php esc_html_e('现金价', 'aksrt'); ?></span>
|
||
<input type="number" min="0" step="0.01" name="aksrt_bulk_pay_price" value="" class="aksrt-bulk-pay-price" placeholder="<?php esc_attr_e('留空=不改', 'aksrt'); ?>">
|
||
</label>
|
||
<label class="alignleft">
|
||
<span class="title"><?php esc_html_e('积分价', 'aksrt'); ?></span>
|
||
<input type="number" min="0" step="1" name="aksrt_bulk_points_price" value="" class="aksrt-bulk-points-price" placeholder="<?php esc_attr_e('留空=不改', 'aksrt'); ?>">
|
||
</label>
|
||
<label class="alignleft">
|
||
<span class="title"><?php esc_html_e('虚拟销量', 'aksrt'); ?></span>
|
||
<input type="number" min="0" step="1" name="aksrt_bulk_virtual_sales" value="" class="aksrt-bulk-virtual-sales" placeholder="<?php esc_attr_e('留空=不改', 'aksrt'); ?>">
|
||
</label>
|
||
<br class="clear">
|
||
</div>
|
||
</fieldset>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Bulk/quick merge update for content pay meta (_aksrt_pay + denormalized keys).
|
||
* Only non-sentinel fields are written; omit to keep existing.
|
||
*/
|
||
private function save_bulk_pay_fields(int $post_id): void {
|
||
if (!class_exists('AKSRT_Domain_Model') || !function_exists('aksrt_get_pay_meta')) {
|
||
return;
|
||
}
|
||
if (!current_user_can('edit_post', $post_id)) {
|
||
return;
|
||
}
|
||
|
||
$type_raw = isset($_POST['aksrt_bulk_pay_type']) ? (string) wp_unslash($_POST['aksrt_bulk_pay_type']) : '-1';
|
||
$modo_raw = isset($_POST['aksrt_bulk_pay_modo']) ? (string) wp_unslash($_POST['aksrt_bulk_pay_modo']) : '-1';
|
||
$price_raw = isset($_POST['aksrt_bulk_pay_price']) ? trim((string) wp_unslash($_POST['aksrt_bulk_pay_price'])) : '';
|
||
$points_raw = isset($_POST['aksrt_bulk_points_price']) ? trim((string) wp_unslash($_POST['aksrt_bulk_points_price'])) : '';
|
||
$virtual_raw = isset($_POST['aksrt_bulk_virtual_sales']) ? trim((string) wp_unslash($_POST['aksrt_bulk_virtual_sales'])) : '';
|
||
|
||
$has_change = ($type_raw !== '' && $type_raw !== '-1')
|
||
|| ($modo_raw !== '' && $modo_raw !== '-1')
|
||
|| $price_raw !== ''
|
||
|| $points_raw !== ''
|
||
|| $virtual_raw !== '';
|
||
if (!$has_change) {
|
||
return;
|
||
}
|
||
|
||
$meta = aksrt_get_pay_meta($post_id);
|
||
|
||
if ($type_raw !== '' && $type_raw !== '-1') {
|
||
$meta['pay_type'] = AKSRT_Domain_Model::normalize_pay_type(sanitize_key($type_raw));
|
||
}
|
||
if ($modo_raw !== '' && $modo_raw !== '-1') {
|
||
$modo = sanitize_key($modo_raw);
|
||
$meta['pay_modo'] = ($modo === 'points') ? 'points' : '0';
|
||
}
|
||
if ($price_raw !== '' && is_numeric($price_raw)) {
|
||
$meta['price'] = max(0, (float) $price_raw);
|
||
}
|
||
if ($points_raw !== '' && is_numeric($points_raw)) {
|
||
$meta['points_price'] = max(0, (int) $points_raw);
|
||
}
|
||
if ($virtual_raw !== '' && is_numeric($virtual_raw)) {
|
||
$meta['virtual_sales'] = max(0, (int) $virtual_raw);
|
||
}
|
||
|
||
$meta = AKSRT_Domain_Model::sanitize_pay_meta($meta);
|
||
update_post_meta($post_id, AKSRT_Domain_Model::PAY_META_KEY, $meta);
|
||
update_post_meta($post_id, AKSRT_Domain_Model::PAY_TYPE_KEY, (string) ($meta['pay_type'] ?? AKSRT_Domain_Model::PAY_TYPE_NO));
|
||
update_post_meta($post_id, AKSRT_Domain_Model::PAY_PRICE_KEY, (float) ($meta['price'] ?? 0));
|
||
if (class_exists('AKSRT_Domain_Model') && method_exists('AKSRT_Domain_Model', 'is_resource_pay_type')) {
|
||
update_post_meta(
|
||
$post_id,
|
||
AKSRT_Domain_Model::RESOURCE_MARKER_KEY,
|
||
AKSRT_Domain_Model::is_resource_pay_type((string) ($meta['pay_type'] ?? 'no')) ? 1 : 0
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* §3.8 Quick / Bulk edit merge-mode save.
|
||
* Only updates fields that were actually submitted (non-sentinel, non-empty).
|
||
* Existing meta values for omitted fields are preserved.
|
||
*/
|
||
private function save_quick_edit(int $post_id): void {
|
||
$existing = self::get_meta($post_id);
|
||
|
||
$views = isset($_POST['aksrt_qe_views']) && $_POST['aksrt_qe_views'] !== ''
|
||
? max(0, (int) $_POST['aksrt_qe_views'])
|
||
: (int) ($existing['views'] ?? 0);
|
||
|
||
$likes = isset($_POST['aksrt_qe_likes']) && $_POST['aksrt_qe_likes'] !== ''
|
||
? max(0, (int) $_POST['aksrt_qe_likes'])
|
||
: (int) ($existing['likes'] ?? 0);
|
||
|
||
$layout = $existing['layout_override'] ?? '';
|
||
if (isset($_POST['aksrt_qe_layout']) && $_POST['aksrt_qe_layout'] !== '-1') {
|
||
$layout = sanitize_key((string) $_POST['aksrt_qe_layout']);
|
||
if (!in_array($layout, ['', 'card', 'list', 'mini', 'grid-cms'], true)) {
|
||
$layout = $existing['layout_override'] ?? '';
|
||
}
|
||
}
|
||
|
||
$toc = $existing['show_toc'] ?? '';
|
||
if (isset($_POST['aksrt_qe_toc']) && $_POST['aksrt_qe_toc'] !== '-1') {
|
||
$toc_v = sanitize_key((string) $_POST['aksrt_qe_toc']);
|
||
$toc = in_array($toc_v, ['', '0', '1'], true) ? $toc_v : ($existing['show_toc'] ?? '');
|
||
}
|
||
|
||
$mh = isset($_POST['aksrt_qe_maxheight']) && $_POST['aksrt_qe_maxheight'] !== ''
|
||
? max(0, (int) $_POST['aksrt_qe_maxheight'])
|
||
: (int) ($existing['maxheight'] ?? 0);
|
||
|
||
$existing['views'] = $views;
|
||
$existing['likes'] = $likes;
|
||
$existing['layout_override'] = $layout;
|
||
$existing['show_toc'] = $toc;
|
||
$existing['maxheight'] = $mh;
|
||
|
||
update_post_meta($post_id, self::META_KEY, $existing);
|
||
}
|
||
|
||
/**
|
||
* §3.8 Output inline JS on edit.php to populate quick edit fields from column data attributes.
|
||
*/
|
||
public function admin_quick_edit_script(): void {
|
||
$screen = function_exists('get_current_screen') ? get_current_screen() : null;
|
||
if (!$screen || $screen->base !== 'edit' || $screen->post_type !== 'post') {
|
||
return;
|
||
}
|
||
?>
|
||
<script>
|
||
(function () {
|
||
var wp_inline_edit = window.inlineEditPost ? window.inlineEditPost.edit : null;
|
||
if (!wp_inline_edit) return;
|
||
|
||
window.inlineEditPost.edit = function (id) {
|
||
wp_inline_edit.apply(this, arguments);
|
||
|
||
var postId = 0;
|
||
if (typeof id === 'object') {
|
||
postId = parseInt(this.getId(id), 10);
|
||
}
|
||
if (!postId) return;
|
||
|
||
var row = document.getElementById('post-' + postId);
|
||
if (!row) return;
|
||
|
||
var viewsEl = row.querySelector('.column-aksrt_views');
|
||
var likesEl = row.querySelector('.column-aksrt_likes');
|
||
var data = (likesEl && likesEl.querySelector('.aksrt-col-data'))
|
||
|| (viewsEl && viewsEl.querySelector('.aksrt-col-data'));
|
||
if (!data) return;
|
||
|
||
var form = document.getElementById('edit-' + postId);
|
||
if (!form) return;
|
||
|
||
var v = data.getAttribute('data-views') || '';
|
||
var l = data.getAttribute('data-likes') || '';
|
||
var layout = data.getAttribute('data-layout') || '';
|
||
var toc = data.getAttribute('data-toc') || '';
|
||
var mh = data.getAttribute('data-maxheight') || '';
|
||
|
||
var qv = form.querySelector('.aksrt-qe-views');
|
||
var ql = form.querySelector('.aksrt-qe-likes');
|
||
if (qv) qv.value = v;
|
||
if (ql) ql.value = l;
|
||
|
||
var qLayout = form.querySelector('.aksrt-qe-layout');
|
||
if (qLayout) qLayout.value = layout;
|
||
var qToc = form.querySelector('.aksrt-qe-toc');
|
||
if (qToc) qToc.value = toc;
|
||
var qMh = form.querySelector('.aksrt-qe-maxheight');
|
||
if (qMh) qMh.value = mh;
|
||
};
|
||
})();
|
||
</script>
|
||
<?php
|
||
}
|
||
}
|