main · Главный модуль 26.700.0 Заметное

Main 26.700.0: в ядре появились фича-флаги

4 мин чтения Устаревших API: 6

Битрикс выкатил main 26.700.0 — и это тот редкий случай, когда в ядре появляется целая новая подсистема: фича-флаги Bitrix\Main\Config\Feature с двумя таблицами в БД. Плюс несколько тихих поведенческих изменений, которые стоит проверить, если у вас не-UTF-8 сайт, кастомные фильтры пользователей или наследники сущностей AccessRights. Дифф — 139 файлов, +3480/−1615 строк.

Что сломается

Начнём с неприятного — с того, что молча меняет поведение.

Uri::urnEncode() больше не перекодирует по умолчанию

У Bitrix\Main\Web\Uri::urnEncode($str, $charset) дефолт второго параметра поменялся с 'UTF-8' на false, и ветки логики поменялись местами. Раньше строка по умолчанию перекодировалась из кодировки сайта в UTF-8 перед rawurlencode. Теперь по умолчанию — просто rawurlencode без перекодировки; конвертация включается, только если явно передать $charset, отличающийся от кодировки сайта.

На UTF-8-сайтах ничего не изменится. На не-UTF-8 — изменится. Ядро свои вызовы адаптировало (например, Engine\Response\Zip\EntryBuilder теперь зовёт urnEncode() без 'UTF-8'), ваш код придётся проверить руками.

CHTTP::URN2URI() переписан

Метод теперь работает через (new Uri($urn))->toAbsolute($server_name ?: null). Убрана ручная сборка протокола и срезание портов :80/:443 из HTTP_HOST; для пустого $urn результат обрезается rtrim($url, '/'). Если у вас сайт живёт на нестандартном порту — поведение может отличаться от старого.

У сущностей AccessRights пропал loadModel()

Публичный loadModel() удалён у AccessDirector, AccessTeamDirector, StructureDepartment, StructureTeam и UserAll в Bitrix\Main\UI\AccessRights\Entity\*. Логика уехала в новый трейт HrStructureModelTrait. Если вы наследовались от этих классов и переопределяли или вызывали loadModel() — это изменение контракта, готовьтесь чинить.

Фильтр пользователей стал доступнее

Bitrix\Main\Filter\UserDataProvider::getAdminAvailability() больше не проверяет $USER->canDoOperation('edit_all_users') — остались только условия по экстранету. То есть пункт фильтра теперь виден пользователям без права edit_all_users. Если вы на это право опирались — учтите.

Помельче, но тоже про контракты

  • UpdateSystem\Migration\Agent::__construct(): параметр переименован $cAgentClass$agentClass. Ломает только вызовы с именованными аргументами.
  • Web\Http\Curl\Handler: Response теперь создаётся в receiveBody() через новый публичный buildResponse(), а не в receiveHeaders(); receiveBody() больше не возвращает false при отсутствии заголовков. Класс помечен @internal, но если вы от него наследовались — проверяйте.
  • Формат debug-лога HttpClient изменился: «шапка» с бэктрейсом больше не пишется автоматически из Handler::log() — за неё отвечает отдельный logBacktrace() и новый флаг HttpDebug::BACKTRACE (входит в HttpDebug::DEFAULT; ALL теперь 0b01111111). Если вы парсите логи main.HttpClient — формат поедет.

А вот «изменения сигнатур» CDatabasePgSql::Add/Insert/PrepareUpdate из api.diff — ложная тревога: только реформат пробелов и array()[].

Deprecated: одного добавили, одного помиловали

  • CHTTP::ParseAuthRequest() теперь официально @deprecated — фактически там просто починили docblock (/*/**). Рекомендованная замена: \Bitrix\Main\Server::parseAuthRequest().
  • Обратный ход: с CEventMessage пометку @deprecated сняли. Старый API почтовых шаблонов снова «легален». Такое бывает нечасто.

Новое: фича-флаги в ядре

Главная новинка релиза — подсистема Bitrix\Main\Config\Feature: 12 новых файлов в lib/Config/Feature*. Флаг — это не строчка в опциях, а полноценный PHP-класс: его FQCN и есть код флага.

Как это устроено:

  • Config\Feature — статический фасад: isEnabled / isDisabled / enable / disable / allow / deny / clearRules / resetToDefault / clearCache.
  • Feature\AbstractFlag — базовый класс флага с хуками onEnable() / onDisable(), которые срабатывают только при фактической смене значения в БД.
  • Feature\AbstractRule + enum RulePolicy (allow / deny) и два готовых правила: Rules\UserIdRule (по списку ID пользователей) и Rules\ModuleMinVersionRule (по минимальной версии модуля).
  • Feature\Context (userId + params, getCurrent()), Feature\Factory, ORM-таблеты FeatureFlagTable / FeatureFlagRuleTable.
  • Порядок проверки в FeatureManager: requirements → deny-правила → allow-правила → значение в БД → enabledByDefault(). Значения и правила кешируются на 86400 секунд.

Свой флаг выглядит примерно так:

        <?php declare(strict_types=1);

namespace Vendor\Module\Feature;

use Bitrix\Main\Config\Feature\AbstractFlag;

final class NewCheckoutFlag extends AbstractFlag
{
    public function enabledByDefault(): bool
    {
        return false;
    }
}

    

А в коде — проверка и раскатка на избранных:

        use Bitrix\Main\Config\Feature;
use Bitrix\Main\Config\Feature\Rules\UserIdRule;
use Vendor\Module\Feature\NewCheckoutFlag;

// пустить в новый чекаут только тестовую группу:
// правило передаётся именем класса, аргументы — конфигом
Feature::allow(NewCheckoutFlag::class, UserIdRule::class, ['userIds' => [1, 42, 137]]);

if (Feature::isEnabled(NewCheckoutFlag::class)) {
    // новый флоу
}

    

Две детали, которые стоит знать заранее. Первая: неизвестный класс флага считается включённым — логика «feature was enabled and removed from codebase»: удалили класс — значит, фича доехала до всех. Вторая: раз в день Feature\CleanupAgent вычищает из таблиц записи флагов и правил, классов которых больше нет в коде. FeatureManager зарегистрирован сервисом в .settings.php модуля main, логгер — main.config.feature.

Новое: по мелочи, но полезно

  • ModuleManager::getModificationDateTime(string $moduleName): ?DateTime — дата модификации version.php модуля через filemtime. Заодно ModuleManager::add() обернули в try/catch (DuplicateEntryException) — повторная регистрация модуля больше не роняет установку.
  • CUserFieldEnum::getDefaultValue(int $fieldId): array — статический кеш значений по умолчанию для enum-полей (сброс — через protected cleanCache(), снаружи он не вызывается); UserField\Types\EnumType::getDefaultValue() переведён на него вместо прямого запроса.
  • В JS main.core кеш BaseCache переехал с голого Map на абстракцию ICacheStorage (memory- и localStorage-реализации), get/set получили дженерик-перегрузки, а Tag.render — параметр типа T = HTMLElement в TS-типах.

БД

  • Две новые таблицы под фича-флаги: b_feature_flag (PK CODE, поля MODULE_ID, ENABLED, MODIFIED_AT, MODIFIED_BY, индекс по MODULE_ID) и b_feature_flag_rule (ID, FEATURE_CODE, POLICY, RULE_CODE, RULE_ARGS, MODIFIED_AT, MODIFIED_BY, индекс по FEATURE_CODE) — и в mysql, и в pgsql install.sql.
  • Новый индекс ix_b_user_field_enum_def по полю DEF таблицы b_user_field_enum — под тот самый CUserFieldEnum::getDefaultValue().
  • db.diff пуст: изменения зафиксированы только в install.sql для новых установок, на существующих их накатит апдейтер.

Мелочи и находки

  • Тихий XSS-фикс: в шаблоне main.interface.toolbar параметры кнопок LINK, TITLE, ICON, TEXT теперь прогоняются через htmlspecialcharsbx(). Если вы туда передавали готовый HTML — он перестанет быть HTML.
  • Фикс конкуренции очередей Messenger: ключ блокировки стал per-таблице (queueLock_<имя_таблицы> вместо общего queueLock). Раньше разные очереди делили один лок и мешали друг другу.
  • Uri::convertToPunycode() / convertToUnicode() получили быстрый выход: конвертация запускается, только если хост содержит не-ASCII символы или подстроку xn--.
  • punycode.php даёт ~1180 строк диффа — но это почти целиком реформат кодстайла без смены алгоритма. То же с sql-хелперами (mssql/oracle/pgsql/mysqli), PhoneNumber/MetadataProvider.php и UI/Uploader/File.php: array()[], camelCase, скобки.
  • Ходившая гипотеза о переезде файлов lib/Mail/Internal на PascalCase/PSR-4 не подтвердилась: в files-added только 13 файлов (Config/Feature/* и HrStructureModelTrait.php), удалённых нет.
  • В application.php при переименовании переменных бережно сохранён вечный TODO: «Should be transfered to where GET parameter is defined in future». Традиции.
  • В xml.php в getAttributesNodesArray() добавили страховку от $ret, не являющегося массивом, — обходной манёвр вместо честного исправления типа переменной.

Релиз 26.700.0 датирован 2026-08-24 — предыдущий 26.650.100 вышел всего 12 дней назад. Вердикт: обновляться можно спокойно, но не-UTF-8 сайтам и владельцам кастомизаций вокруг AccessRights и фильтра пользователей — сначала прогнать тесты.

Устаревшие и удалённые API в этой версии

Символ Статус Чем заменять
CHTTP::ParseAuthRequest() Deprecated Bitrix\Main\Server::parseAuthRequest()
Bitrix\Main\UI\AccessRights\Entity\AccessDirector::loadModel() Удалено Bitrix\Main\UI\AccessRights\Entity\HrStructureModelTrait
Bitrix\Main\UI\AccessRights\Entity\AccessTeamDirector::loadModel() Удалено Bitrix\Main\UI\AccessRights\Entity\HrStructureModelTrait
Bitrix\Main\UI\AccessRights\Entity\StructureDepartment::loadModel() Удалено Bitrix\Main\UI\AccessRights\Entity\HrStructureModelTrait
Bitrix\Main\UI\AccessRights\Entity\StructureTeam::loadModel() Удалено Bitrix\Main\UI\AccessRights\Entity\HrStructureModelTrait
Bitrix\Main\UI\AccessRights\Entity\UserAll::loadModel() Удалено Bitrix\Main\UI\AccessRights\Entity\HrStructureModelTrait

Читайте дальше

main 26.650.0 Заметное Свежее

main 26.650.0: сброс счётчиков ленты пачкой и превью своих ссылок без похода наружу

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

3 мин
location 26.300.0 Заметное Свежее

Location 26.300.0: батчевый обратный геокодинг — до 20 координат за один вызов

Релиз от 17 июня 2026 с одной, но цельной темой: в модуль `location` завезли батчевый обратный геокодинг — метод `findByCoordsList`, который превращает список координат в список локаций за один вызов сервиса. Если вы строите интеграции с картами или доставкой и до сих пор дёргали `findByCoords` в ци...

2 мин
security 26.200.0 Безопасность Свежее

Security 26.200.0 не ставится на маке и Windows: фатал «Cannot redeclare class» прямо в апдейтере

Обновление security 26.200.0 у нас не установилось вообще: апдейтер умирает с фаталом посреди своего скрипта. Если ваш прод на Linux — выдыхайте, вас это не касается. А вот если вы ставите обновления в локальной разработке на macOS или Windows (Docker с bind-mount проектной папки — это ровно тот слу...

4 мин
mail 26.900.0 Заметное Свежее

Mail 26.900.0: общие подписи ломают старый API, а тяжёлые вложения переезжают на Диск

Модуль mail получил один из самых жирных релизов за последнее время: 523 файла, +39 182/−3 131 строк. Внутри — три большие фичи (общие подписи, автоперенос тяжёлых вложений на Диск, избранное с AI-классификацией писем), переработанный IMAP-синк истории и три новые таблицы в БД. Если вы кастомизирова...

4 мин
Мы используем файлы cookie для улучшения работы сайта. Продолжая использовать сайт, вы соглашаетесь с нашей политикой конфиденциальности.
AI Домовой

AI Домовой История

на связи

пишет…
Нет истории чатов
AI Домовой

Нужна авторизация

Войдите, чтобы задавать вопросы AI Домовому.

Войти