diff --git a/wp-content/themes/cosmopet/modules/shop/CosmopetProduct.php b/wp-content/themes/cosmopet/modules/shop/CosmopetProduct.php index 3868670..5fc5665 100644 --- a/wp-content/themes/cosmopet/modules/shop/CosmopetProduct.php +++ b/wp-content/themes/cosmopet/modules/shop/CosmopetProduct.php @@ -227,30 +227,66 @@ class CosmopetProduct extends TimberProduct { return $sorted_siblings; } - protected function get_category_products(){ - // Получаем все товары с похожими атрибутами + protected function get_category_products() { + // Получаем категории текущего товара + $current_product_categories = get_the_terms($this->id, 'product_cat'); + if (!$current_product_categories || is_wp_error($current_product_categories)) { + return []; + } + + $current_category_ids = array_map(function($cat) { + return $cat->term_id; + }, $current_product_categories); + + // Получаем текущий товар + $current_product = Timber::get_post($this->id); + + // Получаем ВСЕ товары $args = array( 'posts_per_page' => -1, 'post_type' => 'product', 'order' => 'ASC', 'orderby' => 'name', - 'post_status' => 'publish' + 'post_status' => 'publish', + 'tax_query' => [ + [ + 'taxonomy' => 'product_visibility', + 'field' => 'slug', + 'terms' => 'exclude-from-catalog', + 'operator' => 'NOT IN' + ] + ], + 'fields' => 'ids' // Получаем только ID товаров для оптимизации ); - error_log("get_category_products: Запрос товаров"); - $posts = Timber::get_posts($args); - error_log("get_category_products: Получено товаров: " . (is_array($posts) ? count($posts) : 'не массив')); - - // Преобразуем в массив, если это PostCollection или PostQuery - if ($posts instanceof \Timber\PostCollection || $posts instanceof \Timber\PostQuery) { - $result = $posts->get_posts(); - error_log("get_category_products: Преобразовано в массив: " . count($result)); - return $result; + $all_products = Timber::get_posts($args); + $matching_products = []; + + foreach ($all_products as $product) { + // Получаем категории товара + $product_categories = get_the_terms($product->ID, 'product_cat'); + if (!$product_categories || is_wp_error($product_categories)) { + continue; + } + + $product_category_ids = array_map(function($cat) { + return $cat->term_id; + }, $product_categories); + + // Проверяем полное совпадение категорий + if (empty(array_diff($current_category_ids, $product_category_ids)) && + empty(array_diff($product_category_ids, $current_category_ids))) { + $matching_products[] = $product; + } } - - $result = is_array($posts) ? $posts : []; - error_log("get_category_products: Возвращаем: " . count($result)); - return $result; + + // Добавляем текущий товар в начало массива + if ($current_product) { + array_unshift($matching_products, $current_product); + } + + error_log("get_category_products: Полное совпадение категорий. Найдено товаров: " . count($matching_products)); + return $matching_products; } public function getProductConstructor() { @@ -271,8 +307,6 @@ class CosmopetProduct extends TimberProduct { } } - - // Получаем упорядоченные таксономии $ordered_taxonomies = $this->getOrderedTaxonomies(); @@ -288,9 +322,13 @@ class CosmopetProduct extends TimberProduct { } } - // ОБХОДИМ МАССИВ ТОВАРОВ ТОЛЬКО ОДИН РАЗ + // Создаем массив для отслеживания уже добавленных товаров по таксономиям + $added_products = []; + foreach (array_keys($constructor) as $taxonomy) { + $added_products[$taxonomy] = []; + } + foreach ($all_products as $product) { - // Получаем все атрибуты сравниваемого товара за один раз $compare_attributes = []; $compare_weight = $product->getNumericWeight(); @@ -303,31 +341,25 @@ class CosmopetProduct extends TimberProduct { } } - // Проверяем, подходит ли товар для каждой таксономии + // Проверяем для каждой таксономии, куда можно добавить этот товар foreach ($this->sibling_categories as $taxonomy) { - // Пропускаем, если у текущего товара нет значения для этой категории - if (!isset($current_product_attributes[$taxonomy])) { + if (!isset($current_product_attributes[$taxonomy]) || + !isset($constructor[$taxonomy]) || + in_array($product->id, $added_products[$taxonomy])) { continue; } - // Проверяем, совпадают ли все остальные атрибуты и вес $attributes_match = true; - // Проверяем все атрибуты кроме текущей таксономии foreach ($this->sibling_categories as $compare_taxonomy) { - if ($compare_taxonomy === $taxonomy) { - continue; // Пропускаем проверяемую категорию - } + if ($compare_taxonomy === $taxonomy) continue; - // Если у текущего товара есть значение для этой категории if (isset($current_product_attributes[$compare_taxonomy])) { - // Проверяем, есть ли у сравниваемого товара значение для этой категории if (!isset($compare_attributes[$compare_taxonomy])) { $attributes_match = false; break; } - // Проверяем, совпадают ли значения $current_values = $current_product_attributes[$compare_taxonomy]; $compare_values = $compare_attributes[$compare_taxonomy]; @@ -336,10 +368,7 @@ class CosmopetProduct extends TimberProduct { $attributes_match = false; break; } - } - // Если у текущего товара НЕТ значения для этой категории, - // то у сравниваемого товара тоже не должно быть значения - else { + } else { if (isset($compare_attributes[$compare_taxonomy])) { $attributes_match = false; break; @@ -347,17 +376,16 @@ class CosmopetProduct extends TimberProduct { } } - // Проверяем вес (числовое сравнение) if (abs($current_weight - $compare_weight) > 0.01) { $attributes_match = false; } - // Если все атрибуты и вес совпадают, добавляем товар в группу if ($attributes_match) { $product_terms = get_the_terms($product->id, $taxonomy); if ($product_terms && !is_wp_error($product_terms)) { foreach ($product_terms as $term) { $option_key = $term->term_id; + if (!isset($constructor[$taxonomy]['options'][$option_key])) { $constructor[$taxonomy]['options'][$option_key] = [ 'term_id' => $term->term_id, @@ -367,7 +395,12 @@ class CosmopetProduct extends TimberProduct { 'products' => [] ]; } - $constructor[$taxonomy]['options'][$option_key]['products'][] = $product; + + // Добавляем товар только если его еще нет в этой опции + if (!in_array($product->id, $added_products[$taxonomy])) { + $constructor[$taxonomy]['options'][$option_key]['products'][] = $product; + $added_products[$taxonomy][] = $product->id; + } } } } @@ -385,7 +418,6 @@ class CosmopetProduct extends TimberProduct { } $constructor[$taxonomy]['options'] = $ordered_options; } - } // Сортируем итоговый конструктор по порядку таксономий diff --git a/wp-content/themes/cosmopet/views/woocommerce/single-product.twig b/wp-content/themes/cosmopet/views/woocommerce/single-product.twig index 36b1994..a30af3b 100644 --- a/wp-content/themes/cosmopet/views/woocommerce/single-product.twig +++ b/wp-content/themes/cosmopet/views/woocommerce/single-product.twig @@ -183,12 +183,14 @@