Как создать собственный тип свойства в Bitrix

  • Необходимо привязаться к событию OnIBlockPropertyBuildList. Я сделаю это в своем модуле (как создать свой модуль или грамотно подвязываемая на события не засоряя init.php (ссылка будет позже))
  • EventManager::getInstance()->registerEventHandler(
                'iblock',
                'OnIBlockPropertyBuildList',
                'main',
                StructureCustomProperty::class,
                'GetUserTypeDescription'
            );

    Далее создаем класс

    class StructureCustomProperty
    {
        /**
         * Метод возвращает массив описания собственного типа свойств.
         *
         * @return array
         */
        public static function GetUserTypeDescription(): array
        {
            return [
                'USER_TYPE'            => 'BLOCKS',
                'DESCRIPTION'          => 'Блоки',
                'PROPERTY_TYPE'        => PropertyTable::TYPE_STRING,
                'GetPropertyFieldHtml' => [__CLASS__, 'getPropertyFieldHtml'],
                'ConvertToDB'          => [__CLASS__, 'convertToDB'],
            ];
        }
        /**
         * Метод возвращает html.Другими словами, визуал вашего свойства в админке.
         *
         * @return string
         */
        public static function getPropertyFieldHtml(array $arProperty, array $value, array $strHTMLControlName): string
        {
            global $APPLICATION;
            ob_start();
            // Тут может быть ваш html. Я вынес его в собственный компонент.Так более правильно
            $APPLICATION->IncludeComponent(
                'custom:custom-property',
                '.default',
                [
                    'ARRAY_VALUES'          => $value,
                    'ARRAY_PROPERTY'        => $arProperty,
                    'STR_HTML_CONTROL_NAME' => $strHTMLControlName,
                ]
            );
            
            return ob_get_clean();
        }
        
        /**
         * @param $arProperty
         * @param $value
         * @return int|null
         */
        public static function convertToDB($arProperty, $value): ?int
        {
            /** Удаление */
            if (!empty($value['VALUE']['REMOVED'])) {
                CIBlockElement::Delete($value['VALUE']['REMOVED']);
                return null;
            }
            
            /** Пропуск пустого шаблона */
            if (empty($value['VALUE']['NAME'])) {
                return null;
            }
            
            /** Создание или обновление */
            $linkIblockId  = (int)$arProperty['LINK_IBLOCK_ID'];
            $linkElementId = (int)$value['VALUE']['ELEMENT_ID'];
            
            if (!$linkElementId) {
                $linkElementId = self::addLinkElement($linkIblockId, $value['VALUE'] ?: []);
            } else {
                self::updateLinkElement($linkIblockId, $linkElementId, $value['VALUE'] ?: []);
            }
            
            return $linkElementId;
        }
        
        /**
         * @param int   $linkIblockId
         * @param array $value
         * @return int|null
         */
        private static function addLinkElement(int $linkIblockId, array $value): ?int
        {
            $newElement = new CIBlockElement();
            $properties = self::preparePropertyValues($value);
            
            $id = $newElement->Add(
                [
                    'IBLOCK_ID'       => $linkIblockId,
                    'NAME'            => $value['NAME'],
                    'ACTIVE'          => $value['ACTIVE'],
                    'SORT'            => $value['SORT'],
                    'PROPERTY_VALUES' => $properties,
                ]
            );
            
            return $id ?: null;
        }
        
        /**
         * @param int   $linkIblockId
         * @param int   $linkElementId
         * @param array $value
         * @return bool
         */
        private static function updateLinkElement(int $linkIblockId, int $linkElementId, array $value): bool
        {
            $properties = self::preparePropertyValues($value);
            $element    = new CIBlockElement();
            $fields     = [
                'NAME'        => $value['NAME'],
                'ACTIVE'      => $value['ACTIVE'] ?? 'N',
                'SORT'        => $value['SORT'],
                'TIMESTAMP_X' => new DateTime(),
            ];
            
            $element->Update($linkElementId, $fields);
            
            CIBlockElement::SetPropertyValuesEx($linkElementId, $linkIblockId, $properties);
            
            return true;
        }
        
        /**
         * @param array $value
         * @return array
         */
        private static function preparePropertyValues(array $value): array
        {
            $propertyValuesPrepared = [];
            
            foreach ($value['PROPERTIES'] ?? [] as $propertyCode => $propertyValue) {
                if (is_array($propertyValue)) {
                    foreach ($propertyValue as $propertyInnerValue) {
                        $propertyValuesPrepared[$propertyCode][]['VALUE'] = $propertyInnerValue;
                    }
                } else {
                    $propertyValuesPrepared [$propertyCode] = ['VALUE' => $propertyValue];
                }
            }
            
            return $propertyValuesPrepared;
        }
    }

    Как результат, в админке у вас появится возможность создать свойство с вашим типом

    Как пример, я использовал редактор json полей, а клиенту сделал удобный интерфейс

    Оставьте комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *