# Проверка на портале

> Всё, что ниже рантайма Битрикса, тестами не закрыть: установка, права, кеш,
раскладка файлов, поведение при обновлении. Проверять это приходится руками —
и лучше по списку, потому что забытый шаг находит не разработчик, а клиент.

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

Процедура рассчитана на **отдельный стенд**, а не на боевой портал. Шаги
«удалить модуль» и «поставить на CP1251» на рабочем портале делать нельзя.

Раскладка репозитория — в [module-structure.md](/modules/options/module-structure), сборка и
релиз — в [build-and-install.md](/modules/options/build-and-install).

## Что понадобится

| | |
|---|---|
| портал | «коробка» Битрикс24 или БУС, главный модуль **22.600.300** и выше |
| PHP | **8.2** и выше, расширение `mbstring` |
| кодировка | **только UTF-8** |
| доступ | администратор портала и доступ к файлам по ssh или ftp |
| если входа нет | четыре шага проходятся из CLI, см. раздел ниже |
| архив | со страницы релиза либо собранный `./build.sh` |

Для сценария «обновление» дополнительно нужен стенд, где уже стоит версия
**2.x** — именно на нём проверяется то, ради чего 3.0.0 сделана мажорной.

## Перед началом

**Снимите копию каталога модуля и дамп таблицы настроек.** Шаги с удалением
необратимы, а сравнивать «было / стало» иначе не с чем.

```bash
cp -a /var/www/portal/bitrix/modules/shef.options /tmp/shef.options.before
mysqldump -u… portal b_option --where="MODULE_ID='shef.options'" > /tmp/opt.before.sql
```

Запишите, что лежит в публичных каталогах до установки — это пригодится на
шаге удаления:

```bash
ls /var/www/portal/bitrix/css/ /var/www/portal/bitrix/js/ | sort > /tmp/public.before
```

## 0. Архив — тот самый

Сверять не с константой из этого документа, а со своей сборкой из того же
тега: архив собирается **побайтово одинаково** у всех, кто взял этот коммит.

```bash
git clone https://github.com/bx-shef/options.git
cd options && git checkout <тег проверяемой версии>
./build.sh                       # последняя строка напечатает sha256
sha256sum /путь/к/скачанному/shef.options.zip
```

Хеши обязаны совпасть. Не сошлось — не ставьте: проверять поведение сборки,
которая неизвестно откуда, бессмысленно.

**У выпусков 2.3.0, 3.0.0 и 3.0.1 сверять не с чем.** Воспроизводимость появилась
вместе с нормализацией времени, прав и порядка записей в `build_archive`, а
эти три архива собраны раньше и несут внутри время того клона, из которого их
собирали. Их хеш пересборкой не повторить — это свойство тех архивов, а не
признак подмены.

Первым уровнем внутри архива обязан быть каталог `shef.options/`:

```bash
unzip -Z1 shef.options.zip | cut -d/ -f1 | sort -u   # ровно одна строка
```

## Если входа в админку нет

Четыре шага — A, C, D и F — сделаны в расчёте на административный раздел.
Капча, чужой стенд, отсутствие пароля — и четыре пункта из десяти встают
целиком.

Запасной путь есть, и он измерен: страница настроек — это файл
`bitrix/modules/shef.options/options.php`, тот же самый, который подключает
`/bitrix/admin/settings.php`. Подняв пролог из CLI, авторизовавшись
администратором и подключив этот файл с буферизацией вывода, вы получаете тот
же html. На стенде с ядром 26.700.0 оба прохода — из CLI и через настоящую
админку — дали одно и то же.

Порядок такой:

1. подключить `bitrix/modules/main/include/prolog_before.php`, задав
   `$_SERVER['DOCUMENT_ROOT']`;
2. авторизоваться администратором — права модуля читаются через
   `GetGroupRight()`, без входа он вернёт `D`;
3. задать `$mid = 'shef.options'` — `options.php` ждёт его глобальной;
4. подключить `options.php` с `ob_start()` и разобрать полученный html.

**Что этим проверяется:** состав вкладок и опций, текст подписей, отсутствие
вкладки «Документация», права пользователей.

**Что не проверяется:** отрисовка в админке, применение стилей, сохранение
через форму (POST с `sessid`), кнопки установки и удаления. Эти пункты либо
проходятся с входом, либо честно отмечаются в бланке как непройденные.

Отдельно: состав настроек можно получить и без отрисовки — `options_conf.php`
возвращает массив `\Shef\Options\Main\Options\Tab`, если перед этим
подключён модуль и `optionsconfig.php`.

## A. Чистая установка

1. Распаковать в `bitrix/modules/`, чтобы получилось
   `bitrix/modules/shef.options/`.
2. Административный раздел → **Marketplace → Установленные решения** →
   поставить модуль.

**Ожидается:** установка проходит, ошибок нет, модуль появился в списке с
русским названием и описанием.

**Если не так:** снимите текст ошибки целиком. Самые частые причины — не та
версия PHP (текст скажет, какая нужна и какая есть) и портал не в UTF-8.

## B. Обновление с 2.x — главный сценарий 3.0.0

Делается на стенде, где уже работает 2.x.

1. Запомнить, что было:

```bash
ls /var/www/portal/bitrix/js/shef-options/ 2>/dev/null   # в 2.x каталог есть
```

2. Заменить каталог модуля содержимым новой версии.
3. Открыть `/bitrix/admin/settings.php?mid=shef.options`.

**Ожидается:**

* страница открывается;
* вкладка **одна** — «Общие». Вкладки «Документация» больше нет, и это не
  поломка: markdown-блок убран из модуля целиком, документация живёт в
  репозитории;
* ранее сохранённое значение «Служебный пользователь» **на месте** — имя
  настройки не менялось;
* в логе портала нет ошибок вида «class not found».

**Если вкладка «Документация» осталась** — заменился не весь каталог модуля.
Уберите каталог целиком и распакуйте заново.

**Каталог `/bitrix/js/shef-options/` после обновления останется** — это
нормально: новая версия туда ничего не кладёт, а убирает его деинсталляция,
см. шаг F.

## C. Страница настроек

`/bitrix/admin/settings.php?mid=shef.options`

Входа в админку нет — см. [«Если входа в админку нет»](#если-входа-в-админку-нет):
состав вкладок и подписи проверяются отрисовкой из CLI, сохранение через
форму — нет.

**Ожидается:** вкладка «Общие», на ней одно поле — «Служебный пользователь»
с описанием «Пользователь с правами администратора, которого не уволят».
Больше на вкладке ничего нет.

**Жёлтого предупреждения про хранение свойств каталога быть не должно** — оно
убрано в 3.0.2. Осталось на стенде, обновлённом с версии ниже, — заменился
не весь каталог модуля.

Дальше:

1. Выбрать пользователя, сохранить, перезайти на страницу — значение на месте.
2. Зайти под сотрудником **без прав** на модуль — страница не должна
   открыться.

## D. Фронт и права на файлы

| адрес | ожидается |
|---|---|
| `/bitrix/css/shef.options/admin-options.css` | **200**, отдаётся содержимое |
| `/bitrix/modules/shef.options/install/css/shef.options/admin-options.css` | **403** |

Второе — не придирка: в поставке nginx закрывает `/bitrix/modules/`, и
поэтому фронт раскладывается установщиком в `/bitrix/css`. Если каталог
модуля отдаётся браузером, на портале неверная конфигурация веб-сервера, и
это стоит починить раньше, чем модуль.

Стили на странице настроек применились. Если нет, а css отдаётся — это кеш:
Ctrl+F5 либо сброс автокеширования в настройках главного модуля. Путь вида
`/bitrix/cache/js/s1/...` в консоли браузера означает, что вы смотрите на кеш.

## E. Разбор настройки — то, что чинили в 3.0.0

`\Shef\Options\Main\Constants::getSystemUserId()` раньше приводил значение
через `(int)`, и опечатка в настройке молча выдавала права не тому
пользователю. Проверяется так:

1. Очистить поле «Служебный пользователь», сохранить.
2. Выполнить в консоли портала (или в тестовом скрипте под прологом):

```php
echo \Shef\Options\Main\Constants::getSystemUserId();
```

**Ожидается `1`** — умолчание, а не `0`. Ноль означал бы работу «от имени
никого».

## F. Удаление

1. Административный раздел → удалить модуль.
2. Сравнить публичные каталоги:

```bash
ls /var/www/portal/bitrix/css/ /var/www/portal/bitrix/js/ | sort > /tmp/public.after
diff /tmp/public.before /tmp/public.after
```

**Ожидается:**

* `/bitrix/css/shef.options` удалён;
* `/bitrix/js/shef-options` удалён — **в том числе на стенде, обновлённом с
  2.x**, где этот каталог остался от прежней версии;
* **чужие файлы и каталоги на месте** — `diff` не должен показать ничего,
  кроме двух этих строк.

3. Проверить, что настройки ушли вместе с модулем:

```sql
SELECT * FROM b_option WHERE MODULE_ID = 'shef.options';   -- строк быть не должно
```

Настройки стираются с 3.0.2. На стенде, где до удаления стояла версия ниже,
строки могли остаться от прежней установки — это не сбой текущего удаления.

Отдельно: если на портале стоит другой модуль линейки, зависящий от
`shef.options`, удаление должно **отказаться** и назвать этот модуль.

Зависимого модуля на стенде может не оказаться, и тогда шаг молча
пропускается. Воспроизводится он так: у любого соседнего модуля временно
дописать в `.settings.php` `'requireModules' => ['shef.options']`, попробовать
снять `shef.options`, затем вернуть `.settings.php` как было и **сверить md5** —
иначе легко оставить чужой модуль поправленным.

Текст отказа из CLI не перехватить: `ShowForm()` заканчивается `die()`, и
буфер теряется. Сам факт отказа виден по тому, что модуль остался
установленным.

## G. Установка через Composer

На проекте с Composer:

```bash
composer require bxshef/options
```

**Ожидается:** модуль развернулся в `bitrix/modules/shef.options/`.

**Не в** `vendor/bxshef/options/` и **не в** `bitrix/modules/bxshef.options/`.

Легло в `vendor/` — на проекте не разрешён плагин `composer/installers`.
В неинтерактивном режиме Composer 2.2+ его не спрашивает, а молча пропускает.
Лечится в корневом `composer.json` проекта:

```json
{
	"config": {
		"allow-plugins": {
			"composer/installers": true
		}
	}
}
```

## H. Примеры

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

```bash
cd /путь/к/репозиторию/options
DOCUMENT_ROOT=/var/www/portal php examples/pid.php
```

**Ожидается:** первая строка кончается `[портал]`, дальше все строки `ok`,
последняя — `ГОТОВО: pid`, код возврата `0`.

* `[заглушки]` вместо `[портал]` — не нашёлся
  `<DOCUMENT_ROOT>/bitrix/modules/main/include/prolog_before.php`;
* `Модуль shef.options не установлен` — модуль распакован, но не установлен из
  административного раздела;
* любая строка `FAIL` — расхождение кода с тем, что обещает пример. Это
  находка, а не шум: присылайте вывод целиком.

`pid.php` проверять обязательно: в нём правка `\Shef\Options\Main\TempFile\Pid`,
которую заглушками до конца не проверить — живость процесса выясняется по
`/proc` и `posix_kill`, а каталог и права на портале настоящие. Файлы он
пишет во временный каталог портала (`upload/tmp/shef.options/example-pid`) и
за собой убирает; сигналов живым процессам не шлёт. **Пустой каталог группы
остаётся** — так и задумано, файлы убирает `remove()`, каталог не его дело.

Пример печатает, чем на этом стенде выясняется живость процесса: строка «Это
окружение: /proc …, ext-posix …». Если нет ни того, ни другого, шаг «убран
ровно один файл» упадёт — и это не поломка модуля, а свойство окружения:
`clearDir()` в таком случае не удаляет ничего намеренно.

В контейнере есть отдельная ловушка: `/proc` показывает процессы **своего**
контейнера. Если временный каталог портала лежит на томе, общем с другим
контейнером, чужие живые блокировки выглядят мёртвыми и будут удалены. На
одном контейнере это не бьёт.

Остальные четыре примера работают только с памятью процесса и на портале
ничего не меняют — их можно прогнать разом:

```bash
for f in examples/*.php; do
	[ "$(basename "$f")" = '_bootstrap.php' ] && continue
	DOCUMENT_ROOT=/var/www/portal php "$f" > /dev/null || echo "провал: $f"
done
```

## I. Отказы установки — если есть куда

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

**Портал в CP1251.** Установка должна **отказаться** с текстом «Модуль
поставляется в кодировке UTF-8…», а не поставиться наполовину и выдать мусор
вместо русского текста.

На современных ядрах этот сценарий **недостижим в принципе**: установщик
спрашивает `\Bitrix\Main\Application::isUtfMode()`, а в main 26.700.0 этот
метод возвращает `true` без условий — CP1251 платформой больше не
поддерживается. Форсирование `BX_UTF` ничего не меняет, метод его не читает.
Ветка отказа при этом остаётся нужной: на ядре, где CP1251 ещё жив, она
сработает. Отмечайте «пропущено, ядро 26.x» — искать, что вы сделали не так,
не нужно.

**PHP ниже 8.2.** Отказ с текстом «Для модуля требуется версия PHP выше
8.2.0. Ваша версия …». Порог задан в `install/index.php`, свойство
`$PHP_MIN_VER`, — берите оттуда, а не отсюда.

Образа Битрикса с PHP 8.1 не существует, а на голом `php:8.1-cli` пролог не
поднять, поэтому установку целиком воспроизвести обычно негде. Частичная
замена — прогнать на настоящем 8.1 ровно то сравнение, которое делает
`DoInstall()`:

```bash
php -r 'echo var_export(version_compare(PHP_VERSION, "8.2.0", "<"), true), PHP_EOL;'
# на 8.1 ожидается true  → установка откажется
# на 8.2 ожидается false → установка продолжится
```

Это проверяет решение, но не саму установку. В бланке — «частично».

## Если что-то не сошлось

Соберите сразу, одним сообщением:

1. что делали — номер шага отсюда;
2. что ожидали и что получили;
3. версии: `php -v`, версия главного модуля, версия `shef.options` из
   `install/version.php`;
4. текст ошибки **целиком**, включая путь и строку;
5. для шага H — весь вывод примера, не только строку `FAIL`;
6. хвост `bitrix/php_interface/log.txt`, если портал в него пишет.

Без пунктов 3 и 4 разбирать нечего: одна и та же жалоба на разных версиях
ядра означает разные причины.

## Бланк результата

```
Стенд: ______________  Ядро: __________  PHP: ______  Кодировка: ______
Версия модуля: ______  sha256 архива сошёлся: да / нет / нечем (выпуск собран до воспроизводимой сборки)
Шаги A, C, D, F пройдены: через админку / отрисовкой из CLI / и так и так

0 архив ................ [ ]      F удаление ............... [ ]
A чистая установка ..... [ ]      G Composer ............... [ ]
B обновление с 2.x ..... [ ]      H примеры ................ [ ]
C страница настроек .... [ ]      I отказы установки ....... [ ] / пропущено
D фронт и права ........ [ ]
E разбор настройки ..... [ ]      Проверил: ______________  Дата: ______
```

---

[↑ Содержание](/modules/options) | [Сборка и релиз](/modules/options/build-and-install) | [Структура](/modules/options/module-structure)

::note
Источник: [options/docs/portal-check.md](https://github.com/bx-shef/options/blob/main/docs/portal-check.md) — правки туда, сайт пересобирается сам.
::
