// /local/php_interface/init.php
use Bitrix\Main\EventManager;
use Bitrix\Main\Loader;
use Bitrix\Main\Application;
$eventManager = EventManager::getInstance();
// Отключаем все стандартные фильтры по наличию и ценам
$eventManager->addEventHandler('iblock', 'OnBeforeIBlockElementGetList', function(&$arFilter) {
// Удаляем все фильтры, связанные с каталогом (они будут мешать)
$keysToRemove = [
'CATALOG_AVAILABLE', 'AVAILABLE', '=CATALOG_AVAILABLE',
'CATALOG_PRICE_', '>CATALOG_PRICE_', '!=CATALOG_PRICE_'
];
foreach ($keysToRemove as $key) {
foreach (array_keys($arFilter) as $filterKey) {
if (strpos($filterKey, $key) === 0) {
unset($arFilter[$filterKey]);
}
}
}
});
// Отключаем проверку доступности через модуль каталога
$eventManager->addEventHandler('catalog', 'OnGetAvailableItems', function() {
return false;
});
// Продолжение в init.php
$eventManager->addEventHandler('iblock', 'OnAfterIBlockElementGetList', function(&$arResult) {
if (empty($arResult) || !Loader::includeModule('catalog') || !Loader::includeModule('sale')) {
return;
}
// Получаем текущего пользователя и его группы
global $USER;
$userId = $USER->GetID();
$userGroups = $USER->GetUserGroupArray();
// Определяем, какие типы цен доступны этим группам
$allowedPriceTypes = [];
// Способ 1: Через стандартные привязки типов цен к группам
$priceTypeRes = \Bitrix\Catalog\GroupTable::getList([
'select' => ['ID', 'NAME'],
'filter' => ['=GROUP_ACCESS.GROUP_ID' => $userGroups]
]);
while ($priceType = $priceTypeRes->fetch()) {
$allowedPriceTypes[] = (int)$priceType['ID'];
}
// Если нет привязок, берем все типы цен
if (empty($allowedPriceTypes)) {
$priceTypeRes = \Bitrix\Catalog\GroupTable::getList(['select' => ['ID']]);
while ($priceType = $priceTypeRes->fetch()) {
$allowedPriceTypes[] = (int)$priceType['ID'];
}
}
// Если все равно пусто - выходим
if (empty($allowedPriceTypes)) {
return;
}
// Собираем ID товаров из результата
$elementIds = [];
foreach ($arResult as $item) {
if (isset($item['ID'])) {
$elementIds[] = (int)$item['ID'];
}
}
if (empty($elementIds)) {
return;
}
// Получаем товары, у которых ЕСТЬ цены в доступных типах
$connection = Application::getConnection();
$sql = "
SELECT DISTINCT cp.PRODUCT_ID
FROM b_catalog_price cp
WHERE cp.PRODUCT_ID IN (" . implode(',', $elementIds) . ")
AND cp.CATALOG_GROUP_ID IN (" . implode(',', $allowedPriceTypes) . ")
AND cp.PRICE > 0
AND (cp.QUANTITY_FROM IS NULL OR cp.QUANTITY_FROM = 0)
AND (cp.QUANTITY_TO IS NULL OR cp.QUANTITY_TO = 0)
";
$result = $connection->query($sql);
$productsWithPrices = [];
while ($row = $result->fetch()) {
$productsWithPrices[(int)$row['PRODUCT_ID']] = true;
}
// Фильтруем результат - оставляем только товары с ценами
$filteredResult = [];
foreach ($arResult as $item) {
if (isset($item['ID']) && isset($productsWithPrices[(int)$item['ID']])) {
$filteredResult[] = $item;
}
}
$arResult = $filteredResult;
// Обновляем навигацию, если есть
if (isset($GLOBALS['NAV_RESULT']) && is_object($GLOBALS['NAV_RESULT'])) {
$GLOBALS['NAV_RESULT']->NavRecordCount = count($filteredResult);
$GLOBALS['NAV_RESULT']->SelectedRows = count($filteredResult);
}
});