Files
wordpress-theme-aksrt/inc/classes/class-aksrt-post-meta-box.php
T

551 lines
28 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']);
}
/**
* 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 = [];
return array_merge($defaults, $saved);
}
/**
* 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('头图模式', '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>
<input type="checkbox" name="aksrt_post_meta[show_toc]" value="1" <?php checked($meta['show_toc'] === '1'); ?>>
<?php esc_html_e('显示目录树', 'aksrt'); ?>
</label>
</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('视频 URL(嵌入/直链)', 'aksrt'); ?>">
<p><strong><?php esc_html_e('视频集数', 'aksrt'); ?></strong></p>
<input type="number" name="aksrt_post_meta[featured_video_episode]" value="<?php echo esc_attr((string) (int) $meta['featured_video_episode']); ?>" class="widefat" min="0" max="9999" step="1">
<small class="description"><?php esc_html_e('0 表示非剧集,>0 表示第 N 集。', '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;
// §3.8 Quick / Bulk edit — separate code path (merge mode)
if (!empty($_POST['aksrt_qe_flag'])) {
$this->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']) : '',
'show_toc' => !empty($raw['show_toc']) ? '1' : '',
'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' => isset($raw['featured_video_episode']) ? max(0, (int) $raw['featured_video_episode']) : 0,
'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');
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>';
}
}
/**
* §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">
</div>
</fieldset>
<?php
}
/**
* §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
}
}