Пример добавления кастомного типа для пользовательских полей
bitrixПример добавления кастомного типа данных для пользовательских полей #
Добавление типа "Привязка к элементам инфоблока с автодополнением" на основе свойства с одноименный типом. #
Ссылки на документацию #
https://dev.1c-bitrix.ru/api_d7/bitrix/main/userfield/uf-fieldclass.php
Расположение базовых типов #
- bitrix/modules/main/lib/userfield/types/enumtype.php
- bitrix/modules/main/lib/userfield/types/basetype.php
Расположение файл свойства у которого берем функционал #
- bitrix/modules/iblock/classes/general/prop_element_auto.php
Подключение класса в init.php #
Bitrix\Main\Loader::registerAutoLoadClasses(null, [
'lib\UserType\CUserTypeElementAutocomplete' => '/local/php_interface/lib/UserType/CUserTypeElementAutocomplete.php'
]);
AddEventHandler("main", "OnUserTypeBuildList", ["lib\UserType\CUserTypeElementAutocomplete", "GetUserTypeDescription"]);
Содержимое файла CUserTypeElementAutocomplete.php #
<?php
namespace lib\UserType;
use Bitrix\Main\Application;
use Bitrix\Main\Loader;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Type;
use Bitrix\Main\UserField\Types\EnumType;
use Bitrix\Iblock;
use CDBResult;
use CUserTypeManager;
use CIBlockElementEnum;
/**
* Class CUserTypeElementAutocomplete
* @package Bitrix\Main\UserField\Types
*/
class CUserTypeElementAutocomplete extends EnumType
{
public const
USER_TYPE_ID = 'iblock_element_autocomplete',
RENDER_COMPONENT = 'bitrix:iblock.field.element',
MODE_EDIT_FORM = 'main.edit_form';
protected static ?bool $iblockIncluded = null;
/**
* @return array
*/
public static function getDescription(): array
{
return [
'DESCRIPTION' => 'Привязка к элементам с автозаполнением',
'BASE_TYPE' => CUserTypeManager::BASE_TYPE_INT,
];
}
/**
* @param array $userField
* @return array
*/
public static function prepareSettings(array $userField): array
{
$height = (int)($userField['SETTINGS']['LIST_HEIGHT'] ?? 1);
$disp = ($userField['SETTINGS']['DISPLAY'] ?? '');
if ($disp !== static::DISPLAY_CHECKBOX && $disp !== static::DISPLAY_LIST)
{
$disp = static::DISPLAY_LIST;
}
$iblockId = (int)($userField['SETTINGS']['IBLOCK_ID'] ?? 0);
if($iblockId <= 0)
{
$iblockId = '';
}
$elementId = (int)($userField['SETTINGS']['DEFAULT_VALUE'] ?? 0);
if($elementId <= 0)
{
$elementId = '';
}
$activeFilter = (($userField['SETTINGS']['ACTIVE_FILTER'] ?? '') === 'Y' ? 'Y' : 'N');
return [
'DISPLAY' => $disp,
'LIST_HEIGHT' => (max($height, 1)),
'IBLOCK_ID' => $iblockId,
'DEFAULT_VALUE' => $elementId,
'ACTIVE_FILTER' => $activeFilter,
];
}
/**
* @param array $userField
* @return string|null
*/
public static function onSearchIndex(array $userField): ?string
{
$res = '';
if (!isset($userField['VALUE']))
{
return $res;
}
if (is_array($userField['VALUE']))
{
$val = $userField['VALUE'];
}
else
{
$val = [$userField['VALUE']];
}
Type\Collection::normalizeArrayValuesByInt($val);
if (!empty($val) && Loader::includeModule('iblock'))
{
$iterator = Iblock\ElementTable::getList([
'select' => [
'NAME',
],
'filter' => [
'@ID' => $val,
],
]);
while ($row = $iterator->fetch())
{
$res .= $row['NAME'] . "\r\n";
}
unset($row, $iterator);
}
unset($val);
return $res;
}
/**
* @param array $userField
* @return bool|CDBResult
*/
public static function getList(array $userField)
{
$iblockId = (int)($userField['SETTINGS']['IBLOCK_ID'] ?? 0);
$activeFilter = (string)($userField['SETTINGS']['ACTIVE_FILTER'] ?? 'N');
if (self::$iblockIncluded === null)
{
self::$iblockIncluded = Loader::includeModule('iblock');
}
if ($iblockId <= 0 || !self::$iblockIncluded)
{
return false;
}
$cacheTtl = 86400;
$iblockRights = self::getIblockRightsMode($iblockId, $cacheTtl);
if ($iblockRights === null)
{
return false;
}
$result = false;
$filter = [
'IBLOCK_ID' => $iblockId
];
if ($iblockRights === Iblock\IblockTable::RIGHTS_SIMPLE)
{
if ($activeFilter === 'Y')
{
$filter['=ACTIVE'] = 'Y';
}
$rows = [];
$elements = \Bitrix\Iblock\ElementTable::getList([
'select' => [
'ID',
'NAME',
],
'filter' => \CIBlockElement::getPublicElementsOrmFilter($filter),
'order' => [
'NAME' => 'ASC',
'ID' => 'ASC',
],
'cache' => [
'ttl' => $cacheTtl,
],
]);
while($element = $elements->fetch())
{
$rows[] = $element;
}
unset($elements);
if (!empty($rows))
{
$result = new \CIBlockElementEnum();
$result->InitFromArray($rows);
}
unset($rows);
}
else
{
$filter['CHECK_PERMISSIONS'] = 'Y';
$filter['MIN_PERMISSION'] = \CIBlockRights::PUBLIC_READ;
if ($activeFilter === 'Y')
{
$filter['ACTIVE'] = 'Y';
}
$result = \CIBlockElement::GetList(
[
'NAME' => 'ASC',
'ID' => 'ASC',
],
$filter,
false,
false,
[
'ID',
'NAME',
]
);
if($result)
{
$result = new \CIBlockElementEnum($result);
}
}
return $result;
}
/**
* @param array $userField
* @param array $additionalParameters
*/
public static function getEnumList(array &$userField, array $additionalParameters = []): void
{
if (self::$iblockIncluded === null)
{
self::$iblockIncluded = Loader::includeModule('iblock');
}
$userField['MANDATORY'] ??= 'N';
$userField['SETTINGS']['IBLOCK_ID'] ??= 0;
$userField['SETTINGS']['SHOW_NO_VALUE'] ??= 'Y';
$userField['SETTINGS']['DISPLAY'] ??= '';
$userField['SETTINGS']['ACTIVE_FILTER'] ??= 'N';
if (
!self::$iblockIncluded
|| (int)$userField['SETTINGS']['IBLOCK_ID']<= 0
)
{
return;
}
$result = [];
$showNoValue = (
$userField['MANDATORY'] !== 'Y'
|| $userField['SETTINGS']['SHOW_NO_VALUE'] !== 'N'
|| (
isset($additionalParameters['SHOW_NO_VALUE'])
&& $additionalParameters['SHOW_NO_VALUE'] === true
)
);
if (
$showNoValue
&& (
$userField['SETTINGS']['DISPLAY'] !== 'CHECKBOX'
|| $userField['MULTIPLE'] !== 'Y'
)
)
{
$result = [
null => static::getEmptyCaption($userField)
];
}
$filter = [];
if (isset($additionalParameters['CURRENT_VALUES']))
{
if (is_array($additionalParameters['CURRENT_VALUES']))
{
Type\Collection::normalizeArrayValuesByInt($additionalParameters['CURRENT_VALUES']);
}
else
{
$additionalParameters['CURRENT_VALUES'] = (int)$additionalParameters['CURRENT_VALUES'];
if ($additionalParameters['CURRENT_VALUES'] <= 0)
{
$additionalParameters['CURRENT_VALUES'] = null;
}
}
if (!empty($additionalParameters['CURRENT_VALUES']))
{
$filter['ID'] = $additionalParameters['CURRENT_VALUES'];
}
}
$filter['ACTIVE'] = $userField['SETTINGS']['ACTIVE_FILTER'] === 'Y';
$elements = self::getElements(
(int)$userField['SETTINGS']['IBLOCK_ID'],
$filter
);
if (!is_array($elements))
{
return;
}
if (!empty($additionalParameters['CURRENT_VALUES']))
{
$result = $elements;
}
else
{
$result = array_replace($result, $elements);
}
$userField['USER_TYPE']['FIELDS'] = $result;
}
public static function getDefaultValue(array $userField, array $additionalParameters = [])
{
$value = ($userField['SETTINGS']['DEFAULT_VALUE'] ?? '');
return ($userField['MULTIPLE'] === 'Y' ? [$value] : $value);
}
protected static function getElements(int $iblockId, array $additionalFilter = [])
{
if (self::$iblockIncluded === null)
{
self::$iblockIncluded = Loader::includeModule('iblock');
}
if ($iblockId <= 0 || !self::$iblockIncluded)
{
return false;
}
$cacheTtl = 86400;
$iblockRights = self::getIblockRightsMode($iblockId, $cacheTtl);
if ($iblockRights === null)
{
return false;
}
if ($iblockRights === Iblock\IblockTable::RIGHTS_SIMPLE)
{
$filter = ['IBLOCK_ID' => $iblockId];
if ($additionalFilter['ACTIVE'])
{
$filter['=ACTIVE'] = 'Y';
}
if (isset($additionalFilter['ID']))
{
$filter['@ID'] = $additionalFilter['ID'];
}
$result = [];
$elements = \Bitrix\Iblock\ElementTable::getList([
'select' => [
'ID',
'NAME',
],
'filter' => \CIBlockElement::getPublicElementsOrmFilter($filter),
'order' => [
'NAME' => 'ASC',
'ID' => 'ASC',
],
'cache' => [
'ttl' => $cacheTtl,
],
]);
while($element = $elements->fetch())
{
$result[$element['ID']] = $element['NAME'];
}
unset($element, $elements);
if (empty($result))
{
$result = false;
}
}
else
{
$filter = [
'IBLOCK_ID' => $iblockId,
'CHECK_PERMISSIONS' => 'Y',
'MIN_PERMISSION' => \CIBlockRights::PUBLIC_READ,
];
if ($additionalFilter['ACTIVE'])
{
$filter['ACTIVE'] = 'Y';
}
if (isset($additionalFilter['ID']))
{
$filter['ID'] = $additionalFilter['ID'];
}
$result = [];
$iterator = \CIBlockElement::GetList(
[
'NAME' => 'ASC',
'ID' => 'ASC',
],
$filter,
false,
false,
[
'ID',
'NAME',
]
);
while ($element = $iterator->Fetch())
{
$result[$element['ID']] = $element['NAME'];
}
unset($element, $iterator);
}
return $result;
}
private static function getIblockRightsMode(int $iblockId, int $cacheTtl): ?string
{
$iblock = Iblock\IblockTable::getRow([
'select' => [
'ID',
'RIGHTS_MODE',
],
'filter' => [
'=ID' => $iblockId
],
'cache' => [
'ttl' => $cacheTtl,
],
]);
return ($iblock['RIGHTS_MODE'] ?? null);
}
public static function renderEditForm(array $userField, ?array $additionalParameters): string
{
if($userField['MULTIPLE'] === 'N'){
return parent::renderEditForm($userField, $additionalParameters);
}
$enum = call_user_func([$userField['USER_TYPE']['CLASS_NAME'], 'getlist'], $userField);
if(!$enum)
{
return '';
}
$items = [];
while($item = $enum->GetNext())
{
$items[$item['ID']] = $item;
}
$additionalParameters['items'] = $items;
return self::renderEditFormCustom($userField, $additionalParameters);
}
public static function renderEditFormCustom(array $userField, ?array $additionalParameters): string
{
$additionalParameters['mode'] = self::MODE_EDIT_FORM;
$userField['USE_COMPONENT'] = 'Y';
return self::getHtmlCustom($userField, $additionalParameters);
}
private static function getHtmlCustom($userField, $additionalParameters): string
{
global $APPLICATION;
$arProperty = [
'ID' => $userField['ID'],
'LINK_IBLOCK_ID' => (int)$userField['SETTINGS']['IBLOCK_ID'],
];
$mxResultValue = static::GetValueForAutoCompleteMulti($arProperty,$additionalParameters);
$strResultValue = (is_array($mxResultValue) ? htmlspecialcharsback(implode("\n",$mxResultValue)) : '');
$strHTMLControlName["VALUE"] = $userField['FIELD_NAME'];
ob_start();
$fixIBlock = true;
$control_id = $APPLICATION->IncludeComponent(
"bitrix:main.lookup.input",
"iblockedit",
array(
"CONTROL_ID" => preg_replace(
"/[^a-zA-Z0-9_]/i",
"x",
$strHTMLControlName["VALUE"].'_'.mt_rand(0, 10000)
),
"INPUT_NAME" => $strHTMLControlName['VALUE'].'[]',
"INPUT_NAME_STRING" => "inp_".$strHTMLControlName['VALUE'],
"INPUT_VALUE_STRING" => $strResultValue,
"MULTIPLE" => $userField['MULTIPLE'],
"IBLOCK_ID" => (int)$userField['SETTINGS']['IBLOCK_ID'],
'WITHOUT_IBLOCK' => 'Y',
'FILTER' => 'Y'
), null, array("HIDE_ICONS" => "Y")
);
$APPLICATION->IncludeComponent(
'bitrix:main.tree.selector',
'iblockedit',
array(
"INPUT_NAME" => $strHTMLControlName['VALUE'],
'ONSELECT' => 'jsMLI_'.$control_id.'.SetValue',
'MULTIPLE' => $userField['MULTIPLE'],
'SHOW_INPUT' => 'N',
'SHOW_BUTTON' => 'Y',
'GET_FULL_INFO' => 'Y',
"START_TEXT" => Loc::getMessage("BT_UT_EAUTOCOMPLETE_MESS_LIST_INVITE"),
'BUTTON_CAPTION' => Loc::getMessage('BT_UT_EAUTOCOMPLETE_MESS_CHOOSE_ELEMENT'),
'BUTTON_TITLE' => Loc::getMessage('BT_UT_EAUTOCOMPLETE_MESS_CHOOSE_ELEMENT_MULTI_DESCR'),
"NO_SEARCH_RESULT_TEXT" => Loc::getMessage("BT_UT_EAUTOCOMPLETE_MESS_NO_SEARCH_RESULT_TEXT"),
"IBLOCK_ID" => (int)$userField['SETTINGS']['IBLOCK_ID'],
'WITHOUT_IBLOCK' => 'Y',
), null, array("HIDE_ICONS" => "Y")
);
return ob_get_clean();
}
public static function GetValueForAutoCompleteMulti($arProperty, $arValues, $arBanSym = '', $arRepSym = '')
{
$arResult = [];
if (is_array($arValues))
{
if (array_key_exists('VALUE', $arValues))
{
if (is_array($arValues['VALUE']))
{
$arValues = $arValues['VALUE'];
}
else
{
$arValues = [$arValues['VALUE']];
}
}
foreach ($arValues as $intPropertyValueID => $arOneValue)
{
if (!is_array($arOneValue))
{
$strTmp = $arOneValue;
$arOneValue = array(
'VALUE' => $strTmp,
);
}
$mxResult = static::GetPropertyValue($arProperty,$arOneValue);
if (is_array($mxResult))
{
$arResult[$intPropertyValueID] = htmlspecialcharsbx(str_replace($arBanSym,$arRepSym,$mxResult['~NAME'])).' ['.$mxResult['ID'].']';
}
}
}
return !empty($arResult) ? $arResult : false;
}
protected static function GetPropertyValue($arProperty, $arValue)
{
$mxResult = false;
if ((int)($arValue['VALUE'] ?? 0) > 0)
{
$mxResult = static::GetLinkElement((int)$arValue['VALUE'], (int)$arProperty['LINK_IBLOCK_ID']);
if (is_array($mxResult))
{
$mxResult['PROPERTY_ID'] = $arProperty['ID'];
if (isset($arProperty['PROPERTY_VALUE_ID']))
{
$mxResult['PROPERTY_VALUE_ID'] = $arProperty['PROPERTY_VALUE_ID'];
}
else
{
$mxResult['PROPERTY_VALUE_ID'] = false;
}
}
}
return $mxResult;
}
protected static function GetLinkElement($elementId, $iblockId)
{
static $cache = [];
$iblockId = (int)$iblockId;
if ($iblockId <= 0)
$iblockId = 0;
$elementId = (int)$elementId;
if ($elementId <= 0)
return false;
if (!isset($cache[$elementId]))
{
$arFilter = [];
if ($iblockId > 0)
$arFilter['IBLOCK_ID'] = $iblockId;
$arFilter['ID'] = $elementId;
$arFilter['SHOW_HISTORY'] = 'Y';
$rsElements = \CIBlockElement::GetList([], $arFilter, false, false, ['IBLOCK_ID','ID','NAME']);
if ($arElement = $rsElements->GetNext())
{
$arResult = array(
'ID' => $arElement['ID'],
'NAME' => $arElement['NAME'],
'~NAME' => $arElement['~NAME'],
'IBLOCK_ID' => $arElement['IBLOCK_ID'],
);
$cache[$elementId] = $arResult;
}
else
{
$cache[$elementId] = false;
}
}
return $cache[$elementId];
}
}
- Next: Принципы работы с git