Менеджеру нужен переход к разделам инфоблока из карточки товара, редактору — поле с проверкой служебного кода, оператору — дополнительная информация в заказе. Для этих задач в Битрикс есть разные точки расширения. Обычно достаточно дополнить штатную страницу через событие: добавить кнопку, вкладку, тип поля или блок.
Ниже разберу, какой способ подходит для каждой задачи и как его подключить. JavaScript нужен для поведения элементов в браузере, admin_header.php — для общего PHP-фрагмента, OnEndBufferContent — для изменения готовой разметки. Замену формы и отдельную административную страницу оставлю напоследок: к ним стоит переходить, если расширения штатного интерфейса недостаточно.
Каждый пример решает отдельную задачу и подключается самостоятельно. PHP-обработчики добавляются в /local/php_interface/init.php, если рядом с кодом не указан другой файл. В существующем PHP-файле повторный <?php не нужен. Значение 7 в условиях — ID инфоблока, который нужно заменить своим. Примеры интерфейсных дополнений ограничены администраторами; для других ролей проверку следует заменить проверкой разрешений на конкретный объект.
Добавить пункт в левое меню: OnBuildGlobalMenu
Пункт меню даёт постоянный вход в нужный раздел. Например, можно вынести разделы конкретного инфоблока в меню «Настройки». Событие OnBuildGlobalMenu позволяет дополнить массив модульных пунктов, сохранив существующее меню.
<?php
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'main', 'OnBuildGlobalMenu',
static function (&$globalMenu, &$moduleMenu): void {
if (!(isset($GLOBALS['USER']) && $GLOBALS['USER']->IsAdmin())) { return; }
$moduleMenu[] = [
'parent_menu' => 'global_menu_settings',
'section' => 'alexeslm_extension',
'sort' => 900,
'text' => 'Разделы каталога',
'title' => 'Открыть разделы каталога',
'url' => '/bitrix/admin/iblock_section_admin.php'
. '?IBLOCK_ID=7&type=content&lang='
. rawurlencode(LANGUAGE_ID),
'items_id' => 'menu_alexeslm_extension',
'items' => [],
];
}
);
В ссылке замените IBLOCK_ID=7 и type=content на ID и тип своего инфоблока. После подключения пункт появится в разделе «Настройки» у администратора. Создавать собственную страницу для такого перехода не требуется.
Добавить кнопку над формой: OnAdminContextMenuShow
Когда действие относится к открытому объекту, его удобнее разместить рядом с формой. Этот пример добавляет в карточку элемента кнопку перехода к разделам его инфоблока.
<?php
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'main', 'OnAdminContextMenuShow',
static function (&$items, &$additionalItems): void {
if (!isset($GLOBALS['USER']) || !$GLOBALS['USER']->IsAdmin()
|| !defined('ADMIN_SECTION') || ADMIN_SECTION !== true
|| $GLOBALS['APPLICATION']->GetCurPage() !== '/bitrix/admin/iblock_element_edit.php'
|| (int)($_GET['IBLOCK_ID'] ?? 0) !== 7) {
return;
}
$items[] = [
'TEXT' => 'Разделы инфоблока',
'LINK' => '/bitrix/admin/iblock_section_admin.php?IBLOCK_ID=7&type=content&lang='
. rawurlencode(LANGUAGE_ID),
];
}
);
Условие ограничивает кнопку одной формой и одним инфоблоком. Параметр type в ссылке также нужно заменить на тип своего инфоблока.
Добавить действие в меню строки: OnAdminListDisplay
Если действие выбирают для конкретной строки списка, используйте OnAdminListDisplay. Здесь к действиям элемента добавляется переход к его редактированию.
<?php
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'main', 'OnAdminListDisplay',
static function (&$list): void {
if (!isset($GLOBALS['USER']) || !$GLOBALS['USER']->IsAdmin()
|| !defined('ADMIN_SECTION') || ADMIN_SECTION !== true
|| $GLOBALS['APPLICATION']->GetCurPage() !== '/bitrix/admin/iblock_element_admin.php'
|| (int)($_GET['IBLOCK_ID'] ?? 0) !== 7) {
return;
}
foreach ($list->aRows as $row) {
$id = (int)($row->arRes['ID'] ?? 0);
if ($id <= 0) { continue; }
$url = '/bitrix/admin/iblock_element_edit.php?IBLOCK_ID=7&type=content&ID='
. $id . '&lang=' . rawurlencode(LANGUAGE_ID);
$actions = is_array($row->aActions) ? $row->aActions : [];
$actions[] = ['TEXT' => 'Открыть карточку', 'ACTION' => $list->ActionRedirect($url)];
$row->AddActions($actions);
}
}
);
AddActions() заменяет набор действий строки, поэтому сначала берём существующий aActions. В проекте таким же способом добавляется переход к связанному объекту или отчёту с ID строки. Пример относится к классическому административному списку.
Добавить кнопку в верхнюю панель сайта: OnPanelCreate
Верхняя панель в публичной части сайта — отдельный интерфейс. Если редактору нужен быстрый переход с сайта к списку контента, кнопку добавляют через OnPanelCreate, а не через событие контекстного меню административной формы.
<?php
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'main', 'OnPanelCreate',
static function (): void {
if (!isset($GLOBALS['USER']) || !$GLOBALS['USER']->IsAdmin()) { return; }
$GLOBALS['APPLICATION']->AddPanelButton([
'ID' => 'catalog_sections', 'TEXT' => 'Разделы каталога',
'HREF' => '/bitrix/admin/iblock_section_admin.php?IBLOCK_ID=7&type=content&lang='
. rawurlencode(LANGUAGE_ID),
'SORT' => 900,
]);
}
);
Добавить вкладку элемента или раздела инфоблока
Для связанных сведений, которым тесно рядом со штатными полями, подходят OnAdminIBlockElementEdit и OnAdminIBlockSectionEdit. Они подключают набор вкладок через CAdminTabEngine. Пример добавляет вкладку с ID открытого объекта.
<?php
final class ProjectIblockTab
{
public static function init(array $args)
{
if (!(isset($GLOBALS['USER']) && $GLOBALS['USER']->IsAdmin())) { return null; }
if (isset($args['IBLOCK'])
&& (int)$args['IBLOCK']['ID'] !== 7) {
return null;
}
return [
'TABSET' => 'alexeslm_info',
'GetTabs' => [self::class, 'tabs'],
'ShowTab' => [self::class, 'show'],
];
}
public static function tabs(array $args): array
{
return [[
'DIV' => 'info', 'TAB' => 'Сведения',
'TITLE' => 'Контекст открытого объекта',
]];
}
public static function show($div, array $args, $fromForm): void
{
if ($div !== 'info' || !(isset($GLOBALS['USER']) && $GLOBALS['USER']->IsAdmin())) { return; }
$id = (int)($args['ID'] ?? 0);
echo '<tr><td>ID:</td><td>'
. ($id > 0 ? $id : 'Новый объект: ID ещё нет')
. '</td></tr>';
}
}
foreach (['OnAdminIBlockElementEdit', 'OnAdminIBlockSectionEdit'] as $event) {
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'main', $event, [ProjectIblockTab::class, 'init']
);
}
Эти события регистрируются в модуле main. GetTabs возвращает описание вкладки, ShowTab печатает её содержимое. При создании объекта ID ещё нет. Для редактируемых данных одного HTML-поля недостаточно: нужны обработчики проверки и сохранения Check/Action либо штатное свойство инфоблока.
Дополнить существующий CAdminTabControl: OnAdminTabControlBegin
Если нужная форма построена на CAdminTabControl, её набор вкладок можно расширить через OnAdminTabControlBegin. Обработчик должен узнавать конкретную форму: имя контроллера и адрес страницы возьмите из её PHP-кода.
<?php
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'main', 'OnAdminTabControlBegin',
static function (&$control): void {
if (!isset($GLOBALS['USER']) || !$GLOBALS['USER']->IsAdmin()
|| !defined('ADMIN_SECTION') || ADMIN_SECTION !== true
|| $GLOBALS['APPLICATION']->GetCurPage() !== '/bitrix/admin/project_settings.php'
|| $control->name !== 'project_settings') {
return;
}
$control->tabs[] = [
'DIV' => 'project_help', 'TAB' => 'Памятка', 'TITLE' => 'Порядок изменения настроек',
'CONTENT' => '<tr><td colspan="2">Перед изменением сохраните текущие настройки.</td></tr>',
];
}
);
Здесь project_settings.php и project_settings обозначают страницу и контроллер, которые вы расширяете: замените оба значения. CONTENT выводится внутри таблицы, поэтому содержит <tr> и <td>. Для стандартной формы элемента инфоблока удобнее специальные события из предыдущего раздела.
Создать тип свойства инфоблока: OnIBlockPropertyBuildList
Для значения товара или другого элемента инфоблока используйте пользовательский тип свойства. Пример «Служебный код» принимает латинские буквы, цифры, дефис и подчёркивание, ограничивает длину 32 символами и приводит значение к верхнему регистру.
<?php
final class ProjectCodeProperty
{
public static function description(): array
{
return [
'PROPERTY_TYPE' => 'S', 'USER_TYPE' => 'alexeslm_code',
'DESCRIPTION' => 'Служебный код',
'GetPropertyFieldHtml' => [self::class, 'input'],
'GetAdminListViewHTML' => [self::class, 'view'],
'CheckFields' => [self::class, 'check'],
'ConvertToDB' => [self::class, 'toDb'],
'GetLength' => [self::class, 'length'],
];
}
public static function input($property, $value, $control): string
{
return self::renderInput($control['VALUE'], $value['VALUE'] ?? '');
}
public static function view($property, $value, $control): string
{
return self::escape($value['VALUE'] ?? '');
}
public static function check($property, $value): array
{
return self::valid($value['VALUE'] ?? null) ? []
: ['Код: до 32 латинских букв, цифр, дефисов или подчёркиваний.'];
}
public static function toDb($property, $value): array
{
$value['VALUE'] = self::normalize($value['VALUE'] ?? '');
return $value;
}
public static function length($property, $value): int
{
return strlen(self::normalize($value['VALUE'] ?? ''));
}
public static function normalize($value): string
{
return is_scalar($value) ? strtoupper(trim((string)$value)) : '';
}
public static function valid($value): bool
{
if (!is_scalar($value) && $value !== null) { return false; }
$value = self::normalize($value);
return $value === ''
|| preg_match('/\A[A-Z0-9_-]{1,32}\z/', $value) === 1;
}
private static function renderInput($name, $value): string
{
return '<input type="text" size="32" maxlength="32" name="'
. self::escape($name) . '" value="'
. self::escape($value) . '" placeholder="SKU-001">';
}
private static function escape($value): string
{
return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
}
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'iblock', 'OnIBlockPropertyBuildList', [ProjectCodeProperty::class, 'description']
);
После подключения выберите тип «Служебный код» при создании свойства инфоблока. Ввод sku-001 сохраняется как SKU-001; кириллица и строка длиннее 32 символов отклоняются. Пустое значение допускает сам тип, а обязательность задаётся в настройках поля. HTML-экранирование защищает вывод значения и имени поля.
Создать тип пользовательского поля: OnUserTypeBuildList
Если данные принадлежат сущности с полями UF_*, нужен пользовательский тип поля, а не свойство инфоблока. Например, для служебного кода пользователя можно создать поле UF_SERVICE_CODE. Этот пример сам содержит вывод, проверку и нормализацию значения.
<?php
final class ProjectCodeUserField
{
public static function description(): array
{
return [
'USER_TYPE_ID' => 'alexeslm_code',
'CLASS_NAME' => self::class,
'DESCRIPTION' => 'Служебный код', 'BASE_TYPE' => 'string',
];
}
public static function GetDBColumnType($field): string
{
return 'varchar(32)'; // MySQL, одиночное значение.
}
public static function GetEditFormHTML($field, $control): string
{
return self::renderInput($control['NAME'], $control['VALUE'] ?? '');
}
public static function GetAdminListViewHTML($field, $control): string
{
return self::escape($control['VALUE'] ?? '');
}
public static function CheckFields($field, $value): array
{
return self::valid($value) ? [] : [[
'id' => $field['FIELD_NAME'],
'text' => 'Код: до 32 латинских букв, цифр, дефисов или подчёркиваний.',
]];
}
public static function OnBeforeSave($field, $value): string
{
return self::normalize($value);
}
public static function normalize($value): string
{
return is_scalar($value) ? strtoupper(trim((string)$value)) : '';
}
public static function valid($value): bool
{
if (!is_scalar($value) && $value !== null) { return false; }
$value = self::normalize($value);
return $value === ''
|| preg_match('/\A[A-Z0-9_-]{1,32}\z/', $value) === 1;
}
private static function renderInput($name, $value): string
{
return '<input type="text" size="32" maxlength="32" name="'
. self::escape($name) . '" value="'
. self::escape($value) . '" placeholder="SKU-001">';
}
private static function escape($value): string
{
return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
}
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'main', 'OnUserTypeBuildList', [ProjectCodeUserField::class, 'description']
);
После подключения выберите тип «Служебный код» при создании пользовательского поля. Реализация рассчитана на одиночное строковое поле в MySQL. Ввод sku-001 сохраняется как SKU-001; кириллица и строка длиннее 32 символов отклоняются. Пустое значение допускает сам тип, а обязательность задаётся в настройках поля. HTML-экранирование защищает вывод значения и имени поля.
Добавить настройку использования свойства: OnPropertyFeatureBuildList
Признак свойства нужен, когда существующее поле требуется пометить для дополнительного сценария: например, включать его в выгрузку. Это настройка самого свойства, а не новый тип вводимого значения.
<?php
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'iblock', 'Bitrix\Iblock\Model\PropertyFeature::OnPropertyFeatureBuildList',
static function (\Bitrix\Main\Event $event): \Bitrix\Main\EventResult {
$property = $event->getParameter('property');
$features = (int)($property['IBLOCK_ID'] ?? 0) === 7
? [['MODULE_ID' => 'main', 'FEATURE_ID' => 'PROJECT_EXPORT',
'FEATURE_NAME' => 'Участвует в выгрузке проекта']]
: [];
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, $features);
}
);
При включённом механизме расширенных свойств появится дополнительный признак. Код выгрузки должен отдельно читать и учитывать его: одна регистрация признака выгрузку не реализует. Здесь используется D7-событие с полным именем класса и параметром property в нижнем регистре.
Показать строку в информационном блоке заказа
Для короткого значения — внутреннего номера или статуса внешней системы — подходит sale:onSaleAdminOrderInfoBlockShow. Обработчик возвращает пары TITLE/VALUE; отдельная вкладка для такой строки не нужна.
<?php
use Bitrix\Main\{Event, EventResult};
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'sale', 'onSaleAdminOrderInfoBlockShow',
static function (Event $event): EventResult {
if (!(isset($GLOBALS['USER']) && $GLOBALS['USER']->IsAdmin())) {
return new EventResult(EventResult::SUCCESS, []);
}
$order = $event->getParameter('ORDER');
$id = $order ? (int)$order->getId() : 0;
return new EventResult(EventResult::SUCCESS, [[
'TITLE' => 'Внутренний ID',
'VALUE' => $id > 0 ? (string)$id : 'Ещё не присвоен',
]]);
}
);
Добавить перемещаемый блок в карточку заказа
Для нескольких связанных сведений или памятки оператору удобен отдельный блок. События OnAdminSaleOrderViewDraggable, OnAdminSaleOrderEditDraggable и OnAdminSaleOrderCreateDraggable подключают его соответственно при просмотре, редактировании и создании заказа.
<?php
final class ProjectOrderBlock
{
public static function init(array $args = [])
{
if (!(isset($GLOBALS['USER']) && $GLOBALS['USER']->IsAdmin())) { return null; }
return [
'BLOCKSET' => 'alexeslm_order',
'getBlocksBrief' => [self::class, 'brief'],
'getBlockContent' => [self::class, 'content'],
];
}
public static function brief(array $args): array
{
return ['alexeslm_order_note' => ['TITLE' => 'Перед передачей заказа']];
}
public static function content($code, $selectedTab, array $args): string
{
if ($code !== 'alexeslm_order_note' || !(isset($GLOBALS['USER']) && $GLOBALS['USER']->IsAdmin())) { return ''; }
$order = $args['ORDER'] ?? null;
$id = $order ? (int)$order->getId() : 0;
return '<div class="adm-info-message">'
. ($id > 0 ? 'Заказ №' . $id : 'Заказ пока не сохранён')
. '. Проверьте контактные данные и способ доставки.</div>';
}
}
foreach (['OnAdminSaleOrderViewDraggable', 'OnAdminSaleOrderEditDraggable',
'OnAdminSaleOrderCreateDraggable'] as $event) {
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'main', $event, [ProjectOrderBlock::class, 'init']
);
}
getBlocksBrief описывает блок, getBlockContent возвращает HTML. У нового заказа может ещё не быть ID. События движка блоков регистрируются в main, хотя сама карточка относится к модулю продаж.
Добавить отдельную вкладку заказа
Вкладка подходит для сведений, которые нужно вынести за пределы основного экрана заказа: например, регламента обработки или истории обмена. Для этого служат OnAdminSaleOrderView, OnAdminSaleOrderEdit и OnAdminSaleOrderCreate. Ниже — самостоятельная вкладка с памяткой.
<?php
final class ProjectOrderTab
{
public static function init(array $args)
{
if (!isset($GLOBALS['USER']) || !$GLOBALS['USER']->IsAdmin()) { return null; }
return ['TABSET' => 'project_order_help',
'GetTabs' => [self::class, 'tabs'], 'ShowTab' => [self::class, 'show']];
}
public static function tabs(array $args): array
{
return [['DIV' => 'help', 'TAB' => 'Памятка', 'TITLE' => 'Перед передачей заказа']];
}
public static function show($div, array $args, $fromForm): void
{
if ($div !== 'help' || !isset($GLOBALS['USER']) || !$GLOBALS['USER']->IsAdmin()) { return; }
echo '<tr><td colspan="2">Проверьте контактные данные и способ доставки.</td></tr>';
}
}
foreach (['OnAdminSaleOrderView', 'OnAdminSaleOrderEdit', 'OnAdminSaleOrderCreate'] as $event) {
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'main', $event, [ProjectOrderTab::class, 'init']
);
}
Вкладка использует CAdminTabEngine; её события также относятся к main. Пример только выводит информацию. Если разместить здесь поля, обработку и сохранение их значений нужно реализовать отдельно.
Подключить JavaScript для поведения элементов формы
JavaScript подходит для раскрытия пояснений, переключения видимости полей и реакции на действия пользователя. PHP по-прежнему проверяет и сохраняет данные. Подключим скрипт только в форме элемента нужного инфоблока через OnEpilog и Asset::addJs().
<?php
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'main', 'OnEpilog',
static function (): void {
if (isset($GLOBALS['USER']) && $GLOBALS['USER']->IsAdmin()
&& defined('ADMIN_SECTION') && ADMIN_SECTION === true
&& $GLOBALS['APPLICATION']->GetCurPage() === '/bitrix/admin/iblock_element_edit.php'
&& (int)($_GET['IBLOCK_ID'] ?? 0) === 7) {
\Bitrix\Main\Page\Asset::getInstance()->addJs('/local/js/admin-help.js');
}
}
);
В HTML своего поля или вкладки разместите кнопку и пояснение. Если строка выводится внутри таблицы административной формы, её содержимое нужно поместить в <tr><td>.
<button type="button" data-admin-extension-toggle aria-expanded="false"
aria-controls="admin-extension-help">Показать пояснение</button>
<p id="admin-extension-help" hidden>Служебный код используется при обмене с внешней системой.</p>
Содержимое /local/js/admin-help.js:
(() => {
if (window.alexeslmAdminExtensionBound) return;
window.alexeslmAdminExtensionBound = true;
document.addEventListener('click', (event) => {
const button = event.target instanceof Element
? event.target.closest('[data-admin-extension-toggle]') : null;
if (!button) return;
const help = document.getElementById(button.getAttribute('aria-controls'));
if (!help) return;
const expanded = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!expanded));
button.textContent = expanded ? 'Показать пояснение' : 'Скрыть пояснение';
help.hidden = expanded;
});
})();
Скрипт меняет hidden и aria-expanded. Делегирование клика позволяет обработать и элементы, добавленные после загрузки страницы. OnEpilog здесь регистрирует ресурс, а не печатает <script> после готового документа.
Вывести общий PHP-фрагмент через admin_header.php
Если сообщение должно появляться перед содержимым административных страниц, можно использовать /local/php_interface/admin_header.php. В примере уведомление ограничено формой редактирования элементов одного инфоблока. Добавьте фрагмент в существующий файл, сохранив его содержимое.
<?php
if (isset($GLOBALS['USER']) && $GLOBALS['USER']->IsAdmin()
&& $GLOBALS['APPLICATION']->GetCurPage() === '/bitrix/admin/iblock_element_edit.php'
&& (int)($_GET['IBLOCK_ID'] ?? 0) === 7) {
echo '<div class="adm-info-message">Изменения каталога попадут в следующую выгрузку.</div>';
}
Это подключаемый PHP-файл, а не событие. Он подходит для общего сообщения, но не заменяет API вкладок, кнопок и типов полей.
Изменить готовый HTML через OnEndBufferContent
Если подходящего события для элемента нет, остаётся обработка выходного буфера. Например, код ниже заменяет HTML-маркер, который уже выводится вашим шаблоном формы. Этот способ зависит от разметки, поэтому сначала стоит проверить штатные точки расширения.
<?php
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'main', 'OnEndBufferContent',
static function (&$content): void {
if (!isset($GLOBALS['USER']) || !$GLOBALS['USER']->IsAdmin()
|| !defined('ADMIN_SECTION') || ADMIN_SECTION !== true
|| $GLOBALS['APPLICATION']->GetCurPage() !== '/bitrix/admin/iblock_element_edit.php'
|| (int)($_GET['IBLOCK_ID'] ?? 0) !== 7
|| ($_SERVER['REQUEST_METHOD'] ?? '') !== 'GET'
|| stripos($content, '</html>') === false) {
return;
}
$content = str_replace('<!--PROJECT_CATALOG_NOTE-->',
'<p class="adm-info-message">Проверьте данные перед выгрузкой.</p>', $content);
}
);
Маркер <!--PROJECT_CATALOG_NOTE--> должен присутствовать в исходном HTML; без него замены не будет. Буфер передаётся по ссылке. Условия ограничивают обработчик полной HTML-страницей выбранной формы и не предназначены для AJAX-ответов.
Заменить форму элемента через EDIT_FILE_AFTER
Если настройки формы, вкладок и типов свойств недостаточно, для инфоблока можно указать собственную форму редактирования. Это уже замена интерфейса: поддержку его поведения и совместимости придётся брать на себя.
В настройках инфоблока укажите путь в параметре EDIT_FILE_AFTER, например /local/admin/catalog_element_form.php. За основу возьмите действующую форму из установленного ядра, разберите её зависимости и сохраните обработку полей, проверку прав, сессии и ошибок. Файл подключается штатной страницей редактирования после обработки данных: он не является самостоятельным обработчиком сохранения. Ветка пользовательской формы отличается от штатной в том числе проверкой сессии, поэтому нельзя ограничиться копированием HTML: проверку запроса нужно сохранить в обработке до записи данных.
Универсального короткого кода для полной замены нет: содержимое зависит от полей конкретного инфоблока. Такой способ оправдан при существенной перестройке экрана; ради дополнительной кнопки или информационного блока менять всю форму не нужно.
Создать отдельную административную страницу
Собственная страница нужна для самостоятельного инструмента: отчёта с отдельными фильтрами, управления своей сущностью или обработки данных из нескольких модулей. Это крайний вариант, если нужный сценарий не помещается в штатные формы и их расширения.
Основной код разместите в /local/admin/project_tool.php. Минимальная страница подключает административное окружение, проверяет доступ и выводит содержимое между прологом и эпилогом.
<?php
require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_before.php';
if (!$USER->IsAdmin()) {
$APPLICATION->AuthForm('Доступ только администратору.');
}
$APPLICATION->SetTitle('Проверка интеграции');
require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_after.php';
echo '<div class="adm-info-message">Здесь размещается результат проверки интеграции.</div>';
require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php';
Точка входа /bitrix/admin/project_tool.php подключает этот файл:
<?php
require $_SERVER['DOCUMENT_ROOT'] . '/local/admin/project_tool.php';
Откройте /bitrix/admin/project_tool.php под администратором: появятся заголовок и информационный блок. Если инструмент изменяет данные, добавьте POST-обработчик с проверкой сессии, прав и входных значений до вывода страницы. Сам административный пролог не реализует бизнес-логику инструмента.
Выбирайте точку расширения по месту действия: переход — в меню или кнопке, данные объекта — в поле или вкладке, сведения заказа — в его карточке. После подключения выбранного примера проверьте нужную страницу и соседние экраны, а также доступ под теми ролями, которые будут пользоваться доработкой.