# Интеграция с Bitrix — спецификация для backend-разработчика Это документ для человека, который не участвовал в разработке самого React-приложения (`portal-chart-builder`) и не обязан знать TypeScript — здесь только то, что нужно на стороне PHP/Bitrix. ## 1. Что это Конструктор диаграмм — отдельное React-приложение (не часть Bitrix24, продукт — «1С-Битрикс: Управление сайтом»). Встраивается как **пользовательский тип свойства инфоблока**: в админке, на странице редактирования элемента, вместо обычного поля отображается iframe с редактором диаграммы. Значение свойства — JSON-строка со схемой диаграммы, хранится как обычное строковое свойство (`PROPERTY_TYPE => 'S'`). Никакого REST-модуля, вебхуков или JS SDK Bitrix24 не требуется — это нативный механизм модуля `iblock`. ## 2. Регистрация типа свойства В `local/php_interface/init.php`: ```php AddEventHandler("iblock", "OnIBlockPropertyBuildList", ["DiagramProperty", "GetUserTypeDescription"]); ``` После регистрации новый тип появляется в **Контент → Инфоблоки → [нужный] → Свойства → Тип свойства**. Свойство должно быть **одиночным** (`MULTIPLE = N`) — одна диаграмма на элемент. ## 3. Скелет PHP-класса Ниже — иллюстративный каркас, не готовый к продакшену код. Реализация валидации, экранирования и т.д. — на усмотрение разработчика, но с обязательным соблюдением требований из раздела 5. ```php class DiagramProperty { public static function GetUserTypeDescription(): array { return [ 'PROPERTY_TYPE' => 'S', 'USER_TYPE' => 'DiagramEditor', 'DESCRIPTION' => 'Конструктор диаграмм процессов', 'GetPropertyFieldHtml' => [__CLASS__, 'GetPropertyFieldHtml'], 'ConvertToDB' => [__CLASS__, 'ConvertToDB'], 'ConvertFromDB' => [__CLASS__, 'ConvertFromDB'], ]; } public static function GetPropertyFieldHtml($arProperty, $value, $strHTMLControlName): string { $inputName = htmlspecialcharsbx($strHTMLControlName['VALUE']); $rawValue = $value['VALUE'] ?? ''; // JSON_HEX_* флаги обязательны — см. раздел 5. $jsValue = json_encode($rawValue, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT); // Вариант A — рекомендуемый, приложение лежит внутри дерева портала (см. раздел 7): // appOrigin — это просто origin текущего запроса, appUrl — конкретный файл. $appOrigin = (CMain::IsHTTPS() ? 'https://' : 'http://') . $_SERVER['HTTP_HOST']; $appUrl = $appOrigin . '/local/diagram-app/index.html'; // Вариант B — если приложение развёрнуто отдельным контейнером (см. раздел 7), // appUrl/appOrigin вместо этого указывают на его отдельный адрес, например: // $appOrigin = 'http://localhost:5178'; // $appUrl = $appOrigin; ob_start(); ?> } 5. Пользователь редактирует → с debounce ~400мс: Приложение → мост: { type: 'diagram:change', payload: '' } 6. Мост при каждом diagram:change пишет payload в value hidden input 7. Пользователь жмёт штатное «Сохранить» → браузер сабмитит форму → ConvertToDB → сохранение ``` Важно: `payload` в `diagram:change` — **уже сериализованная JSON-строка** (`JSON.stringify` со стороны приложения), не объект. Мост должен положить её в `input.value` как есть, без повторной обработки. `diagram:init` с `payload: null` (или пустой строкой) — валидный случай: новый элемент без диаграммы, приложение стартует с чистого холста. ## 5. Требования безопасности (обязательны, не опциональны) - При встраивании `initialValue` в инлайн-скрипт — **обязательно** `JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT` (см. пример в разделе 3). Без этого — риск XSS через выход из `