Add previewFilterGroupProducts AJAX handler

- Add case in handleEntitySelectorAjax switch for previewFilterGroupProducts
- Implement ajaxPreviewFilterGroupProducts() to get products by attribute/feature group
- Returns items with name, reference, manufacturer, image for popover preview

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-28 10:46:55 +00:00
parent 2988385acd
commit eb15170e1c

View File

@@ -263,6 +263,9 @@ trait EntitySelector
case 'getCategoryTree': case 'getCategoryTree':
$this->ajaxGetCategoryTree(); $this->ajaxGetCategoryTree();
return true; return true;
case 'previewFilterGroupProducts':
$this->ajaxPreviewFilterGroupProducts();
return true;
} }
return false; return false;
@@ -583,6 +586,109 @@ trait EntitySelector
} }
} }
/**
* AJAX: Preview products that have any value from a specific attribute or feature group
* Used by filter panel toggle buttons
*/
protected function ajaxPreviewFilterGroupProducts()
{
$groupId = (int) Tools::getValue('group_id');
$groupType = Tools::getValue('group_type'); // 'attribute' or 'feature'
$limit = (int) Tools::getValue('limit', 10);
if (!$groupId || !in_array($groupType, ['attribute', 'feature'])) {
die(json_encode([
'success' => false,
'error' => 'Invalid parameters'
]));
}
$idLang = (int) Context::getContext()->language->id;
$idShop = (int) Context::getContext()->shop->id;
try {
$db = Db::getInstance();
if ($groupType === 'attribute') {
// Get products with any attribute from this group
$sql = new DbQuery();
$sql->select('DISTINCT p.id_product');
$sql->from('product', 'p');
$sql->innerJoin('product_shop', 'ps', 'ps.id_product = p.id_product AND ps.id_shop = ' . $idShop);
$sql->innerJoin('product_attribute', 'pa', 'pa.id_product = p.id_product');
$sql->innerJoin('product_attribute_combination', 'pac', 'pac.id_product_attribute = pa.id_product_attribute');
$sql->innerJoin('attribute', 'a', 'a.id_attribute = pac.id_attribute AND a.id_attribute_group = ' . $groupId);
$sql->where('ps.active = 1');
} else {
// Get products with any feature value from this group
$sql = new DbQuery();
$sql->select('DISTINCT p.id_product');
$sql->from('product', 'p');
$sql->innerJoin('product_shop', 'ps', 'ps.id_product = p.id_product AND ps.id_shop = ' . $idShop);
$sql->innerJoin('feature_product', 'fp', 'fp.id_product = p.id_product');
$sql->innerJoin('feature_value', 'fv', 'fv.id_feature_value = fp.id_feature_value AND fv.id_feature = ' . $groupId);
$sql->where('ps.active = 1');
}
// Get total count first
$countSql = clone $sql;
$countResult = $db->executeS($countSql);
$totalCount = count($countResult);
// Get limited results for preview
$sql->limit($limit);
$results = $db->executeS($sql);
$productIds = array_column($results, 'id_product');
// Get product details for preview
$items = [];
if (!empty($productIds)) {
$productSql = new DbQuery();
$productSql->select('p.id_product, pl.name, p.reference, i.id_image, m.name as manufacturer');
$productSql->from('product', 'p');
$productSql->innerJoin('product_lang', 'pl', 'pl.id_product = p.id_product AND pl.id_lang = ' . $idLang . ' AND pl.id_shop = ' . $idShop);
$productSql->leftJoin('image', 'i', 'i.id_product = p.id_product AND i.cover = 1');
$productSql->leftJoin('manufacturer', 'm', 'm.id_manufacturer = p.id_manufacturer');
$productSql->where('p.id_product IN (' . implode(',', array_map('intval', $productIds)) . ')');
$productSql->limit($limit);
$products = $db->executeS($productSql);
foreach ($products as $product) {
$imageUrl = null;
if ($product['id_image']) {
$imageUrl = Context::getContext()->link->getImageLink(
Tools::link_rewrite($product['name']),
$product['id_product'] . '-' . $product['id_image'],
'small_default'
);
}
$items[] = [
'id' => (int) $product['id_product'],
'name' => $product['name'],
'reference' => $product['reference'],
'manufacturer' => $product['manufacturer'],
'image' => $imageUrl
];
}
}
die(json_encode([
'success' => true,
'items' => $items,
'count' => $totalCount,
'hasMore' => $totalCount > count($items)
]));
} catch (\Exception $e) {
die(json_encode([
'success' => false,
'error' => $e->getMessage()
]));
}
}
/** /**
* Apply modifiers (sort, limit) to product IDs * Apply modifiers (sort, limit) to product IDs
* Delegates to ProductConditionResolver * Delegates to ProductConditionResolver