Andrei | изменил логику конструктора товаров. Исключил дубли при двойном значении аттрибута, добавил проверку по полному совпадению категорий

web_10
parent f88fd2b39f
commit c732040f75
  1. 106
      wp-content/themes/cosmopet/modules/shop/CosmopetProduct.php
  2. 4
      wp-content/themes/cosmopet/views/woocommerce/single-product.twig

@ -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) : 'не массив'));
$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);
// Преобразуем в массив, если это PostCollection или PostQuery
if ($posts instanceof \Timber\PostCollection || $posts instanceof \Timber\PostQuery) {
$result = $posts->get_posts();
error_log("get_category_products: Преобразовано в массив: " . count($result));
return $result;
// Проверяем полное совпадение категорий
if (empty(array_diff($current_category_ids, $product_category_ids)) &&
empty(array_diff($product_category_ids, $current_category_ids))) {
$matching_products[] = $product;
}
}
// Добавляем текущий товар в начало массива
if ($current_product) {
array_unshift($matching_products, $current_product);
}
$result = is_array($posts) ? $posts : [];
error_log("get_category_products: Возвращаем: " . count($result));
return $result;
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;
}
}
// Сортируем итоговый конструктор по порядку таксономий

@ -183,12 +183,14 @@
<div class="product-constructor__block-list">
{% for option_id, option in attribute_data.options %}
{% set first_product = option.products[0] %}
{% if first_product.link %}
<a href="{{first_product.link}}" class="product-constructor__block-item{% if attribute_data.current_value == option.term_id %} active{% endif %}">
{% if option.icon %}
<img src="{{option.icon}}" alt="" class="product-constructor__block-item-icon{% if attribute_data.current_value == option.term_id %} active{% endif %} svg">
{% endif %}
<div class="product-constructor__block-item-name">{{option.name}}</div>
</a>
{% endif %}
{% endfor %}
</div>
</div>
@ -217,12 +219,14 @@
<div class="product-constructor__block-list">
{% for option_id, option in attribute_data.options %}
{% set first_product = option.products[0] %}
{% if first_product.link %}
<a href="{{first_product.link}}" class="product-constructor__block-item{% if attribute_data.current_value == option.term_id %} active{% endif %}">
{% if option.icon %}
<img src="{{option.icon}}" alt="" class="product-constructor__block-item-icon{% if attribute_data.current_value == option.term_id %} active{% endif %} svg">
{% endif %}
<div class="product-constructor__block-item-name">{{option.name}}</div>
</a>
{% endif %}
{% endfor %}
</div>
</div>

Loading…
Cancel
Save