[ 'name' => __('优惠活动', 'aksrt'), 'singular_name' => __('优惠活动', 'aksrt'), 'search_items' => __('搜索优惠活动', 'aksrt'), 'all_items' => __('所有优惠活动', 'aksrt'), 'edit_item' => __('编辑优惠活动', 'aksrt'), 'add_new_item' => __('新增优惠活动', 'aksrt'), 'menu_name' => __('优惠活动', 'aksrt'), ], 'public' => true, 'hierarchical' => false, 'show_ui' => $shop_show_ui, 'show_in_menu' => $shop_show_menu, 'show_in_rest' => true, 'show_admin_column' => true, 'rewrite' => ['slug' => 'shop-discount', 'with_front' => false], ]); } // ─── Term Meta Registration ────────────────────────────────── /** * Register all term meta fields for REST API exposure. */ public function register_term_meta_fields(): void { $auth = function () { return current_user_can('manage_categories'); }; // ── aksrt_product_cat ── $cat_fields = $this->get_cat_field_definitions(); foreach ($cat_fields as $key => $def) { register_term_meta('aksrt_product_cat', $key, [ 'type' => $def['type'], 'description' => $def['description'] ?? $key, 'single' => true, 'default' => $def['default'] ?? '', 'show_in_rest' => true, 'sanitize_callback' => $def['sanitize'] ?? 'sanitize_text_field', 'auth_callback' => $auth, ]); } // ── aksrt_product_tag ── $tag_fields = $this->get_tag_field_definitions(); foreach ($tag_fields as $key => $def) { register_term_meta('aksrt_product_tag', $key, [ 'type' => $def['type'], 'description' => $def['description'] ?? $key, 'single' => true, 'default' => $def['default'] ?? '', 'show_in_rest' => true, 'sanitize_callback' => $def['sanitize'] ?? 'sanitize_text_field', 'auth_callback' => $auth, ]); } // ── shop_discount ── $discount_fields = $this->get_discount_field_definitions(); foreach ($discount_fields as $key => $def) { register_term_meta('shop_discount', $key, [ 'type' => $def['type'], 'description' => $def['description'] ?? $key, 'single' => true, 'default' => $def['default'] ?? '', 'show_in_rest' => true, 'sanitize_callback' => $def['sanitize'] ?? 'sanitize_text_field', 'auth_callback' => $auth, ]); } } // ─── Field Definitions ─────────────────────────────────────── /** * Product category term meta field definitions. * * @return array */ private function get_cat_field_definitions(): array { return [ 'shop_cat_limit_buy' => [ 'type' => 'integer', 'description' => '分类级限购 (-1 不限)', 'default' => -1, 'sanitize' => function ($v) { return max(-1, min(9999, (int) $v)); }, ], 'shop_cat_shipping_fee' => [ 'type' => 'string', 'description' => '分类级运费类型', 'default' => '', 'sanitize' => function ($v) { $v = sanitize_key((string) $v); return in_array($v, ['', 'free', 'fixed', 'amount'], true) ? $v : ''; }, ], 'shop_cat_guest_buy' => [ 'type' => 'string', 'description' => '分类级免登录购买', 'default' => '', ], 'shop_cat_email_fill' => [ 'type' => 'string', 'description' => '分类级邮箱必留', 'default' => '', ], 'shop_cat_after_sale' => [ 'type' => 'string', 'description' => '分类级售后政策', 'default' => '', 'sanitize' => function ($v) { $v = sanitize_key((string) $v); return in_array($v, ['', 'refund', 'refund_return', 'none'], true) ? $v : ''; }, ], 'shop_cat_rebate' => [ 'type' => 'string', 'description' => '分类级返佣覆盖', 'default' => '', ], 'shop_cat_service' => [ 'type' => 'string', 'description' => '分类级服务保障', 'default' => '', 'sanitize' => 'sanitize_textarea_field', ], 'shop_cat_single_tab' => [ 'type' => 'string', 'description' => '分类级自定义 TAB', 'default' => '', 'sanitize' => 'sanitize_textarea_field', ], 'shop_cat_content_after' => [ 'type' => 'string', 'description' => '分类级详情页底部内容', 'default' => '', 'sanitize' => 'wp_kses_post', ], 'shop_cat_content_layout' => [ 'type' => 'string', 'description' => '分类级内容布局', 'default' => '', 'sanitize' => function ($v) { $v = sanitize_key((string) $v); return in_array($v, ['', 'adapt', 'full', 'sidebar'], true) ? $v : ''; }, ], 'shop_cat_content_show_bg' => [ 'type' => 'string', 'description' => '分类级详情背景盒子', 'default' => '', ], 'shop_cat_list_style' => [ 'type' => 'string', 'description' => '分类页列表样式', 'default' => '', 'sanitize' => function ($v) { $v = sanitize_key((string) $v); return in_array($v, ['', 'default', 'card-lg', 'card-sm'], true) ? $v : ''; }, ], ]; } /** * Product tag term meta field definitions. * * @return array */ private function get_tag_field_definitions(): array { return [ 'shop_tag_priority' => [ 'type' => 'integer', 'description' => '标签优先级(影响显示顺序)', 'default' => 0, 'sanitize' => function ($v) { return max(0, min(9999, (int) $v)); }, ], 'shop_tag_class' => [ 'type' => 'string', 'description' => '标签颜色 class', 'default' => '', 'sanitize' => 'sanitize_html_class', ], 'shop_tag_is_important' => [ 'type' => 'string', 'description' => '重点标签(商品价格位着重显示)', 'default' => '', ], ]; } /** * Shop discount term meta field definitions. * * @return array */ private function get_discount_field_definitions(): array { return [ 'shop_discount_small_badge' => [ 'type' => 'string', 'description' => '小标签文案', 'default' => '', ], 'shop_discount_priority' => [ 'type' => 'integer', 'description' => '优先级(数字越大越优先)', 'default' => 0, 'sanitize' => function ($v) { return max(0, min(9999, (int) $v)); }, ], 'shop_discount_is_important' => [ 'type' => 'string', 'description' => '重点活动', 'default' => '', ], 'shop_discount_important_class' => [ 'type' => 'string', 'description' => '重点活动背景色 class', 'default' => '', 'sanitize' => 'sanitize_html_class', ], 'shop_discount_scope' => [ 'type' => 'string', 'description' => '优惠范围', 'default' => 'item', 'sanitize' => function ($v) { $v = sanitize_key((string) $v); return in_array($v, ['item', 'product', 'author', 'order'], true) ? $v : 'item'; }, ], 'shop_discount_type' => [ 'type' => 'string', 'description' => '优惠类型', 'default' => 'reduction', 'sanitize' => function ($v) { $v = sanitize_key((string) $v); return in_array($v, ['reduction', 'discount', 'gift'], true) ? $v : 'reduction'; }, ], 'shop_discount_value' => [ 'type' => 'string', 'description' => '优惠数值(立减金额/折扣 0.01-9.99)', 'default' => '0', 'sanitize' => function ($v) { return sanitize_text_field((string) $v); }, ], 'shop_discount_gift_config' => [ 'type' => 'string', 'description' => '赠品配置 JSON', 'default' => '', 'sanitize' => 'sanitize_textarea_field', ], 'shop_discount_price_limit' => [ 'type' => 'string', 'description' => '金额门槛', 'default' => '0', 'sanitize' => function ($v) { return max(0, (float) $v); }, ], 'shop_discount_user_limit' => [ 'type' => 'string', 'description' => '用户身份限制', 'default' => '', 'sanitize' => function ($v) { $v = sanitize_key((string) $v); return in_array($v, ['', 'vip', 'vip_2', 'auth'], true) ? $v : ''; }, ], 'shop_discount_start' => [ 'type' => 'string', 'description' => '活动开始时间', 'default' => '', 'sanitize' => 'sanitize_text_field', ], 'shop_discount_end' => [ 'type' => 'string', 'description' => '活动结束时间', 'default' => '', 'sanitize' => 'sanitize_text_field', ], 'shop_discount_countdown' => [ 'type' => 'string', 'description' => '倒计时显示', 'default' => '', ], ]; } // ─── Getters ───────────────────────────────────────────────── /** * Get all shop term meta for a product category. * * @param int $term_id * @return array */ public static function get_cat_meta(int $term_id): array { $defaults = [ 'limit_buy' => -1, 'shipping_fee' => '', 'guest_buy' => '', 'email_fill' => '', 'after_sale' => '', 'rebate' => '', 'service' => '', 'single_tab' => '', 'content_after' => '', 'content_layout' => '', 'content_show_bg' => '', 'list_style' => '', ]; $result = []; foreach ($defaults as $key => $default) { $meta_key = "shop_cat_{$key}"; $val = get_term_meta($term_id, $meta_key, true); $result[$key] = ($val !== '' && $val !== false) ? $val : $default; } return $result; } /** * Get all shop term meta for a product tag. * * @param int $term_id * @return array */ public static function get_tag_meta(int $term_id): array { $priority = get_term_meta($term_id, 'shop_tag_priority', true); $class = get_term_meta($term_id, 'shop_tag_class', true); $is_important = get_term_meta($term_id, 'shop_tag_is_important', true); return [ 'priority' => $priority !== '' ? (int) $priority : 0, 'class' => is_string($class) ? $class : '', 'is_important' => !empty($is_important), ]; } /** * Get all shop discount term meta. * * @param int $term_id * @return array */ public static function get_discount_meta(int $term_id): array { $defaults = [ 'small_badge' => '', 'priority' => 0, 'is_important' => false, 'important_class' => '', 'scope' => 'item', 'type' => 'reduction', 'value' => '0', 'gift_config' => '', 'price_limit' => '0', 'user_limit' => '', 'start' => '', 'end' => '', 'countdown' => '', ]; $result = []; foreach ($defaults as $key => $default) { $meta_key = "shop_discount_{$key}"; $val = get_term_meta($term_id, $meta_key, true); $result[$key] = ($val !== '' && $val !== false) ? $val : $default; } $result['priority'] = (int) $result['priority']; $result['is_important'] = !empty($result['is_important']); $result['price_limit'] = (float) $result['price_limit']; return $result; } /** * Resolve parameter inheritance: product → category → theme settings. * * Returns the effective value for a given parameter key by checking: * 1. Product-level override (from post meta) * 2. Category-level override (from term meta) * 3. Theme-level default (from AKSRT_Settings::get_shop_settings()) * * @param int $product_id Product post ID * @param string $param_key Parameter key (e.g. 'limit_buy', 'shipping_fee') * @param mixed $product_value Product-level value (null if not set) * @return mixed */ public static function resolve_inheritance(int $product_id, string $param_key, $product_value = null) { // 1. Product-level override if ($product_value !== null && $product_value !== '' && $product_value !== -1) { return $product_value; } // 2. Category-level override $terms = get_the_terms($product_id, 'aksrt_product_cat'); if (is_array($terms) && !empty($terms)) { $cat_meta_key = "shop_cat_{$param_key}"; foreach ($terms as $term) { $val = get_term_meta($term->term_id, $cat_meta_key, true); if ($val !== '' && $val !== false && $val !== -1) { return $val; } } } // 3. Theme-level default $shop = AKSRT_Settings::get_shop_settings(); $defaults = $shop['product_defaults'] ?? []; return $defaults[$param_key] ?? $product_value; } }