__('Mix and Match', 'yoone-product-bundles'), 'target' => 'yoone_bundle_data', 'class' => array('show_if_yoone_bundle'), // Only show for 'yoone_bundle' type 'priority' => 70, ); return $tabs; } public function render_product_data_panel() { global $post; $product = wc_get_product($post->ID); $config = Yoone_Product_Bundles::get_bundle_config($product); $allowed = $config['allowed_products']; $min_qty = $config['min_qty']; $cats = $config['categories']; echo '
'; wp_nonce_field('yoone-bundle-admin-nonce', 'yoone_bundle_admin_nonce_field'); echo '
'; echo '

' . esc_html__('Configure the simple products that can be included in the bundle, the minimum quantity, and the category grouping for the frontend display.', 'yoone-product-bundles') . '

'; // Allowed products: use Woo's product search (select2), multiple echo '

'; echo ''; // Search only for products, not variations, to avoid errors echo ''; echo '' . esc_html__('Only simple products are supported. Variable products may be supported in a future version.', 'yoone-product-bundles') . ''; echo '

'; // Minimum bundle quantity woocommerce_wp_text_input(array( 'id' => 'yoone_bundle_min_quantity', 'label' => __('Minimum Quantity', 'yoone-product-bundles'), 'type' => 'number', 'desc_tip' => true, 'description' => __('The total quantity of selected items must be greater than or equal to this value to add to the cart.', 'yoone-product-bundles'), 'value' => $min_qty, 'custom_attributes' => array('min' => '0'), )); // Display categories (product_cat) echo '

'; echo ''; echo '' . esc_html__('Group the allowed products by category on the frontend. Only products matching the selected categories will be shown.', 'yoone-product-bundles') . ''; echo '

'; echo '
'; // options_group echo '
'; // panel } public function save_product_meta($post_id) { // 无论当前 product 对象类型为何,只要提交了我们的字段,就进行保存。 // 这可以避免在首次切换产品类型时由于保存顺序问题导致配置未写入。 $has_fields = isset($_POST['yoone_bundle_allowed_products']) || isset($_POST['yoone_bundle_min_quantity']) || isset($_POST['yoone_bundle_categories']); if (! $has_fields) return; // 保存 allowed products $allowed = isset($_POST['yoone_bundle_allowed_products']) ? (array) $_POST['yoone_bundle_allowed_products'] : array(); $allowed = array_values(array_filter(array_map('absint', $allowed))); // 仅保留 simple 产品ID if (! empty($allowed)) { $simple_only = array(); foreach ($allowed as $aid) { $p = wc_get_product($aid); if ($p && $p->is_type('simple')) { $simple_only[] = $aid; } } $allowed = $simple_only; } update_post_meta($post_id, Yoone_Product_Bundles::META_ALLOWED_PRODUCTS, $allowed); // 保存 min qty $min_qty = isset($_POST['yoone_bundle_min_quantity']) ? absint($_POST['yoone_bundle_min_quantity']) : 0; update_post_meta($post_id, Yoone_Product_Bundles::META_MIN_QTY, max(0, $min_qty)); // 保存 categories $cats = isset($_POST['yoone_bundle_categories']) ? (array) $_POST['yoone_bundle_categories'] : array(); $cats = array_values(array_filter(array_map('absint', $cats))); update_post_meta($post_id, Yoone_Product_Bundles::META_CATEGORIES, $cats); } /** * AJAX handler: 获取所有已发布的 simple product */ public function ajax_get_all_simple_products() { if (! current_user_can('edit_products')) { wp_send_json_error('permission_denied', 403); } check_ajax_referer('yoone-bundle-admin-nonce', 'security'); $products = wc_get_products(array( 'type' => 'simple', 'status' => 'publish', 'limit' => -1, )); $results = array(); foreach ($products as $product) { $results[] = array( 'id' => $product->get_id(), 'text' => $product->get_formatted_name(), ); } wp_send_json_success($results); } }