Свободный вечер пятницы и жажда креатива заставили меня сделать дополнительное пользовательское свойство для инфоблоков – чекбокс.
Традиционно, хардкорные программисты реализуют функционал чекбокса с помощью строки, где хранится значение Y/N, или с помощью числа 0/1. Интеграторы со стажем используют свойство список с единственным элементом.
Первый подход мне не нравится, потому что он не юзер-ориентирован, а второй мне кажется слишком тяжеловесным. А еще хотелось бы работать с этим свойством как с полем "ACTIVE". Поэтому я решил сделать своё свойство с... ну вы знаете с чем
[spoiler]
Следующий код надо положить в какой-нибудь файл и заинклюдить его в init.php. Всё остальное он сделает сам.
Код так же доступен на
Что имеем?
Традиционно, хардкорные программисты реализуют функционал чекбокса с помощью строки, где хранится значение 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 мелкого модуля. По этой причине свойство не удастся использовать на сайте с несколькими языками (хотя все языковые фразы я вынес в отдельный массив). Если кто-то задумает собрать модуль с пользовательскими свойствами, то я буду только рад, если моё творенье окажется там
