вход   
 
 

весь список раздела "Модули, компоненты, файлы"


Пользовательский тип свойства инфоблока в виде списка разделов с чекбоксами для выбора.

Код нужно разместить в "local/php_interface/init.php" или "/bitrix/php_interface/init.php".
Для свойства надо выбрать тип "Привязка к разделам (список чекбоксов)". Обязательно должна быть отметка "Множественное".

php

// Регистрация кастомного свойства
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
    'iblock',
    'OnIBlockPropertyBuildList',
    ['CUserTypeSectionCheckboxes', 'GetUserTypeDescription']
);

class CUserTypeSectionCheckboxes
{
    public static function GetUserTypeDescription()
    {
        return [
            'PROPERTY_TYPE' => 'G', // Базовый тип "Привязка к разделам"
            'USER_TYPE' => 'SectionCheckboxes',
            'DESCRIPTION' => 'Привязка к разделам (список чекбоксов)',
            'CLASS_NAME' => __CLASS__,
            // Переопределяем вывод для множественного свойства
            'GetPropertyFieldHtmlMulty' => [__CLASS__, 'GetPropertyFieldHtmlMulty'],
            'GetPropertyFieldHtml' => [__CLASS__, 'GetPropertyFieldHtml'],
        ];
    }

    // Этот метод вызывается, если у свойства СНЯТ флаг "Множественное"
    public static function GetPropertyFieldHtml($arProperty, $arValue, $strHTMLControlName)
    {
        return self::renderCheckboxes($arProperty, [$arValue['VALUE']], $strHTMLControlName['VALUE']);
    }

    // Этот метод вызывается, если у свойства СТОИТ флаг "Множественное"
    public static function GetPropertyFieldHtmlMulty($arProperty, $arValues, $strHTMLControlName)
    {
        $selectedValues = [];
        if (is_array($arValues)) {
            foreach ($arValues as $val) {
                if (!empty($val['VALUE'])) {
                    $selectedValues[] = $val['VALUE'];
                }
            }
        }
        return self::renderCheckboxes($arProperty, $selectedValues, $strHTMLControlName['VALUE']);
    }

    // Общая функция отрисовки HTML
    private static function renderCheckboxes($arProperty, $arSelected, $inputName)
    {
        // Определяем, из какого инфоблока брать разделы. 
        // По умолчанию берется инфоблок, указанный в настройках связи свойства (LINK_IBLOCK_ID)
        // Если он пустой, берем текущий инфоблок свойства.
        $iblockId = intval($arProperty['LINK_IBLOCK_ID']) > 0 
            ? intval($arProperty['LINK_IBLOCK_ID']) 
            : intval($arProperty['IBLOCK_ID']);

        if ($iblockId <= 0) {
            return '<em>Ошибка: не задан ID инфоблока для связи.</em>';
        }

        // Получаем все разделы инфоблока с сохранением иерархии (сортировка по left_margin)
        $dbRes = \CIBlockSection::GetList(
            ['left_margin' => 'asc'],
            ['IBLOCK_ID' => $iblockId, 'ACTIVE' => 'Y'],
            false,
            ['ID', 'NAME', 'DEPTH_LEVEL']
        );

        $html = '<div style="max-height: 250px; min-width: 300px; overflow-y: auto; border: 1px solid #c8d1d6; padding: 8px; background: #fff; border-radius: 4px;">';
        
        // Скрытый input, чтобы при снятии всех чекбоксов Битрикс понимал, что свойство нужно очистить
        $html .= '<input type="hidden" name="'.$inputName.'[]" value="">';

        $hasSections = false;
        while ($arSection = $dbRes->Fetch()) {
            $hasSections = true;
            $checked = in_array($arSection['ID'], $arSelected) ? ' checked' : '';
            
            // Визуальный отступ для вложенных разделов
            $margin = ($arSection['DEPTH_LEVEL'] - 1) * 20;
            
            $html .= '<div style="margin-left: '.$margin.'px; margin-bottom: 5px; white-space: nowrap;">';
            $html .= '<label style="cursor: pointer; display: inline-flex; align-items: center; gap: 5px;">';
            $html .= '<input type="checkbox" name="'.$inputName.'[]" value="'.$arSection['ID'].'"'.$checked.'>';
            $html .= htmlspecialcharsbx($arSection['NAME']);
            $html .= '</label>';
            $html .= '</div>';
        }

        if (!$hasSections) {
            $html .= '<span style="color: #888;">В выбранном инфоблоке нет разделов.</span>';
        }

        $html .= '</div>';
        return $html;
    }
}