Landing 26.1000.0: удалён Block::isContains, ссылки теперь режутся по белому списку схем
Обновление landing 26.1000.0 (сборка от 24.08.2026) — это на 90% security-хардening плюс новая песочница для превью страниц «на устройствах». Дифф огромный — 1300 файлов, +73 тысячи строк — но почти всё это пересобранные JS-бандлы, контентные блоки и webp вместо png. Содержательного PHP — примерно 17 файлов в lib/, и вот там как раз есть чем зацепиться: ломающие изменения публичного API без всякого deprecated-периода.
Проверьте вызовы Block::isContains — метода больше нет
Самое жёсткое: публичный Bitrix\Landing\Block::isContains(int $entityId, string $needed, bool $isLanding = false): bool удалён. Не помечен deprecated — именно удалён. Если ваш код его вызывает, после обновления получите фатальную ошибку.
Взамен появились два узкоспециализированных метода:
Block::findVisibleLandingIdByFileInBlock(int $blockId, int $fileId): ?intBlock::findVisibleLandingIdByFileInLanding(int $landingId, int $fileId): ?int
Причина замены — Mantis #252316: старый метод искал подстроку, и числовой префикс id файла ложно совпадал (искали файл 25 — находили 250). Новая реализация ищет ссылку на файл Диска по точному паттерну через Connector\Disk::getExactFileHrefPattern. Важно: прямой замены для произвольного строкового $needed нет — если вы искали в блоке не файл, а что-то своё, придётся писать поиск самостоятельно.
Ссылки со странными схемами молча превратятся в пустую строку
Второе, что может «выстрелить» тихо и не сразу. При сохранении контента:
Node\Linkтеперь прогоняетhrefчерез новыйSanitizer::sanitizeHref()— allow-list схем, default-deny;Node\Text,Node\Img,Node\Iconпропускаютdata-pseudo-urlчерезsanitizePseudoUrl()вместо сырогоjson_encode;Block::setAttributesсанирует все атрибуты с манифест-типомurl(через новый сборщикBlock::collectUrlAttrs).
Белый список: http, https, mailto, tel, sms, skype плюс псевдосхемы ландингов page:, block:, form:, product:, file:, user:, help:. Всё остальное — включая намеренно заблокированные javascript:, data:, vbscript: — при сохранении молча становится пустой строкой. Никаких ошибок, никаких предупреждений.
Если ваши кастомные блоки писали в url-атрибуты нестандартные значения (свои схемы, диплинки приложений) — после обновления при первом же пересохранении блока они обнулятся. Проверяйте.
Остальные ломающие изменения — по мелочи, но проверьте наследников
Hook\Page\Fonts::resolveFontName()— сигнатура изменилась:resolveFontName(string $fontCode, ?string $claimedName = null). Методprotected, параметр опционален — заденет только тех, кто переопределял его в наследниках. По сути защита от подмены имени Google-шрифта: заявленное имя из сниппета принимается только как регистровый вариант доверенного slug (isCasingVariantOfSlug), потому что имена Google Fonts регистрозависимы.Vibe\TemplateRegions— из enum выпилены 17 региональных кейсов (AutomationDe,AutomationFr,AutomationJaи т.д.), вместо них одинAutomationCn = 'alaio.vibe_automation_cn'. Сигнатураresolve()расширена:resolve(Templates $code, ?string $portalZone = null, ?string $language = null)— региональность теперь параметр, а не отдельный кейс. Ссылки на удалённые кейсы enum сломаются на этапе компиляции.Subtype\Form::getFormsViaConnector()— возвращаемый тип сменился сarrayна?array(null= коннектор не дал валидного ответа). Ломает наследников этого protected-метода.Connector\Crm— маркер#requisiteCompanyTitleтеперь экранируется черезhtmlspecialcharsbx. Контекст жёсткий: контент блока исполняется черезeval()вBlock::view()(Mantis #253063). Если кто-то клал HTML в название компании и ждал, что он отрендерится — больше не отрендерится.Manager::availableOnlyForZone()— починили мемоизацию: раньше первый вердикт замораживался для всех последующих зон, теперь кэш пер-зона. Поведение изменится, но в корректную сторону.
Deprecated
Новых @deprecated в PHP API нет. Единственное вхождение — шум пересобранного JS-бандла с давно существовавшей пометкой.
Новое: Sanitizer и sandboxed device preview
Sanitizer — три метода для санации ссылок
Класс Bitrix\Landing\Sanitizer получил публичный API, который можно использовать и в своём коде:
<?php declare(strict_types=1);
use Bitrix\Landing\Sanitizer;
$sanitizer = new Sanitizer();
// Обычный href: allow-list схем + текстовый аудитор
$href = $sanitizer->sanitizeHref($request->get('link') ?? '');
// 'javascript:alert(1)' -> ''
// 'page:#landing123' -> останется, псевдосхемы ландингов в белом списке
// data-pseudo-url: json с ключами text/href/query/target/enabled
$pseudoUrl = $sanitizer->sanitizePseudoUrl($rawPseudoUrl);
// декодирует \uXXXX-экранирование — спрятать схему юникодом не выйдет
// Жёсткий вариант (единственный static): только http/https и относительные ссылки
$strict = Sanitizer::sanitizeHrefScheme($userInput);
// режет protocol-relative (//evil.host) и управляющие символы:
// "java\tscript:" тоже не пройдёт
Обратите внимание на sanitizePseudoUrl: она специально декодирует \uXXXX-экранирование перед проверкой, чтобы скрытые схемы стали видны. И на sanitizeHrefScheme — это static-метод для случаев, когда псевдосхемы ландингов не нужны вовсе.
Device preview в песочнице
Центральная фича релиза. Превью страницы «на устройствах» в редакторе теперь живёт в изолированном iframe (sandboxed, opaque origin), и под это появился API:
<?php declare(strict_types=1);
use Bitrix\Landing\Landing;
Landing::setDevicePreviewMode();
if (Landing::getDevicePreviewMode())
{
// страница рендерится в песочнице редактора,
// это НЕ то же самое, что preview непубликованной страницы
}
У sandboxed-iframe opaque origin, поэтому вокруг него доработали кучу мелочей:
install/components/bitrix/landing.pub/class.phpполучил ~160 строк: определение same-origin превью (isSandboxedDevicePreview) и инъекция storage-шима в самое начало<head>— в песочнице cookie/localStorage бросают DOMException и валят целые скрипт-блоки;Assets\PreProcessing\Icon::buildInlineVendorStyles()иbuildInlineFontFace()— иконочные шрифты инлайнятся, потому что сетевые шрифты в opaque origin блокируются;Hook\Page\Cookies::enabled()возвращаетfalseв device-preview-режиме — баннер согласия в такой песочнице работать не может.
Снапшот форм в Subtype\Form
Subtype\Form оброс пакетом методов вокруг «снапшота форм»: isConnector(), getConnectorFormsResponse(), isFormsSnapshotAvailable(), isActiveFormId(int), getFormActivityState(int): ?bool, resolveImportFormId(): ?int, resetFormsRuntimeState(). Кэш форм переехал со static $forms на поля класса с флагом доступности.
Смежно доработан перенос сайтов: Transfer\Script\Action\PrepareBlocksData получил resolveTargetFormId(), isTargetFormSnapshotAvailable(), getFormActivityState() и ~20 приватных методов нормализации маркеров CRM-форм — при импорте сайта форма перепривязывается на целевом портале. Enum Transfer\Requisite\Dictionary\RatioPart пополнился кейсами CrmFormTargetId и CrmFormActivity.
Шрифты
Hook\Page\Fonts::extractClaimedFontName(string $content): ?string — извлекает заявленный font-family из сниппета шрифта. Работает в паре с обновлённым resolveFontName (см. выше).
БД
Изменений схемы нет: db.diff пуст, ни новых таблиц, ни полей.
Мелочи и находки
- В комментариях кода упоминаются охранные тесты — например,
CrmRequisiteCompanyTitleEscapeTest. Битрикс пишет тесты на свои security-фиксы, приятно видеть. - 242 новых файла — почти всё контент: 150 файлов в
landing.blocks.mp_widget.*(west_auto_overview_block, vibe_auto, west_auto_header/footer_banner) и 48 вinstall/blocks/bitrix/mp_widget.west_auto_*— новые виджеты «west auto» и «vibe auto» для главной страницы и Vibe (overview- и link-блоки: CRM, задачи и проекты, воркфлоу, ИИ, смарт-процессы). - Доступность: новое JS-расширение
install/js/landing/ui/a11y/и модулиdecorate-tree.js/get-tree-focusable.js— клавиатурная навигация по дереву меню. - Массовая замена png на webp в
landing.site_master,landing.demo,landing.mainpage.pub; 39 удалённых файлов — в основном старые png/svg.
Итого
severity: notable. Схему БД не тронули, но публичный API ломали без сантиментов: Block::isContains удалён без deprecated, у Fonts::resolveFontName и Vibe\TemplateRegions::resolve изменились сигнатуры, а санация URL-схем молча обнуляет нестандартные ссылки при сохранении. Перед обновлением сделайте grep по isContains, кейсам Automation* из Vibe\TemplateRegions и своим кастомным блокам с url-атрибутами.
Устаревшие и удалённые API в этой версии
| Символ | Статус | Чем заменять |
|---|---|---|
Bitrix\Landing\Block::isContains()
|
Удалено |
Bitrix\Landing\Block::findVisibleLandingIdByFileInBlock() / Bitrix\Landing\Block::findVisibleLandingIdByFileInLanding()
|