Перейти к содержимому

Мастер тиражного решения - шаги, макросы, публичная часть

Собираем мастер, который после установки решения разворачивает у клиента готовый сайт: создаёт его, копирует публичную часть и подставляет реальные значения.

Механика

Мастер - это многошаговый диалог в административной части, разворачивающий решение. Клиент ставит модуль решения как обычный модуль, а затем запускает мастер и получает работающий сайт с демо-данными.

Файлы мастера живут в отдельном каталоге мастеров с собственным пространством имён партнёра. Пространство имён здесь такое же, как у компонентов: имя партнёра и код решения.

В корне каталога мастера обязателен файл описания с параметрами. Рядом лежат языковые файлы, изображения решения, публичная часть, шаблоны сайта и выгрузки демонстрационных инфоблоков.

Мастер решения почти никогда не пишут полностью с нуля. Стандартное решение из поставки уже умеет выбирать шаблон, тему и настраивать сайт, поэтому свой мастер наследуют от него и переопределяют только нужные шаги.

Каждый шаг мастера - это класс с понятным жизненным циклом. Один метод готовит заголовки и переменные, второй выводит форму шага, третий обрабатывает введённые данные после нажатия кнопки.

Реальные пути и идентификаторы в файлы решения не зашивают. Вместо них ставят макросы, которые мастер заменяет на настоящие значения прямо во время установки.

Замена макросов бывает точечной по файлу и рекурсивной по дереву. Первая правит один файл, вторая проходит по всему дереву публичной части решения и правит все файлы разом.

Демонстрационные инфоблоки решения грузятся из готовых выгрузок. Полученные при загрузке идентификаторы подставляются в файлы всё той же заменой макросов, поэтому ссылки в шаблонах остаются рабочими.

Шаг настройки сайта делает пять разных вещей строго по порядку. Создаёт сайт, копирует публичную часть, копирует шаблон дизайна, применяет цветовую тему и выставляет настройки модулей.

Оформление мастера подключают отдельным ключом в файле описания. Без него берётся стандартный шаблон оформления, и это вполне рабочий вариант для первой версии решения.

Мастер живёт заметно дольше первой версии решения, и это стоит учесть сразу. Каждое обновление решения означает и проверку мастера: шаги, макросы и выгрузки должны соответствовать новым файлам публичной части.

Отсюда практическое правило: чем меньше шагов переопределено, тем дешевле поддержка. Стандартные шаги обновляются вместе с продуктом, а собственные приходится сопровождать своими силами годами.

Шаги

  1. Завести каталог мастера в пространстве имён партнёра и кода решения.
  2. Описать мастер файлом описания с наследованием от стандартного мастера поставки.
  3. Переопределить только те шаги, поведение которых заметно отличается от типового.
  4. Разложить публичную часть решения по языковым каталогам без всякой бизнес-логики.
  5. Заменить все абсолютные пути и идентификаторы инфоблоков макросами установки.
  6. Проверить установку на чистом сайте и на сайте с уже существующими данными.

Код

Описываем мастер:

/bitrix/wizards/vendor/shop/.description.php
$arWizardDescription = [
'NAME' => GetMessage('WIZARD_NAME'), // текст только из языкового файла
'DESCRIPTION' => GetMessage('WIZARD_DESC'),
'VERSION' => '1.0.0',
'PARENT' => 'wizard_sol', // наследуем стандартный мастер
'STEPS' => ['SelectTemplate', 'SelectTheme', 'SiteSettings', 'DataInstall'],
// языковые строки описания лежат в каталоге lang рядом с файлом
];

Файл описания проверяется системой ещё до запуска самого мастера. Пропущенное имя или версия означают, что мастер не появится в списке, а причина в интерфейсе будет описана обтекаемо.

Наследуем стандартные шаги:

/bitrix/wizards/vendor/shop/wizard.php
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/install/wizard_sol/wizard.php';
class VendorSiteSettingsStep extends CSiteSettingsWizardStep
{
public function InitStep() { parent::InitStep(); $this->SetTitle('Настройки магазина'); }
public function OnPostForm() { parent::OnPostForm(); /* свои значения */ }
}

Наследование стандартного мастера экономит недели работы команды. Выбор шаблона, темы и базовая настройка сайта уже написаны, а своим кодом остаётся дополнить только то, что действительно отличается в решении.

Ставим макросы вместо путей и идентификаторов:

// в файлах публичной части решения
$APPLICATION->IncludeComponent('bitrix:news.list', '', [
'IBLOCK_ID' => '#NEWS_IBLOCK_ID#', // подставится при установке
'DETAIL_URL' => '#SITE_DIR#news/#ELEMENT_CODE#/',
]);

Абсолютные пути и жёстко заданные идентификаторы ломают решение на втором сайте. Макросы решают это сразу и заодно позволяют ставить решение в подкаталог, а не только в корень.

Подставляем значения при установке:

CWizardUtil::ReplaceMacros($file, ['NEWS_IBLOCK_ID' => $iblockId]); // один файл
WizardServices::ReplaceMacrosRecursive($dir, ['SITE_DIR' => $siteDir]); // дерево
// рекурсивную замену делают после копирования публичной части
// список макросов собирают заранее: пропущенный останется в файле как есть

Замена макросов выполняется уже по скопированным файлам самого решения. Порядок здесь важен: сначала копирование, потом загрузка демонстрационных данных, и только потом подстановка полученных идентификаторов.

Загружаем демонстрационные инфоблоки:

$iblockId = WizardServices::ImportIBlockFromXML(
$wizardPath . '/site/xml/news.xml', // выгрузка инфоблока решения
'news', $siteId
);
// полученный идентификатор тут же уходит в замену макросов
// выгрузку кладут в каталог мастера рядом с публичной частью

Инфоблоки решения переносят готовыми выгрузками, а не скриптами создания структуры. Так структура переносится целиком, а полученные идентификаторы сразу попадают в файлы через замену макросов.

Добавляем кнопку запуска мастера:

// include.php модуля решения
$APPLICATION->AddPanelButton([
'ID' => 'vendor_shop_wizard',
'TEXT' => GetMessage('VENDOR_SHOP_WIZARD'),
'HREF' => '/bitrix/admin/wizard_install.php?wizardName=vendor:shop',
// wizardSiteID добавляют, когда сайтов на копии несколько
]);

Кнопка на панели администратора избавляет клиента от поиска адреса мастера. Запуск мастера возможен и по прямому адресу, но клиенту его сообщать неудобно.

Проверяем, что макросы не остались в файлах:

Окно терминала
grep -rn '#[A-Z_]\{3,\}#' /home/bitrix/www/ --include='*.php' | grep -v bitrix/wizards | head
# найденные строки означают пропущенный макрос в списке замены
# проверку делают сразу после установки решения на чистый сайт

Оставшийся в файле макрос выдаёт себя решёткой прямо в разметке страницы. Проверка одной командой после установки ловит это раньше, чем клиент откроет сайт и увидит непонятную строку.

Ограничения

Подсистема мастеров целиком относится к старому ядру платформы. Современного аналога у неё нет, и код мастера пишут в процедурном стиле старых классов.

Готовое решение не должно трогать чужие и системные файлы. Каталог загрузок, файл правил обработки адресов и клиентский шаблон по умолчанию перезаписывать нельзя.

На многосайтовом проекте имена шаблонов сайта должны быть уникальными. Одинаковое имя шаблона перетирает чужой шаблон соседнего сайта прямо при установке решения.

Установка решения на непустой сайт требует отдельной проверки. Мастер, проверенный только на чистой установке, у клиента с данными ведёт себя иначе.

Типичные проблемы

Мастер не появляется в списке установки.

В файле описания не хватает обязательных значений или он лежит не в том каталоге. Проверка идёт по файлу описания до запуска любого кода мастера.

Русский текст решения после установки нечитаем.

Текст зашит прямо в код решения вместо языковых файлов. Перекодировка при установке решения применяется только к файлам языковых каталогов.

Решение работает только на первом сайте.

В файлах публичной части решения остались абсолютные пути и жёстко заданные идентификаторы. Их место в файлах решения занимают макросы установки.

После установки на втором сайте сломался дизайн соседнего.

Шаблон решения назван так же, как уже существующий на сайте. На многосайтовых проектах к имени шаблона добавляют признак сайта.

Часть файлов решения не попала на сайт.

Файлы, начинающиеся с точки, получили признак скрытых ещё при переносе. Перед сборкой архива этот признак снимают рекурсивно по всему дереву.

Частые вопросы

Обязателен ли мастер для решения?

Нет, модуль может ставиться и без него. Мастер нужен тиражным решениям, которые разворачивают у клиента готовый сайт с демо-данными и настройками.

Можно ли написать мастер с нуля?

Технически да, практически - не стоит. Стандартный мастер из поставки уже реализует типовые шаги, и наследование экономит недели работы.

Где хранить демонстрационные данные?

В выгрузках инфоблоков внутри каталога мастера. Мастер загружает их при установке и подставляет полученные идентификаторы в файлы решения.

Как проверить мастер перед публикацией?

Установкой на чистый сайт и на сайт с существующими данными, в обеих кодировках. Ошибки установки чаще всего вылезают именно на втором сценарии.

Что нельзя класть в решение?

Каталог загрузок, файл правил обработки адресов и системные файлы ядра. Такое решение не пройдёт проверку при публикации в каталоге решений.

Смежное

Первоисточник