Как добавить кастомный блок главной страницы
- 1. Концепция
- 2. Структура блока в /local
- 3. Блок центра: center_block/.php
- 4. Блок сайдбара: right_block/.php
- 5. Настройки блока после выгрузки
- 6. Что выгрузить и что делать дальше (порядок для пользователя)
- 7. Примеры
- 8. Обновления модуля и файлы /mainpage/index.php и /mainpage/.left.menu.php
- 9. Безопасность и диагностика
- 10. Инструкция для ИИ-агента
Руководство для разработчика и для ИИ-агента. Относится к модулю ithive.homepage версии 12.4.0 и выше.
Описание соответствует коду lib/Blocks/*, lib/Rest/Controllers/Blocks.php и lib/Migration/MainpageThinIndexMigration.php.
Коротко: кастомный блок - это один обычный PHP-файл в /local/ithive.homepage/blocks/center_block/<code>.php (блок центра) или /local/ithive.homepage/blocks/right_block/<code>.php (блок сайдбара). Раскладка такая же, как у стандартных блоков модуля (/mainpage/center_block/<code>.php, /mainpage/right_block/<code>.php): код блока - имя файла без .php, зона - каталог. Манифеста, регистрации и REST-вызова для создания блока нет. Порядок, активность, название, права, мобильный контракт и пункт левого меню настраиваются после выгрузки файлов - на странице «Настроить Главную» и методом homepage.blocks.update.
1. Концепция
Главная страница (/mainpage/) состоит из блоков двух зон:
| Зона | Код зоны | Файл блока | Где выводится |
|---|---|---|---|
| Центр | center |
center_block/<code>.php |
В основной колонке страницы; разметку и оформление блока формирует сам блок |
| Сайдбар | right |
right_block/<code>.php |
В правой колонке через view target sidebar; вывод блока автоматически оборачивается в стандартную карточку виджета |
Кастомный блок переживает обновления модуля, потому что:
- Файлы блока лежат в
/local/ithive.homepage/blocks/center_block/и/local/ithive.homepage/blocks/right_block/. Обновление модуля копирует файлы только в/bitrix/modules/ithive.homepage/,/bitrix/components/ithive/,/bitrix/js/ithive.homepage/и т. п. и не трогает/local. /mainpage/index.phpтонкий. Он подключает модуль и вызывает\Ithive\Homepage\Blocks\Renderer::renderPage(__DIR__, __FILE__). Вся логика вывода живёт в модуле и обновляется вместе с ним (раздел 8).- Реестр блоков (
BlocksRegistry) собирается на лету: встроенные блоки модуля + файлы из/local/ithive.homepage/blocks/center_block/иright_block/. Никакой регистрации не нужно: положили файл - блок появился. - Настройки хранятся отдельно от файлов в опции
componentsettings(по сайтам): порядок (sort), активность (active), название (lang), а для локальных блоков такжеrights,mobile,menu,left_menu. Эффективное описание блока = то, что обнаружил реестр (код, зона, файл, источник) плюс настройки сайта.
Блок, которого ещё нет в componentsettings, не активен (active = false, на главной не выводится), с sort = 500 и названием, равным коду. Блок виден в «Настроить Главную» и в homepage.blocks.list / homepage.blocks.get; чтобы он появился на главной, его нужно включить (галочка «Акт.» в «Настроить Главную» или homepage.blocks.update с {"active": true}). Запись создаётся при первом изменении настроек.
Источник блока (source):
| source | Откуда | Что можно менять через homepage.blocks.update |
|---|---|---|
builtin |
Встроенный блок модуля | active, sort, title (то же, что даёт «Настроить Главную») |
local |
/local/ithive.homepage/blocks/center_block/<code>.php или right_block/<code>.php |
active, sort, title, rights, mobile, menu, left_menu |
Блоки не создаются и не удаляются через REST: создаёт файлы разработчик (или ИИ формирует файлы, а пользователь выгружает их), удаляет файл тоже разработчик.
2. Структура блока в /local
/local/ithive.homepage/blocks/
├── center_block/
│ └── <code>.php # блок центра: код = имя файла без .php
└── right_block/
└── <code>.php # блок сайдбара
Каталога на блок нет: один блок - один файл. Если файлы с одним именем лежат и в center_block/, и в right_block/, это два блока одного кода (по одному в каждой зоне) с раздельными настройками (как у встроенных блоков). Свои ассеты и подшаблоны держите в /local вне этих каталогов, например /local/ithive.homepage/assets/<code>/, и подключайте абсолютными путями (подробнее в конце раздела 3).
Правила кода блока (имя файла без .php): только a-z, 0-9, _; длина до 64 символов; без двойного подчёркивания __ и без _ в начале и в конце кода (страница «Настроить Главную» передаёт поля как <код>__<параметр> и разбирает их по __, поэтому такие коды ломают разбор: файл с таким именем не загружается, на странице показывается ошибка ShowError); префиксы custom_ и new_custom_ зарезервированы (HTML-виджеты страницы настроек); коды всех встроенных блоков зарезервированы для обеих зон: код встроенного блока центра нельзя использовать и для блока сайдбара, и наоборот (встроенный блок остаётся, локальный пропускается с ошибкой; например, /local/ithive.homepage/blocks/right_block/news.php пропускается, хотя news - блок центра). Коды встроенных блоков центра: banner, news, news_smi, services, gallery, leader_sales, structure_events, stream; сайдбара: assessment360, birthday, bizproc, changes, events, gamification, goalsmanagement, goalsmanagement2, helpdesk, ipr, knowledgebase, message_blog, popular, pulse, socials, soon, task, urls, vote, vote_polls, workplaces. Выбирайте код с префиксом клиента (acme_memo), он не пересечётся с будущими блоками модуля.
Правила загрузки (BlocksRegistry):
- Просматриваются только файлы
*.phpпрямо в/local/ithive.homepage/blocks/center_block/(блоки центра) и/local/ithive.homepage/blocks/right_block/(блоки сайдбара); код блока - имя файла без.php. Нет каталога зоны - зона пуста, ошибки нет. - Файл с недопустимым кодом (символы вне
[a-z0-9_], длина больше 64,__в коде,_в начале или конце, префиксыcustom_/new_custom_) пропускается, причина показывается на странице ошибкойShowError. - Файлы с другим расширением (
x.txt,x.bak) и подкаталоги внутриcenter_block/иright_block/блоками не считаются и молча игнорируются. - Символьные ссылки и junction, ведущие за пределы каталога блоков (каталог зоны - ссылка, либо файл блока
<code>.php- ссылка), отвергаются с ошибкой. - Конфликт кода с кодом встроенного блока любой зоны: локальный блок пропускается с ошибкой на странице.
- Файл блока, который не является файлом или недоступен для чтения: блок пропускается с ошибкой на странице («Template file is not readable»); если файл исчезает или становится нечитаемым уже после загрузки, на месте блока выводится «Ошибка вывода блока ...: Файл шаблона блока не найден или недоступен для чтения», остальные блоки работают. Фатальные ошибки PHP внутри самого шаблона (например, повторное объявление функции) перехватить нельзя, они прерывают страницу.
Файл подключается в изолированной области: доступны $APPLICATION, $USER и $block (Block - эффективное описание текущего блока: getCode(), getZone(), getTitle(), getSort()). Вывод файла идёт в буфер; при исключении буфер сбрасывается и блок не выводится совсем (без частичной разметки), а на его месте показывается ошибка ShowError с кодом блока и причиной. Остальные блоки продолжают работать.
Шаблон подключается уже внутри страницы: не подключайте в нём header.php/footer.php и не печатайте <html>/<body>. Начинайте файл с защиты пролога (как стандартные блоки):
<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
die();
}
После защиты можно писать обычную разметку и вставки <?php ... ?>, <?= ... ?>, вызывать $APPLICATION->IncludeComponent(...) (например bitrix:news.list с нужными параметрами - так устроены стандартные блоки /mainpage/right_block/urls.php, news.php и др.), подключать свои подшаблоны абсолютным путём вне каталогов зон, например include $_SERVER['DOCUMENT_ROOT'] . '/local/ithive.homepage/assets/<code>/partial.php' (любой *.php, лежащий прямо в center_block/ или right_block/, считается блоком, поэтому подшаблоны туда не кладут). Данные пользователя выводите с экранированием (htmlspecialcharsbx()).
3. Блок центра: center_block/.php
Образец (/local/ithive.homepage/blocks/center_block/acme_memo.php):
<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
die();
}
/** @global CUser $USER */
?>
<div class="acme-memo" style="padding: 20px; background: #fff; border-radius: 12px; margin-bottom: 20px;">
<h3>Добро пожаловать, <?= htmlspecialcharsbx($USER->GetFirstName()) ?>!</h3>
<ol>
<li>Заполните свой профиль и добавьте фотографию.</li>
<li>Познакомьтесь со структурой компании.</li>
</ol>
</div>
Правила центра:
- Блок выводится в основной колонке как есть, без обёртки: фон, отступы, скругления и заголовок блок задаёт сам (как в образце). Поле «Свое название» в «Настроить Главную» у блоков центра недоступно для редактирования. Для вида, единого со встроенными блоками, смотрите стандартные файлы
/mainpage/center_block/<code>.php и используйте те же компоненты и шаблоны.
- Блоки выводятся по возрастанию
sort. При совпадении sort у двух встроенных блоков второй ставится в конец списка (поведение прежнего index.php). Клиентский блок с тем же sort, что у другого блока, встаёт сразу после него, как в «Настроить Главную»; новый блок получает sort = 500, как и встроенный gallery, поэтому для точного места задайте sort явно.
- Выводятся только блоки с
active = Y (локальные блоки, ещё не сохранённые в настройках, считаются неактивными: сначала включите блок).
- Пользовательские HTML-виджеты (
custom_items) выводятся только в сайдбаре; custom_items центра (наследие опции) не выводятся - как и в прежнем index.php.
Ассеты и подшаблоны блока (CSS, JS, изображения, подключаемые *.php) модуль не ищет и не проверяет: каталога на блок нет. Положите их в /local где удобно, например в /local/ithive.homepage/assets/<code>/, и подключайте абсолютными путями: \Bitrix\Main\Page\Asset::getInstance()->addCss('/local/ithive.homepage/assets/acme_memo/style.css'), include $_SERVER['DOCUMENT_ROOT'] . '/local/ithive.homepage/assets/acme_memo/partial.php'. Не кладите их внутрь center_block/ и right_block/: каждый *.php прямо в этих каталогах считается блоком.
4. Блок сайдбара: right_block/.php
Образец (/local/ithive.homepage/blocks/right_block/acme_links.php) - только содержимое карточки:
<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
die();
}
?>
<ul>
<li><a href="/company/">О компании</a></li>
<li><a href="/docs/">Документы</a></li>
<li><a href="/company/structure.php">Структура компании</a></li>
</ul>
Правила сайдбара:
- Сайдбар выводится, только если в настройках главной включена правая колонка (
right_block.active = Y), а страница выводится шаблоном bitrix24 (иначе Renderer ничего не выводит).
- Renderer сам кладёт вывод блока в view target
sidebar: $APPLICATION->AddViewContent('sidebar', $html, $sort). Блок не должен сам вызывать AddViewContent и выводить обёртку карточки - достаточно вывести содержимое.
- Вывод оборачивается в разметку, идентичную
ithive:widget.wrapper:
<div class="widget-mainpage" id="homepage-block-<code>-<N>">
<div class="widget-mainpage-top"><div class="widget-mainpage-top-title">Название блока</div></div>
<div class="widget-mainpage-content"><div class="widget-mainpage-content-container">
...вывод блока...
</div></div>
</div>
- Заголовок карточки добавляет модуль: сохранённое администратором название (
title), иначе код блока. Свой заголовок в файле блока сайдбара не выводите, иначе он задвоится. Чтобы карточка называлась по-человечески, после выгрузки задайте title (раздел 5).
- Оформление: рамку, отступы и заголовок карточки дают классы
widget-mainpage* (стили sidebar.css шаблона bitrix24, страница подключает его сама); содержимое оформляйте своей разметкой (списки, ссылки, <p>), специальных классов контента модуль не предоставляет. Для вида, единого со встроенными виджетами, ориентируйтесь на стандартные файлы /mainpage/right_block/<code>.php и их шаблоны компонентов.
- Сайдбар выводится по возрастанию
sort (при совпадении sort действует то же правило, что в центре); в нём же выводятся пользовательские HTML-виджеты.
5. Настройки блока после выгрузки
Блок, выгруженный в /local, сразу появляется на странице «Настроить Главную» (вкладки центра и сайдбара) и в homepage.blocks.list, но выключенным: на главной он не виден, пока его не включат. Включается и настраивается там же (галочка «Акт.») или методом homepage.blocks.update (нужны права администратора). Все значения хранятся в настройках сайта (componentsettings), а не в файлах; страница «Настроить Главную» не редактирует rights, mobile, но не теряет их при сохранении; menu и left_menu блока центра редактируются там же (раздел 5.2).
Поле update
Что задаёт
Границы
active
Включён ли блок на сайте
true / false
sort
Порядок вывода (меньше - выше)
целое 0..1000000
title
Название блока (заголовок карточки сайдбара)
1-255 символов, теги вырезаются
rights
Права (раздел 5.1)
{admin: bool, groups: int[]}
mobile
Контракт мобильного приложения (раздел 5.3)
{type, url, dataMethod}
menu
Пункт левого меню (раздел 5.2), только зона center
{url, title}
left_menu
Показывать пункт menu в левом меню
true / false, нужен menu
Пример (название, порядок, доступ только администраторам):
curl -X POST "https://{portal}/rest/{user_id}/{webhook_code}/homepage.blocks.update.json" \
-H "Content-Type: application/json" \
-d '{"code":"acme_links","zone":"right","fields":{"title":"Полезные ссылки","sort":300,"active":true,"rights":{"admin":true,"groups":[]}}}'
rights, mobile, menu, left_menu у встроенных блоков отклоняются (VALIDATION_ERROR); menu/left_menu у блока сайдбара - тоже. Любая ошибка валидации отменяет всё изменение целиком. Метод меняет один блок за вызов; остальные блоки и состояние зон не затрагиваются, недостающие в сохранённых настройках встроенные блоки и флаги зон перед записью берутся из значений по умолчанию.
5.1. Права
Поле rights:
Поле
Тип
Описание
admin
bool
Блок виден администраторам портала
groups
int[]
ID групп пользователей, которым виден блок
Правила (Block::canView() по эффективным rights из настроек):
- Пустые права (
admin = false, groups = []) - блок виден всем, кто видит главную.
- Иначе пользователь должен быть администратором (при
admin = true) или состоять хотя бы в одной группе из groups.
- Проверка выполняется при выводе блока на странице, в пункте меню раздела
/mainpage/ (пункт показывается, только если блок доступен пользователю; в левом меню портала блок с rights пункта не получает, раздел 5.2), в homepage.blocks.list (недоступные блоки не возвращаются), в homepage.blocks.get и homepage.blocks.data (ACCESS_DENIED), а также в homepage.widgets.list / homepage.widgets.get для локальных блоков (скрытый блок не возвращается, get отвечает NOT_FOUND).
homepage.blocks.update (только администратор) возвращает блок даже если после сохранения rights вызывающий администратор сам потерял к нему доступ: ответ строится по сохранённым настройкам без проверки прав. Последующие get/list/data для него блок уже скрывают.
- Права скрывают сам блок, но не данные: код блока (шаблон, компонент) отвечает за проверку доступа к тому, что он показывает.
- Снять ограничение:
"rights": [].
5.2. Пункт левого меню
Блок центра может добавить пункт в левое меню портала (и в меню раздела /mainpage/, /mainpage/.left.menu.php). Для этого задайте menu и включите left_menu:
{"menu": {"url": "/company/news/", "title": "Новости компании"}, "left_menu": true}
url: относительный путь, начинающийся с / (но не //), либо https://.... Другие схемы (javascript:, http:, data:) отклоняются.
title: по умолчанию равен названию блока.
- Ограничение по
rights. Левое меню портала задаётся на уровне сайта и не умеет скрывать пункт от отдельных пользователей. Поэтому блок с ограничением rights (администраторы и/или группы) не добавляет пункт в левое меню портала вообще; в меню раздела /mainpage/ пункт показывается только пользователям с доступом к блоку (проверка та же, что при выводе блока). Нужен пункт в меню портала - не ограничивайте блок по rights или ограничьте содержимое самим блоком.
- Когда пункт появляется и исчезает. Модуль сам синхронизирует пункты блоков из
/local с левым меню портала при сохранении настроек: в «Настроить Главную», в настройках модуля и при вызове homepage.blocks.update (любое поле) для блока центра. Пункт появляется, когда блок активен, включён left_menu, задана ссылка menu.url и нет rights. Пункт исчезает при снятии флага, выключении блока, удалении ссылки (menu), добавлении rights и удалении записи блока из настроек. Удалили файл блока из /local - пункт уйдёт при следующем сохранении настроек блоков или вызове homepage.menu.refresh. Пункты встроенных блоков и пункты, добавленные администратором портала вручную, синхронизация не меняет; повторное сохранение пункт не дублирует. Текст пункта - название блока (title, оно же lang), иначе menu.title; ссылка - menu.url. Изменения видны после перезагрузки страницы.
- Пункт появляется только у активных блоков центра и только если включён
left_menu (его же отмечает администратор флагом «Вывести в левое меню» в «Настроить Главную»; флаг и поле ссылки рядом с ним есть у каждого блока центра из /local, ссылка вводится прямо там и хранится в тех же настройках, что и menu.url). Флаг хранится в componentsettings (left_menu), по умолчанию выключен. Если флаг отмечен, а ссылка пустая или недопустима (правила menu.url: путь на портале или https), «Настроить Главную» не сохраняет изменения и показывает ошибку. Если флаг снят, введённая допустимая ссылка сохраняется, пункт не показывается; очистка поля удаляет menu.
- Название пункта: сохранённое название блока, иначе
menu.title.
- Удалить пункт:
"menu": [] (флаг left_menu сбрасывается).
5.3. Мобильное приложение
Мобильное приложение (МП) получает список блоков через homepage.blocks.list, а данные блока - через homepage.blocks.data. Клиент МП находится вне этого репозитория; контракт задаёт поле mobile:
mobile.type
Дополнительные поля
Что получает приложение
none (по умолчанию)
-
Блок не отдаётся в МП; homepage.blocks.data вернёт NOT_SUPPORTED
webview-url
url (/... или https://...)
url и absoluteUrl - страница открывается во встроенном браузере
native-json
dataMethod (необязательно)
Данные блока в JSON для нативной отрисовки либо имя REST-метода, который приложение вызывает само
mobile.dataMethod для native-json - только имя REST-метода формата <scope>.<entity>.<action> (например acme.news.list). Сервер этот метод не вызывает и PHP-класс по строке не разрешает: имя возвращается приложению в поле dataMethod ответа homepage.blocks.data. Формат Class::method не поддерживается и отклоняется (VALIDATION_ERROR).
Данные блока на стороне сервера поставляет событие ithive.homepage:OnBlockMobileData с параметрами code, zone, userId, siteId. Подписчик отвечает EventResult с параметром data (массив); используется первый ответ с данными, он попадает в data ответа homepage.blocks.data. Если событие данных не дало, а задан dataMethod - возвращается имя метода (data = null); иначе NOT_SUPPORTED.
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'ithive.homepage',
'OnBlockMobileData',
static function (\Bitrix\Main\Event $event) {
if ($event->getParameter('code') !== 'acme_memo') {
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::UNDEFINED);
}
return new \Bitrix\Main\EventResult(
\Bitrix\Main\EventResult::SUCCESS,
['data' => ['items' => [['title' => 'Пункт 1']], 'userId' => (int)$event->getParameter('userId')]]
);
}
);
homepage.blocks.data требует, чтобы блок был активен и доступен пользователю по rights.
6. Что выгрузить и что делать дальше (порядок для пользователя)
- Выгрузите файл блока на портал (FTP/SFTP/
scp/файловый менеджер хостинга): /local/ithive.homepage/blocks/center_block/<code>.php (центр) и/или /local/ithive.homepage/blocks/right_block/<code>.php (сайдбар), а свои ассеты и подшаблоны - в любое место в /local, например /local/ithive.homepage/assets/<code>/. Каталоги /local/ithive.homepage/blocks/center_block/ и right_block/ создаёт установка и обновление модуля, если их нет; если при обновлении не хватило прав на запись, создайте их сами.
- Сбросьте
opcache (если включён и не проверяет время изменения файлов): иначе портал может отдавать старую версию файла.
- Откройте страницу «Настроить Главную»: блок уже в списке, но не активен,
sort = 500, название = код. На /mainpage/ он пока не выводится. Если над блоками показана красная ошибка - прочитайте причину (раздел 9).
- Включите блок (галочка «Акт.» в «Настроить Главную» или
homepage.blocks.update с {"active": true}), при необходимости отсортируйте и переименуйте (sort, title). Блок сайдбара виден на главной, если включена правая колонка.
- При необходимости выставьте права, мобильный контракт и пункт левого меню через
homepage.blocks.update (раздел 5).
- Проверьте
homepage.blocks.get (код и зона) и главную под обычным сотрудником.
Изменить блок позже - заменить файл в /local (и сбросить opcache). Удалить блок - удалить файл (запись в настройках остаётся и подхватится, если блок с тем же кодом выгрузят снова).
7. Примеры
Два готовых примера лежат в репозитории модуля: docs/examples/blocks/center_block/example_onboarding_memo.php (центр) и docs/examples/blocks/right_block/example_useful_links.php (сайдбар). Копируйте их в /local/ithive.homepage/blocks/center_block/ и /local/ithive.homepage/blocks/right_block/ соответственно.
8. Обновления модуля и файлы /mainpage/index.php и /mainpage/.left.menu.php
Файлы блоков в /local и их настройки обновление не затрагивает. Файлы вне /local, от которых зависит механизм, - /mainpage/index.php и /mainpage/.left.menu.php портала: они должны быть тонкими (вызывать код модуля).
Тонкий index.php:
<?php
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/header.php");
// The homepage logic lives in the module (Ithive\Homepage\Blocks\Renderer) and is updated together with it.
if (CModule::IncludeModule('ithive.homepage') && class_exists(\Ithive\Homepage\Blocks\Renderer::class)) {
if (!\Ithive\Homepage\Blocks\Renderer::renderPage(__DIR__, __FILE__)) {
return;
}
}
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/footer.php"); ?>
Автоматическая замена при обновлении. Обновление 12.4.0 (updater.php) для корня портала и каждого активного сайта проверяет /mainpage/index.php и /mainpage/.left.menu.php:
- Если в файле уже есть вызов модуля (
Renderer::renderPage( для index.php, LeftMenu::build( для .left.menu.php) - файл пропускается.
- Иначе рядом создаётся резервная копия
<файл>.bak-<ГГГГММДД> и файл заменяется тонким вариантом из модуля (/bitrix/modules/ithive.homepage/install/public/mainpage/). Заменяется любой файл, в том числе изменённый вручную.
- Если резервную копию создать не удалось (нет прав на запись в каталог), файл не меняется.
Если клиент менял index.php или .left.menu.php вручную, свои правки после обновления нужно вернуть из резервной копии .bak-<дата> вручную: перенесите их в блоки по этому руководству (для меню - добавьте свои пункты после вызова LeftMenu::build). Отдельных настроек, вкладки в настройках модуля или предупреждений на странице для этого нет.
Левое меню. Тонкий /mainpage/.left.menu.php содержит один вызов:
<?php
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
$aMenuLinks = [];
if (\CModule::IncludeModule("ithive.homepage")) {
$aMenuLinks = \Ithive\Homepage\Blocks\LeftMenu::build(SITE_ID, SITE_DIR);
}
Пункты меню раздела /mainpage/ (встроенных блоков и блоков клиента с menu, с учётом rights) строит класс модуля \Ithive\Homepage\Blocks\LeftMenu, поэтому правки логики меню приходят с обновлением модуля. Пункты в левом меню портала (меню интранета) этот файл не определяет: для блоков клиента их записывает модуль при сохранении настроек (раздел 5.2).
Если блок не появился после обновления. Проверьте, что /mainpage/index.php вызывает Renderer::renderPage( (например, обновление не смогло записать файл из-за прав). Если нет, замените содержимое файла вручную на тонкий вариант выше, образец - /bitrix/modules/ithive.homepage/install/public/mainpage/index.php; для меню - вызов $aMenuLinks = \Ithive\Homepage\Blocks\LeftMenu::build(SITE_ID, SITE_DIR); после подключения модуля. Встроенные блоки по-прежнему выводятся файлами /mainpage/center_block/<code>.php и /mainpage/right_block/<code>.php.
9. Безопасность и диагностика
- REST ничего не пишет и не исполняет. Блоки не создаются и не удаляются через REST, файлы не записываются.
homepage.blocks.update меняет только опцию componentsettings; значения (title, sort, rights, mobile, menu) проверяются и не исполняются как код.
- Серверных вызовов по строке из данных нет.
mobile.dataMethod - только имя REST-метода, его вызывает приложение, не сервер. Данные для МП поставляет событие ithive.homepage:OnBlockMobileData.
- Единственный динамический
include локальных блоков - файл блока <code>.php, который разработчик положил в /local/ithive.homepage/blocks/center_block/ или right_block/ (файловый доступ к серверу = доверенный). Путь файла проверяется realpath строго внутри каталога зоны (при загрузке и при каждом выводе), файл-ссылка отвергается; каталог зоны не может быть символьной ссылкой за пределы /local/ithive.homepage/blocks/.
- В
menu.url и mobile.url разрешены только относительные пути и https://.
- Данные пользователя выводите с экранированием (
htmlspecialcharsbx()); не подключайте файлы по путям из запроса.
- Права блока (
rights) ограничивают видимость блока, но не защищают данные, которые блок получает сам.
- Ошибки показываются на странице, серверный лог модуль не пишет. Блок, который не удалось загрузить (недопустимый код файла, в том числе с
__ или с _ в начале/конце; конфликт с кодом встроенного блока любой зоны; нечитаемый файл, файл или каталог зоны - ссылка), пропускается, а над блоками центра показывается ShowError вида «Блок «» (зона: ..., источник: local) не загружен: <причина>» (одна ошибка на пару «зона + код» за запрос; видна всем пользователям). Ошибка при выводе блока (исключение в шаблоне, файл не найден) показывается на месте блока: «Ошибка вывода блока «» (зона: ): <причина>».
Блок не виден - проверьте по порядку
- Тонкий ли
/mainpage/index.php. В файле должен быть вызов Blocks\Renderer::renderPage. Если нет - раздел 8.
- Версия модуля 12.4.0 или выше, класс
\Ithive\Homepage\Blocks\Renderer существует.
- Путь и имя. Файл
/local/ithive.homepage/blocks/center_block/<code>.php (или right_block/<code>.php); код блока - имя файла без .php ([a-z0-9_], без __ и без _ в начале/конце, не custom_*/new_custom_*, не код встроенного блока ни центра, ни сайдбара); расширение именно .php, файл лежит прямо в каталоге нужной зоны (не в подкаталоге).
- Причина пропуска. Откройте главную: ошибка
ShowError над блоками центра назовёт код, зону и причину (недопустимый код, конфликт со встроенным блоком любой зоны, нечитаемый файл, файл или каталог зоны - ссылка). Вызов homepage.blocks.get вернёт NOT_FOUND, если реестр блок не распознал.
- Блок включён. Новый блок из
/local по умолчанию выключен: включите его в «Настроить Главную» или homepage.blocks.update ({"active": true}); в REST смотрите поле active у homepage.blocks.get.
- Сайдбар. Для зоны
right должна быть включена правая колонка; страница должна выводиться шаблоном bitrix24.
- Права. Если заданы
rights, вы должны быть администратором или состоять в группе из groups.
- Ошибка при выводе. На месте блока выведена ошибка «Ошибка вывода блока ...»: исключение в шаблоне, неверный компонент или параметры. Проверьте синтаксис (
php -l <code>.php).
- Кэш PHP. Реестр не кэшируется между запросами, но
opcache может отдавать старую версию PHP-файла: сбросьте opcache.
- Не появился пункт меню. В левом меню портала: нужны
menu, зона center, активный блок, left_menu = true, отсутствие rights и сохранение настроек после включения (в «Настроить Главную» или homepage.blocks.update); для настроек, сохранённых до этой версии, выполните homepage.menu.refresh. В меню раздела /mainpage/ те же условия, но rights допустимы (по доступу) и нужен тонкий /mainpage/.left.menu.php (вызов Blocks\LeftMenu::build; обновление заменяет файл с резервной копией, см. раздел 8).
Проверка без браузера: homepage.blocks.list с filter={"source":"local"} показывает все распознанные локальные блоки; homepage.blocks.get с кодом и зоной - один блок. Сам вывод блока на странице без браузера проверить нельзя.
Известное поведение: если блок удалить из /local вручную, его запись в componentsettings остаётся (в homepage.widgets.list она приходит с source = settings). Запись безвредна и подхватывается, если блок с тем же кодом выгрузят снова.
10. Инструкция для ИИ-агента
ИИ сам формирует файлы блока и сообщает пользователю, куда их выгрузить и что делать дальше. REST для создания блока не используется: его нет.
10.1. Что выяснить до начала
- Что должен показывать блок (контент, данные, ссылки) и в какой зоне: центр (
center_block/<code>.php), сайдбар (right_block/<code>.php) или обе.
- Откуда берутся данные: статичная разметка, штатный компонент (
bitrix:news.list и т. п., нужен IBLOCK_ID), данные пользователя.
- Нужны ли ограничение по правам, пункт левого меню, контракт для мобильного приложения.
- Код блока: коротко,
a-z0-9_, с префиксом клиента, без __ и без _ в начале/конце, не код встроенного блока (ни центра, ни сайдбара) и не custom_*/new_custom_*. Если пользователь не назвал - предложите и подтвердите.
10.2. Шаги
- Сформируйте файл(ы) блока по образцам разделов 3 и 4 и примерам
docs/examples/blocks/: защита B_PROLOG_INCLUDED, экранирование вывода, для сайдбара только содержимое без карточки и заголовка, без header.php/footer.php. Свои ассеты/подшаблоны, если нужны, сформируйте отдельно (например, /local/ithive.homepage/assets/<code>/, не внутри каталогов зон) и подключайте абсолютными путями.
- Проверьте код блока по правилам раздела 2 и синтаксис файлов (
php -l, если есть доступ к PHP).
- Сообщите пользователю пути выгрузки (
/local/ithive.homepage/blocks/center_block/<code>.php и/или /local/ithive.homepage/blocks/right_block/<code>.php) и список файлов для выгрузки, включая ассеты вне каталогов зон.
- Опишите следующие шаги (раздел 6): выгрузить файлы -> сбросить
opcache при необходимости -> блок появится в «Настроить Главную» и в homepage.blocks.list выключенным -> включить (галочка «Акт.» или homepage.blocks.update с {"active": true}), отсортировать, переименовать, выставить права.
- Если нужны название, порядок, права, меню или контракт МП - подготовьте готовый вызов
homepage.blocks.update с code, zone и fields (раздел 5) и отдайте пользователю (или выполните, если у вас есть вебхук администратора, после того как пользователь подтвердил, что файлы выгружены: до выгрузки update вернёт NOT_FOUND).
- Проверка результата:
homepage.blocks.get с code и zone (источник local, нужные title, sort, active, rights), затем главная.
Шаблон ответа пользователю:
Блок «<название>» готов. Файлы:
- center_block/<code>.php (или right_block/<code>.php)
- <ассеты, если есть: /local/ithive.homepage/assets/<code>/...>
Куда выгрузить: /local/ithive.homepage/blocks/center_block/<code>.php (или .../right_block/<code>.php)
Дальше:
1. Выгрузите файлы на портал (при необходимости сбросьте opcache).
2. Блок появится в «Настроить Главную» и в homepage.blocks.list выключенным - включите его (галочка «Акт.» или `homepage.blocks.update` с `{"active": true}`) и задайте порядок.
3. Название/права/меню - homepage.blocks.update (готовый вызов ниже).
10.3. Чего делать нельзя
- Не создавать блок через REST (методов
homepage.blocks.add и homepage.blocks.delete нет) и не писать манифест block.php: он не используется.
- Не выводить в файле блока сайдбара собственную карточку
widget-mainpage и заголовок (модуль добавляет их сам) и не вызывать AddViewContent из блока.
- Не использовать в
mobile.dataMethod форму Class::method: только REST-имя scope.entity.action.
- Не называть блок кодом встроенного блока (любой зоны), кодом с префиксом
custom_/new_custom_, кодом с __ или с _ в начале/конце.
- Не подключать файлы по путям из запроса, не выводить данные без
htmlspecialcharsbx().
- Не писать в серверные логи: ошибки блока показываются на странице.
10.4. Критерии готовности
- Файлы блока созданы, начинаются с защиты
B_PROLOG_INCLUDED, синтаксически верны.
- Пользователю названы пути выгрузки (
/local/ithive.homepage/blocks/center_block/<code>.php, .../right_block/<code>.php) и дальнейшие шаги.
- Для нужной настройки (название, порядок, права, меню, МП) дан корректный вызов
homepage.blocks.update.
- После выгрузки блок виден в
homepage.blocks.get (source = local) и на главной.