refactor(admin): 清理付费 meta 死字段并补齐商品介绍渲染
延续上一轮 pay_count「只写不读」的排查,把其余写而不读的字段一次 性处理完。按字段性质分两类处理,不是一律删。 【删除】纯数据垃圾,无界面入口、无消费方: - card_keys / purchase_limit / stock:只有 DomainModel 的默认值与 sanitize,全仓零引用。契约测试原本还断言它们不得出现在 metabox 上。 - 随 card_keys 一并删除 sanitle_card_keys() 助手。 - video_scale_height「固定长宽比例」:参考主题里这是轮播组件 widget 的参数,不属于付费视频字段,当初误搬到付费 metabox 上且从未被消费。 连默认值、sanitize、metabox 保存项一起移除,并同步修正契约测试。 【补齐】有界面入口、管理员填了但不显示的四个字段: pay_title / pay_doc / pay_details / pay_extra_hide 此前只有 metabox 输入框和 sanitize,前端一个都不读。按参考主题 pages/download.php 的结构接到单篇资源下载页: - pay_title 有值则替代文章标题作商品标题(回退 get_the_title); - pay_doc 商品简介、pay_details 更多详情渲染在标题区下方; - pay_extra_hide 额外隐藏内容只在有下载权限时渲染在下载盒之后。 三处 HTML 输出均走 wp_kses_post,与 sanitize 侧的安全 HTML 口径一致。 同时把 pay_extra_hide 接进文章页付费盒 (aksrt_get_paid_box_html):该函数本身只在有付费权限时执行,天然 就是「付费后才可见」的位置,复用已有的 .pay-extra-hide 样式。 验证:php -l 四个 PHP 文件无语法错误; node --test tests/widget-system/*.test.cjs 449 项全部通过。
This commit is contained in:
1 parent
8e1fd0a30f
commit
b447c41f13
5 files changed
+25
-32
No files matched your search
@@ -1623,6 +1623,11 @@ if (!function_exists('aksrt_get_paid_box_html')) {
|
|||||||
$title_style = $count !== '' ? ' style="padding-right:48px"' : '';
|
$title_style = $count !== '' ? ' style="padding-right:48px"' : '';
|
||||||
$body_class = 'box-body relative' . ($pay_type === AKSRT_PAY_TYPE_VIDEO ? ' dplayer-featured' : '');
|
$body_class = 'box-body relative' . ($pay_type === AKSRT_PAY_TYPE_VIDEO ? ' dplayer-featured' : '');
|
||||||
|
|
||||||
|
// 付费后才展示的额外隐藏内容。整个函数只在有付费权限时才会走到这里,
|
||||||
|
// 因此无需再判断购买状态;HTML 由管理员在 metabox 里录入,已过 kses。
|
||||||
|
$pay_extra_hide = trim((string) ($meta['pay_extra_hide'] ?? ''));
|
||||||
|
$pay_extra_hide = $pay_extra_hide !== '' ? '<div class="pay-extra-hide">' . $pay_extra_hide . '</div>' : '';
|
||||||
|
|
||||||
return '<div class="pay-box zib-widget paid-box order-type-' . $order_type . '" id="posts-pay"' . $root_data . '>'
|
return '<div class="pay-box zib-widget paid-box order-type-' . $order_type . '" id="posts-pay"' . $root_data . '>'
|
||||||
. $header
|
. $header
|
||||||
. $paid_box
|
. $paid_box
|
||||||
@@ -1630,6 +1635,7 @@ if (!function_exists('aksrt_get_paid_box_html')) {
|
|||||||
. $count
|
. $count
|
||||||
. '<div' . $title_style . '><span class="badg c-red hollow badg-sm mr6">' . esc_html($type_label) . '</span><b>' . esc_html($title) . '</b></div>'
|
. '<div' . $title_style . '><span class="badg c-red hollow badg-sm mr6">' . esc_html($type_label) . '</span><b>' . esc_html($title) . '</b></div>'
|
||||||
. $download_box
|
. $download_box
|
||||||
|
. $pay_extra_hide
|
||||||
. $service
|
. $service
|
||||||
. '</div></div>';
|
. '</div></div>';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,7 +181,6 @@ class DomainModel {
|
|||||||
'video_pic' => '',
|
'video_pic' => '',
|
||||||
'video_title' => '',
|
'video_title' => '',
|
||||||
'video_episode' => [],
|
'video_episode' => [],
|
||||||
'video_scale_height' => 0,
|
|
||||||
'downloads' => [],
|
'downloads' => [],
|
||||||
'attributes' => [],
|
'attributes' => [],
|
||||||
'gallery' => [],
|
'gallery' => [],
|
||||||
@@ -194,9 +193,6 @@ class DomainModel {
|
|||||||
'require_captcha' => false,
|
'require_captcha' => false,
|
||||||
// §3.8 电商增强字段
|
// §3.8 电商增强字段
|
||||||
'virtual_sales' => 0,
|
'virtual_sales' => 0,
|
||||||
'stock' => -1,
|
|
||||||
'card_keys' => [],
|
|
||||||
'purchase_limit' => 0,
|
|
||||||
'free_preview' => '',
|
'free_preview' => '',
|
||||||
'show_sales' => true,
|
'show_sales' => true,
|
||||||
// legacy: free daily quota overbuy price (cash or points by pay_modo).
|
// legacy: free daily quota overbuy price (cash or points by pay_modo).
|
||||||
@@ -356,26 +352,6 @@ class DomainModel {
|
|||||||
return array_values(array_unique($gallery));
|
return array_values(array_unique($gallery));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sanitize card/key codes for auto-delivery.
|
|
||||||
* Each entry is a non-empty sanitized string (one code per line).
|
|
||||||
*/
|
|
||||||
public static function sanitize_card_keys($value): array {
|
|
||||||
if (!is_array($value)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$keys = [];
|
|
||||||
foreach ($value as $key) {
|
|
||||||
$key = sanitize_text_field((string) $key);
|
|
||||||
if ($key !== '') {
|
|
||||||
$keys[] = $key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $raw
|
* @param array<string, mixed> $raw
|
||||||
* @return array<string, mixed>
|
* @return array<string, mixed>
|
||||||
@@ -409,7 +385,6 @@ class DomainModel {
|
|||||||
$meta['video_pic'] = esc_url_raw((string) ($raw['video_pic'] ?? ''));
|
$meta['video_pic'] = esc_url_raw((string) ($raw['video_pic'] ?? ''));
|
||||||
$meta['video_title'] = sanitize_text_field((string) ($raw['video_title'] ?? ''));
|
$meta['video_title'] = sanitize_text_field((string) ($raw['video_title'] ?? ''));
|
||||||
$meta['video_episode'] = self::sanitize_video_episodes($raw['video_episode'] ?? []);
|
$meta['video_episode'] = self::sanitize_video_episodes($raw['video_episode'] ?? []);
|
||||||
$meta['video_scale_height'] = max(0, min(200, (int) ($raw['video_scale_height'] ?? 0)));
|
|
||||||
$meta['downloads'] = self::sanitize_downloads($raw['downloads'] ?? []);
|
$meta['downloads'] = self::sanitize_downloads($raw['downloads'] ?? []);
|
||||||
$meta['attributes'] = self::sanitize_attributes($raw['attributes'] ?? []);
|
$meta['attributes'] = self::sanitize_attributes($raw['attributes'] ?? []);
|
||||||
$meta['gallery'] = self::sanitize_gallery($raw['gallery'] ?? []);
|
$meta['gallery'] = self::sanitize_gallery($raw['gallery'] ?? []);
|
||||||
@@ -423,9 +398,6 @@ class DomainModel {
|
|||||||
|
|
||||||
// §3.8 电商增强字段
|
// §3.8 电商增强字段
|
||||||
$meta['virtual_sales'] = max(0, (int) ($raw['virtual_sales'] ?? 0));
|
$meta['virtual_sales'] = max(0, (int) ($raw['virtual_sales'] ?? 0));
|
||||||
$meta['stock'] = (int) ($raw['stock'] ?? -1);
|
|
||||||
$meta['card_keys'] = self::sanitize_card_keys($raw['card_keys'] ?? []);
|
|
||||||
$meta['purchase_limit'] = max(0, (int) ($raw['purchase_limit'] ?? 0));
|
|
||||||
$meta['free_preview'] = wp_kses_post((string) ($raw['free_preview'] ?? ''));
|
$meta['free_preview'] = wp_kses_post((string) ($raw['free_preview'] ?? ''));
|
||||||
$meta['show_sales'] = !isset($raw['show_sales']) || !empty($raw['show_sales']);
|
$meta['show_sales'] = !isset($raw['show_sales']) || !empty($raw['show_sales']);
|
||||||
$meta['download_limit_over_price'] = $meta['pay_modo'] === 'points'
|
$meta['download_limit_over_price'] = $meta['pay_modo'] === 'points'
|
||||||
|
|||||||
@@ -141,7 +141,6 @@ class ResourceMetaBox {
|
|||||||
<?php $this->upload('video_pic', __('视频封面(可选)', 'aksrt'), (string) ($meta['video_pic'] ?? ''), 'image'); ?>
|
<?php $this->upload('video_pic', __('视频封面(可选)', 'aksrt'), (string) ($meta['video_pic'] ?? ''), 'image'); ?>
|
||||||
<?php $this->text('video_title', __('本集标题', 'aksrt'), (string) ($meta['video_title'] ?? ''), __('如需添加剧集则需填写此处', 'aksrt'), __('第1集', 'aksrt')); ?>
|
<?php $this->text('video_title', __('本集标题', 'aksrt'), (string) ($meta['video_title'] ?? ''), __('如需添加剧集则需填写此处', 'aksrt'), __('第1集', 'aksrt')); ?>
|
||||||
<?php $this->group('video_episode', __('更多剧集', 'aksrt'), (array) ($meta['video_episode'] ?? []), 'video_row', __('添加剧集', 'aksrt'), __('为付费视频添加更多剧集。', 'aksrt')); ?>
|
<?php $this->group('video_episode', __('更多剧集', 'aksrt'), (array) ($meta['video_episode'] ?? []), 'video_row', __('添加剧集', 'aksrt'), __('为付费视频添加更多剧集。', 'aksrt')); ?>
|
||||||
<?php $this->number('video_scale_height', __('固定长宽比例', 'aksrt'), (string) ($meta['video_scale_height'] ?? 0), '5', '%', __('为 0 则不固定长宽比例。', 'aksrt')); ?>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-pay-type="download">
|
<div data-pay-type="download">
|
||||||
@@ -336,7 +335,6 @@ class ResourceMetaBox {
|
|||||||
'video_pic' => (string) ($raw['video_pic'] ?? ''),
|
'video_pic' => (string) ($raw['video_pic'] ?? ''),
|
||||||
'video_title' => (string) ($raw['video_title'] ?? ''),
|
'video_title' => (string) ($raw['video_title'] ?? ''),
|
||||||
'video_episode' => $raw['video_episode'] ?? [],
|
'video_episode' => $raw['video_episode'] ?? [],
|
||||||
'video_scale_height' => $raw['video_scale_height'] ?? 0,
|
|
||||||
'downloads' => $raw['downloads'] ?? [],
|
'downloads' => $raw['downloads'] ?? [],
|
||||||
'attributes' => $raw['attributes'] ?? [],
|
'attributes' => $raw['attributes'] ?? [],
|
||||||
'demo_url' => (string) ($raw['demo_url'] ?? ''),
|
'demo_url' => (string) ($raw['demo_url'] ?? ''),
|
||||||
|
|||||||
@@ -40,7 +40,11 @@ if (!$is_download) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$article_url = get_permalink($post) . '#posts-pay';
|
$article_url = get_permalink($post) . '#posts-pay';
|
||||||
$pay_title = get_the_title($post);
|
// 商品简介 / 更多详情 / 额外隐藏内容三个字段只在管理员填写时才有输出。
|
||||||
|
$pay_title = trim((string) ($pay_meta['pay_title'] ?? '')) !== '' ? (string) $pay_meta['pay_title'] : get_the_title($post);
|
||||||
|
$pay_doc = trim((string) ($pay_meta['pay_doc'] ?? ''));
|
||||||
|
$pay_details = trim((string) ($pay_meta['pay_details'] ?? ''));
|
||||||
|
$pay_extra_hide = trim((string) ($pay_meta['pay_extra_hide'] ?? ''));
|
||||||
$subtitle = '';
|
$subtitle = '';
|
||||||
if (function_exists('get_the_subtitle')) {
|
if (function_exists('get_the_subtitle')) {
|
||||||
// noop — AKSRT may not have legacy subtitle helper
|
// noop — AKSRT may not have legacy subtitle helper
|
||||||
@@ -115,6 +119,13 @@ get_header();
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if ($pay_doc !== '') : ?>
|
||||||
|
<div><?php echo wp_kses_post($pay_doc); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($pay_details !== '') : ?>
|
||||||
|
<div class="muted-2-color em09" style="margin:2em 0;"><?php echo wp_kses_post($pay_details); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if ($can_dl) : ?>
|
<?php if ($can_dl) : ?>
|
||||||
<div style="margin-bottom:2em;" class="pay-box">
|
<div style="margin-bottom:2em;" class="pay-box">
|
||||||
<?php
|
<?php
|
||||||
@@ -128,6 +139,9 @@ get_header();
|
|||||||
wp_reset_postdata();
|
wp_reset_postdata();
|
||||||
?>
|
?>
|
||||||
</div>
|
</div>
|
||||||
|
<?php if ($pay_extra_hide !== '') : ?>
|
||||||
|
<div class="pay-extra-hide"><?php echo wp_kses_post($pay_extra_hide); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
<?php elseif ($need_login) : ?>
|
<?php elseif ($need_login) : ?>
|
||||||
<div class="alert jb-yellow em12" style="margin:2em;">
|
<div class="alert jb-yellow em12" style="margin:2em;">
|
||||||
<b><?php echo ($price <= 0) ? esc_html__('免费资源,请登录后下载', 'aksrt') : esc_html__('请先登录后再下载', 'aksrt'); ?></b>
|
<b><?php echo ($price <= 0) ? esc_html__('免费资源,请登录后下载', 'aksrt') : esc_html__('请先登录后再下载', 'aksrt'); ?></b>
|
||||||
|
|||||||
@@ -249,7 +249,6 @@ test('article paid-content metabox follows the reference field set without shop
|
|||||||
'promotion_tag',
|
'promotion_tag',
|
||||||
'gallery_show',
|
'gallery_show',
|
||||||
'video_episode',
|
'video_episode',
|
||||||
'video_scale_height',
|
|
||||||
'downloads',
|
'downloads',
|
||||||
'attributes',
|
'attributes',
|
||||||
'pay_doc',
|
'pay_doc',
|
||||||
@@ -259,6 +258,10 @@ test('article paid-content metabox follows the reference field set without shop
|
|||||||
|
|
||||||
assert.match(meta, /add_meta_box\('aksrt_pay_meta', __\('付费功能'/);
|
assert.match(meta, /add_meta_box\('aksrt_pay_meta', __\('付费功能'/);
|
||||||
fields.forEach((field) => assert.match(meta, new RegExp(field)));
|
fields.forEach((field) => assert.match(meta, new RegExp(field)));
|
||||||
|
|
||||||
|
// video_scale_height 是参考主题轮播组件 widget 的参数,不属于付费视频字段,
|
||||||
|
// 当初误搬到付费 metabox 上且从未被消费,已移除。
|
||||||
|
assert.doesNotMatch(meta, /video_scale_height/);
|
||||||
assert.doesNotMatch(meta, /aksrt_pay_(?:stock|purchase_limit|card_keys|free_preview|require_login|require_captcha)/);
|
assert.doesNotMatch(meta, /aksrt_pay_(?:stock|purchase_limit|card_keys|free_preview|require_login|require_captcha)/);
|
||||||
assert.doesNotMatch(meta, /电商增强|parse_json_array/);
|
assert.doesNotMatch(meta, /电商增强|parse_json_array/);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user