Свободный вечер пятницы и жажда креатива заставили меня сделать дополнительное пользовательское свойство для инфоблоков – чекбокс.
Традиционно, хардкорные программисты реализуют функционал чекбокса с помощью строки, где хранится значение Y/N, или с помощью числа 0/1. Интеграторы со стажем используют свойство список с единственным элементом.
Первый подход мне не нравится, потому что он не юзер-ориентирован, а второй мне кажется слишком тяжеловесным. А еще хотелось бы работать с этим свойством как с полем "ACTIVE". Поэтому я решил сделать своё свойство с... ну вы знаете с чем
[spoiler]
Следующий код надо положить в какой-нибудь файл и заинклюдить его в init.php. Всё остальное он сделает сам.
Код так же доступен наhttps://github.com/alexxxnf/bitrix_prop_checkbox
Что имеем?
http://idea.1c-bitrix.ru/4146/ , http://idea.1c-bitrix.ru/3391/ .
Традиционно, хардкорные программисты реализуют функционал чекбокса с помощью строки, где хранится значение Y/N, или с помощью числа 0/1. Интеграторы со стажем используют свойство список с единственным элементом.
Первый подход мне не нравится, потому что он не юзер-ориентирован, а второй мне кажется слишком тяжеловесным. А еще хотелось бы работать с этим свойством как с полем "ACTIVE". Поэтому я решил сделать своё свойство с... ну вы знаете с чем
[spoiler]
Следующий код надо положить в какой-нибудь файл и заинклюдить его в init.php. Всё остальное он сделает сам.
Код так же доступен на
global $MESS; $MESS['IBLOCK_PROP_CHECKBOX_DESC'] = 'Флажок'; $MESS['IBLOCK_PROP_CHECKBOX_YES'] = 'Да'; $MESS['IBLOCK_PROP_CHECKBOX_NO'] = 'Нет'; $MESS['IBLOCK_PROP_CHECKBOX_NA'] = '(любой)'; class CIBlockPropertyCheckbox{ function GetUserTypeDescription(){ return array( 'PROPERTY_TYPE' => 'S', 'USER_TYPE' => 'Checkbox', 'DESCRIPTION' => GetMessage( 'IBLOCK_PROP_CHECKBOX_DESC' ), 'GetAdminListViewHTML' => array( 'CIBlockPropertyCheckbox', 'GetTextVal' ), 'GetPublicViewHTML' => array( 'CIBlockPropertyCheckbox', 'GetTextVal' ), 'GetPropertyFieldHtml' => array( 'CIBlockPropertyCheckbox', 'GetPropertyFieldHtml' ), 'AddFilterFields' => array( 'CIBlockPropertyCheckbox', 'AddFilterFields' ), 'GetPublicFilterHTML' => array( 'CIBlockPropertyCheckbox', 'GetFilterHTML' ), // It seems it doesn't work :( 'GetAdminFilterHTML' => array( 'CIBlockPropertyCheckbox', 'GetFilterHTML' ), 'ConvertToDB' => array( 'CIBlockPropertyCheckbox', 'ConvertToFromDB' ), 'ConvertFromDB' => array( 'CIBlockPropertyCheckbox', 'ConvertToFromDB' ), 'GetSearchContent' => array( 'CIBlockPropertyCheckbox', 'GetSearchContent' ), ); } function GetTextVal( $arProperty, $value, $strHTMLControlName ){ return $value['VALUE'] == 'Y' ? GetMessage( 'IBLOCK_PROP_CHECKBOX_YES' ) : GetMessage( 'IBLOCK_PROP_CHECKBOX_NO' ); } function GetPropertyFieldHtml( $arProperty, $value, $strHTMLControlName ){ return '<input type="checkbox" name="'.$strHTMLControlName['VALUE'].'" value="Y" '.( $value['VALUE'] == 'Y' ? 'checked="checked"' : '' ).'/>'; } function AddFilterFields( $arProperty, $strHTMLControlName, &$arFilter, &$filtered ){ if( isset( $_REQUEST[$strHTMLControlName['VALUE']] ) ){ $prefix = $_REQUEST[$strHTMLControlName['VALUE']] == 'Y' ? '=' : '!='; $arFilter[$prefix.'PROPERTY_'.$arProperty['ID']] = 'Y'; $filtered = TRUE; } } function GetFilterHTML( $arProperty, $strHTMLControlName ){ $select = '<select name="'.$strHTMLControlName['VALUE'].'"> <option value="" >'.GetMessage( 'IBLOCK_PROP_CHECKBOX_NA' ).'</option> <option value="Y" '.( $_REQUEST[$strHTMLControlName['VALUE']] == 'Y' ? 'selected="selected"' : '' ).'>'.GetMessage( 'IBLOCK_PROP_CHECKBOX_YES' ).'</option> <option value="N" '.( $_REQUEST[$strHTMLControlName['VALUE']] == 'N' ? 'selected="selected"' : '' ).'>'.GetMessage( 'IBLOCK_PROP_CHECKBOX_NO' ).'</option> </select>'; return $select; } function GetSearchContent( $arProperty, $value, $strHTMLControlName ){ $propId = $arProperty; // $arProperty contains property id, not array. // Is it bug in Bitrix, isn't it? $propParams = CIBlockProperty::GetByID( $propId )->Fetch(); return $value['VALUE'] == 'Y' ? $propParams['NAME'] : ''; } function ConvertToFromDB( $arProperty, $value ){ $value['VALUE'] = $value['VALUE'] == 'Y' ? 'Y' : 'N'; return $value; } function GetLength( $arProperty, $value ){ return 1; // checkbox is always filled } } AddEventHandler( 'iblock', 'OnIBlockPropertyBuildList', array( 'CIBlockPropertyCheckbox', 'GetUserTypeDescription' ) ); |
- По сути моё свойство – это обёртка над строкой, в базе оно сохраняется как "Y" и "N". Соответственно, для фильтрации через API надо использовать эти значения. Кроме того, везде, где можно, любые значения отличные от "Y" считаются за "N".
- Если разрешить поиск по этому свойству, то в индекс попадёт название свойства, а не значение. Ну действительно, зачем кому-то искать по букве "Y" ? Так что, если мы назовём свойство «горячее предложение», то в поиске по этой фразе найдутся все элементы, у которых установлен соответствующий флажок.
- Фильтр в публичной части выглядит, как текстовый инпут. В штатных свойствах «Дата/Время» и «Счетчик» можно подглядеть метод GetPublicFilterHTML, который, по-видимому, должен отвечать за внешний вид фильтров в публичке, однако Битрикс его нигде не использует, а жаль.
- Мне не захотелось оборачивать одно единственное свойство в модуль, потому что я не сторонник теории 1001 мелкого модуля. По этой причине свойство не удастся использовать на сайте с несколькими языками (хотя все языковые фразы я вынес в отдельный массив). Если кто-то задумает собрать модуль с пользовательскими свойствами, то я буду только рад, если моё творенье окажется там