Note 26.600.0: публичные базы знаний и новая корзина
Ломающее обновление
Удалены или изменены публичные API — прикладной код может перестать работать.
В Note 26.600.0 базу знаний можно открыть наружу по ссылке с паролем, удалённая база теперь попадает в корзину и восстанавливается целиком, а бизнес-процессы научились создавать и менять статьи. Для интеграций важнее другое: note.collection.delete больше не удаляет базу насовсем, звезда и подписка разделились, а у нескольких команд поменялись конструкторы.
Новое
Откройте базу по публичной ссылке
В диалоге прав появилась вкладка публичной ссылки с паролем и сроком действия. Управлять ею может модератор (LEVEL_MODERATE), посетитель по адресу /pub/note/{token}/ только читает базу и вложения. Флаг ExternalAccess по умолчанию выключен, и его выключение закрывает все публичные входы, сохраняя настройки ссылок.
Если включить закрытую или просроченную ссылку заново, токен сменится. Пустые password и expiresAt при сохранении очищают значения, отсутствующие оставляют прежние. После трёх неверных паролей появляется CAPTCHA.
Восстанавливайте базы целиком
Удалённая база теперь лежит в корзине вместе с деревом. Восстановление базы возвращает только статьи, удалённые вместе с ней, а удалённые раньше остаются в корзине. Статья, восстановленная в архивную базу, остаётся архивной. Корзина хранит удалённое 30 дней, отрицательный TTL отключает автоочистку. HardDeleteCollectionCommand может вернуть completed=false, тогда очистку продолжают следующим запросом.
Рабочая область, архив и корзина показывают разделы баз деревом. Для своих списков есть SectionProvider и LevelProvider из Bitrix\Note\Public\Provider\ContentList, по 50 записей, максимум 200. Массовые операции проверяют права на каждую статью, а MoveAllOwnedInCollectionCommand с планировщиком переносит больше 50 верхних узлов агентом и возвращает deferredTail.
Работайте с базами через REST V3
note.document.list отдаёт метаданные с курсором, текст читается через note.document.get. note.file.list отдаёт файлы одного документа с курсором по ID. Страницы по 50 записей, максимум 200, у поиска появился pagination.offset до 10000. note.collection.list фильтрует по state (live, archived, trashed), без фильтра отдаёт live. Допустимы = и in внутри положительного and, or и отрицания отклоняются.
Новые note.collection.unarchive, note.collection.restore, note.document.unarchive и note.document.restore возвращают объекты из архива и корзины. Для базы нужна модерация. Документу, чья база удалена, нужна целевая collectionId, иначе придёт NOTE_RESTORE_TARGET_REQUIRED. Базу нельзя восстановить, если срок хранения истёк или окончательная очистка уже началась.
Автоматизируйте статьи бизнес-процессами
У Note появился тип документа бизнес-процесса, триггеры создания и перемещения статьи, действия изменения статьи и подписки сотрудников (режимы self и subtree, сотрудников без права чтения действие пропускает). Запись из процесса идёт как WriteSource::Workflow с checkRights:false и повторно триггеры не запускает. Составной узел по умолчанию скрыт настройкой bizproc.complex_activity_excluded=1.
Те же изменения из PHP делает UpdateDocumentFieldsCommand: название, Markdown и место в дереве. Команда не атомарна, поэтому смотрите, что успело примениться:
use Bitrix\Note\Public\Command\UpdateDocumentFieldsCommand;
$result = (new UpdateDocumentFieldsCommand(
documentId: $documentId,
title: 'Регламент отпусков',
markdown: null,
collectionId: null,
parentId: null,
userId: $userId,
))->run();
['appliedFields' => $applied, 'failedField' => $failed] = $result->getData();
checkRights=true по умолчанию проверяет права только при перемещении, право менять название и текст проверяйте сами. Событие note:onDocumentLifecycle получило initiatorId, writeSource (по умолчанию user) и причину collectionHardDeleted.
Редактор, CoPilot и картинки по ссылке
Видео вставляется ссылкой с проверкой embed-хоста при флаге VideoEmbedLink, уже сохранённые плееры работают и без него. CoPilot правит выделение или раздел статьи и вставляет текст и картинки, если включены AiEditorFlag, модуль ai, опция note_editor_allow_text_generate и разрешение CoPilot.
FileController::uploadImageByUrlAction() скачивает картинку по URL в документ с правом редактирования. Принимаются только HTTP(S) без частных IP и SVG, до 25 МиБ, трёх редиректов и 15 секунд. По умолчанию 60 запросов в минуту на пользователя, дальше HTTP 429, лимит задаёт опция remote_image_import_limit_per_minute. showAction() получил preview=false, предпросмотр ограничивает сторону копии 2000 пикселями.
Что сломается
Удаление базы стало мягким
DeleteCollectionCommand и note.collection.delete теперь кладут базу в корзину с описанием, деревом, ACL, избранным и подписками. Строка базы и collectionId остаются, и код, который считал базу после удаления исчезнувшей, найдёт её в note.collection.list с state: trashed. Смотреть, восстанавливать и окончательно удалять такую базу может модератор базы или администратор, восстанавливать или удалять её статьи по одной нельзя. В архивную базу нельзя писать и переносить статьи даже администратору.
Звезда больше не подписка
Снятие звезды не отменяет подписку, из результата RemoveFavoriteCommand пропало removed.notifyMode, а подписаться можно без звезды. У FavoriteProvider::getPage() и FavoriteController::listAction() убран $onlyNotified, подписки отдают SubscriptionProvider::getPage() и SubscriptionController::listAction(). Архивные статьи остаются в избранном, но пропадают из подписок. Уведомлениями управляет флаг DocumentNotifications (по умолчанию выключен), старая опция note.notifications_enabled больше ни на что не влияет.
Вставляйте загруженные файлы в текст
Файл, загруженный через note.file.upload, надо вставить в текст статьи. При включённой очистке версий агент удаляет файлы старше суток, которых нет ни в текущем Markdown, ни в сохранённых версиях, и не ждёт истечения срока хранения версии. Загруженный, но не вставленный файл агент удалит.
Поправьте конструкторы команд
Если создаёте команды Bitrix\Note\Public\Command сами, проверьте аргументы. Вызовы только с обязательными первыми аргументами работают, а позиционные зависимости и удалённые именованные аргументы — нет.
BulkHardDeleteDocumentsCommand: третьим вставлен$withNested=false, уBulkRestoreDocumentsCommandон пятый.MoveDocumentCommand: перед$backlinkNotifierдобавлены$writeSourceи$checkRights.DeleteCollectionCommand: удалены$searchIndexService,$documentRepository,$hardDeleteService,$favoriteRepository.RemoveFavoriteCommand: удалены$subscriptionRepositoryи$lockService, уSetSubscriptionCommand—$favoriteRepositoryи$lockService.
В JS NotePermissionsApp.openPopup() заменён на openCollectionPopup(), openCollectionCreatePopup(), openDocumentPopup() и openGlobalSettings(). Новый диалог прав сохраняет изменения сам.
БД
В b_note_collection добавлены TRASHED_AT, TRASHED_BY и PURGE_STARTED_AT, b_note_recycle_bin получила COLLECTION_ID и IS_ROOT, b_note_event получила SOURCE_TYPE и SOURCE_ID. Публичные ссылки хранятся в b_note_external_access и b_note_external_access_collection. Пока новые поля не заполнены, старые записи корзины могут не показываться в списке разделов.
Мелочи и находки
- История, справка по горячим клавишам, обратные ссылки, Markdown и наследуемые права поддерева больше не требуют прежних opt-in.
- Боковой AI-чат не проверяет
ai_chat_enabled, остальные проверки модулей и CoPilot остались. - Мобильная оболочка синхронизирует тему и навигацию, загружает файлы и импортирует Markdown. Базы, статьи и избранное можно перемещать с клавиатуры с теми же проверками прав, что при drag-and-drop.
- Тема, боковая панель и ширина текста посетителя публичной ссылки хранятся у него в браузере и настройки сотрудника не трогают.
- Импорт из Landing исправляет ссылки на главную страницу базы и заголовки с вложенными абзацами.
Устаревшие и удалённые API в этой версии
| Символ | Статус | Чем заменять |
|---|---|---|
Bitrix\Note\Public\Command\SetSubscriptionCommand::ERROR_FAVORITE_REQUIRED
|
Удалено | — |
NotePermissionsApp.openPopup()
|
Удалено |
NotePermissionsApp.openCollectionPopup(), NotePermissionsApp.openCollectionCreatePopup(), NotePermissionsApp.openDocumentPopup(), NotePermissionsApp.openGlobalSettings()
|