add_action('wp_ajax_pm_get_products', 'pm_ajax_get_products'); function pm_ajax_get_products() { check_ajax_referer('pm_ajax_nonce', 'nonce'); $search = sanitize_text_field($_POST['search'] ?? ''); $category = sanitize_text_field($_POST['category'] ?? ''); $brand = sanitize_text_field($_POST['brand'] ?? ''); $tag = sanitize_text_field($_POST['tag'] ?? ''); $vendor = intval($_POST['vendor'] ?? 0); $stock_status = sanitize_text_field($_POST['stock_status'] ?? ''); $product_type = sanitize_text_field($_POST['product_type'] ?? ''); $page = max(1, intval($_POST['page'] ?? 1)); $per_page = intval($_POST['per_page'] ?? 50); // آرگومانهای پایه $args = array( 'post_status' => 'publish', 'posts_per_page' => $per_page, 'paged' => $page, // فقط از paged استفاده میکنیم 'meta_query' => array(), 'tax_query' => array(), 'orderby' => 'ID', 'order' => 'DESC', ); // ۱) تعیین نوع پست بر اساس فیلتر نوع محصول if (!empty($product_type) && in_array($product_type, array('simple', 'variable'))) { // فقط محصولات والد را نمایش میدهیم $args['post_type'] = 'product'; $args['meta_query'][] = array( 'key' => '_product_type', 'value' => $product_type, ); } else { // حالت "همه" - هم محصولات و هم تغییرات $args['post_type'] = array('product', 'product_variation'); } // ۲) فیلتر وضعیت موجودی if (!empty($stock_status)) { $args['meta_query'][] = array( 'key' => '_stock_status', 'value' => $stock_status, ); } // ۳) فیلتر فروشنده if ($vendor > 0) { $args['author'] = $vendor; } // ۴) جستجوی SKU و نام $search_ids = array(); if (!empty($search)) { // جستجوی SKU $search_sql_sku = $GLOBALS['wpdb']->prepare( "SELECT post_id FROM {$GLOBALS['wpdb']->postmeta} WHERE meta_key = '_sku' AND meta_value LIKE %s", '%' . $GLOBALS['wpdb']->esc_like($search) . '%' ); $sku_ids = $GLOBALS['wpdb']->get_col($search_sql_sku); // جستجوی عنوان $title_query = new WP_Query(array( 'post_type' => $args['post_type'], // استفاده از post_type تعیین شده 'post_status' => 'publish', 'posts_per_page' => -1, 'fields' => 'ids', 's' => $search, )); $search_ids = array_unique(array_merge($sku_ids, $title_query->posts)); if (empty($search_ids)) { $search_ids = array(0); // هیچ نتیجهای پیدا نشد } } // ۵) فیلترهای تاکسونومی (دسته، برند، تگ) $tax_term_ids = array(); $need_tax_filter = (!empty($category) || !empty($brand) || !empty($tag)); if ($need_tax_filter) { if (in_array('product', $args['post_type'])) { // حالت ۱: فقط محصولات والد - tax_query مستقیم if (!empty($category)) { $args['tax_query'][] = array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $category, ); } if (!empty($brand)) { $args['tax_query'][] = array( 'taxonomy' => 'product_brand', 'field' => 'slug', 'terms' => $brand, ); } if (!empty($tag)) { $args['tax_query'][] = array( 'taxonomy' => 'product_tag', 'field' => 'slug', 'terms' => $tag, ); } if (count($args['tax_query']) > 1) { $args['tax_query']['relation'] = 'AND'; } } else { // حالت ۲: شامل تغییرات - ابتدا والدها را پیدا میکنیم $parent_args = array( 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => -1, 'fields' => 'ids', 'tax_query' => array('relation' => 'AND'), ); if (!empty($category)) { $parent_args['tax_query'][] = array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => $category, ); } if (!empty($brand)) { $parent_args['tax_query'][] = array( 'taxonomy' => 'product_brand', 'field' => 'slug', 'terms' => $brand, ); } if (!empty($tag)) { $parent_args['tax_query'][] = array( 'taxonomy' => 'product_tag', 'field' => 'slug', 'terms' => $tag, ); } $parent_query = new WP_Query($parent_args); $parent_ids = $parent_query->posts; if (empty($parent_ids)) { wp_send_json(array('products' => [], 'total' => 0, 'pages' => 0)); } // تغییرات این والدها را اضافه میکنیم $variation_ids = get_posts(array( 'post_type' => 'product_variation', 'post_parent__in'=> $parent_ids, 'posts_per_page' => -1, 'fields' => 'ids', 'post_status' => 'publish', )); $tax_term_ids = array_merge($parent_ids, $variation_ids); } } // ۶) ترکیب نتایج جستجو و فیلترهای تاکسونومی $final_ids = array(); if (!empty($search_ids) && !empty($tax_term_ids)) { $final_ids = array_intersect($search_ids, $tax_term_ids); // تغییرات جستجو شده که والدشان در tax_term_ids باشد foreach ($search_ids as $id) { $post = get_post($id); if ($post && $post->post_type == 'product_variation' && in_array($post->post_parent, $tax_term_ids)) { $final_ids[] = $id; } } $final_ids = array_unique($final_ids); } elseif (!empty($search_ids)) { $final_ids = $search_ids; } elseif (!empty($tax_term_ids)) { $final_ids = $tax_term_ids; } // ۷) اگر نوع محصول انتخاب شده، مطمئن شویم فقط محصولات با آن نوع باقی بمانند if (!empty($product_type) && !empty($final_ids)) { $final_ids = get_posts(array( 'post_type' => 'product', 'post__in' => $final_ids, 'fields' => 'ids', 'posts_per_page' => -1, 'meta_query' => array( array('key' => '_product_type', 'value' => $product_type), ), )); } // ۸) اعمال فیلتر نهایی if (!empty($final_ids)) { $args['post__in'] = $final_ids ?: array(0); } // ۹) اجرای کوئری نهایی $query = new WP_Query($args); $products_data = array(); $start_num = ($page - 1) * $per_page; if ($query->have_posts()) { $i = $start_num; while ($query->have_posts()) { $query->the_post(); $i++; $product_id = get_the_ID(); $product = wc_get_product($product_id); if (!$product) continue; $sku = $product->get_sku(); $name = $product->get_name(); $thumb = $product->get_image(array(50, 50)); $permalink = get_permalink($product_id); if ($product->managing_stock()) { $stock_qty = $product->get_stock_quantity(); $stock_input = ''; } else { $stock_input = '---'; } $regular_price = $product->get_regular_price(); $sale_price = $product->get_sale_price(); $weight = $product->get_weight(); $length = $product->get_length(); $width = $product->get_width(); $height = $product->get_height(); $author_id = get_post_field('post_author', $product_id); $vendor_name = get_the_author_meta('display_name', $author_id); $products_data[] = array( 'id' => $product_id, 'row_num' => $i, 'thumb' => $thumb, 'sku' => $sku, 'name' => $name, 'permalink' => $permalink, 'stock_html' => $stock_input, 'regular' => $regular_price, 'sale' => $sale_price, 'weight' => $weight, 'length' => $length, 'width' => $width, 'height' => $height, 'vendor' => $vendor_name, ); } wp_reset_postdata(); } $total_products = $query->found_posts; $total_pages = ceil($total_products / $per_page); wp_send_json(array( 'products' => $products_data, 'total' => $total_products, 'pages' => $total_pages, )); }