blog · Блоги 26.600.0 Заметное

Blog 26.600.0: тег кеша для важных сообщений и исправленные права в уведомлениях

2 мин чтения Устаревших API: 1
Узнавайте о ломающих изменениях Битрикса раньше, чем они доедут до прода: свежие разборы — в канале @bxmax_updates

Blog 26.600.0 ничего не ломает и базу не трогает. Разработчику он даёт тег кеша blogpost_important_all и метод, который считает, сколько секунд осталось до ближайшей отложенной публикации важного сообщения. bitrix:blog.blog в папке модуля больше не перебирает все посты блога ради списка авторов, а на портале с intranet уведомления об упоминаниях и благодарностях считают права каждого получателя по его собственному типу пользователя.

Новое

Сбрасывайте свой кеш вместе с важными сообщениями

Модуль сбрасывает тег blogpost_important_all в двух местах. CBlogPost::Delete делает это после удаления важного поста. CBlogPost::Update сбрасывает тег, если пост был или стал важным и при этом поменялись флаг важности или срок UF_IMPRTANT_DATE_END, статус публикации, дата публикации, права SOCNET_RIGHTS или блог. Без BX_COMP_MANAGED_CACHE сброса нет. В коробке БУС тег никто не регистрирует, и кто читает его в Битрикс24, по её коду не проверить. Повесить на него свой кеш ничто не мешает.

У отложенного поста статус уже P, в списках он появляется, когда наступает DATE_PUBLISH, и в этот момент тег никто не сбрасывает. Для этого случая есть Bitrix\Blog\Integration\Socialnetwork\ImportantPostQuery::getNextPublicationDelay(DateTime $now, string $siteId): ?int. Метод находит по всем блогам, без учёта сайта и прав, ближайший важный пост с датой публикации в будущем и неистёкшим сроком важности и возвращает, через сколько секунд он выйдет (минимум 1). $siteId нужен только для формата даты. Если ждать нечего, вернёт null. Поле UF_BLOG_POST_IMPRTNT модуль blog сам не создаёт, и там, где его нет, запрос упадёт. Перед вызовом проверяйте hasField(), как это делает CBlogPost::Delete.

Файловый кеш, который стоит по умолчанию, применяет TTL из initCache() при чтении. Поэтому срок до публикации считаем один раз, при записи, кладём в сам кеш и сверяем после getVars(). Если раньше у важного поста сменят важность или её срок, статус, дату публикации, права или блог, запись сбросится по тегу. Правка заголовка и текста тег не сбрасывает.

        <?php declare(strict_types=1);

use Bitrix\Blog\Integration\Socialnetwork\ImportantPostQuery;
use Bitrix\Blog\PostTable;
use Bitrix\Main\Application;
use Bitrix\Main\Data\Cache;
use Bitrix\Main\Loader;
use Bitrix\Main\Type\DateTime;

/** Виджет «Важное»: кеш до ближайшей отложенной публикации, но не дольше часа */
function getImportantWidget(string $siteId, callable $build): array
{
    Loader::requireModule('blog');

    $dir = '/vendor/important_widget';
    $cache = Cache::createInstance();
    if ($cache->initCache(3600, $siteId, $dir)) {
        $vars = $cache->getVars();
        if (is_array($vars) && ($vars['expiresAt'] ?? 0) > time()) {
            return $vars['data'];
        }
        $cache->clean($siteId, $dir);
    }

    // срок считаем один раз, при записи: файловый кеш сверяет возраст с TTL из initCache()
    $delay = PostTable::getEntity()->hasField('UF_BLOG_POST_IMPRTNT')
        ? (new ImportantPostQuery())->getNextPublicationDelay(new DateTime(), $siteId)
        : null;
    $expiresAt = time() + min(3600, $delay ?? 3600);

    $cache->startDataCache(3600, $siteId, $dir);
    $taggedCache = Application::getInstance()->getTaggedCache();
    $taggedCache->startTagCache($dir);
    $taggedCache->registerTag('blogpost_important_all');

    $data = $build();

    $taggedCache->endTagCache();
    $cache->endDataCache(['data' => $data, 'expiresAt' => $expiresAt]);

    return $data;
}

    

CBlogPost::Add тег не сбрасывает, так что важный пост, опубликованный сразу, появится в виджете не позже чем через час, когда истечёт запись кеша. Если это долго, уменьшите верхнюю границу, но не убирайте её.

Источник «Блоги» в схеме уведомлений

CBlogNotifySchema::OnGetNotifySchema() теперь отдаёт в блоке blog ключ PRODUCT_SOURCE: ID blog, название «Блоги», описание «Комментарии и упоминания в ленте», иконка folder, сортировка 1500. Такой же ключ уже объявляют lists и mail. Читает его модуль im, которого в коробке БУС нет, поэтому где и как источник покажется в интерфейсе, по её коду не видно. Если хотите так же подписать уведомления своего модуля, повторите структуру blog в обработчике im:OnGetNotifySchema и проверьте результат на портале.

Обработчик регистрируем совместимым способом, как это делают blog, lists и mail:

        <?php declare(strict_types=1);

namespace Vendor\Shop\Integration\Im;

use Bitrix\Main\EventManager;
use Bitrix\Main\Localization\Loc;

final class NotifySchema
{
    public static function onGetNotifySchema(): array
    {
        return [
            'vendor.shop' => [
                'NAME' => Loc::getMessage('VENDOR_SHOP_NOTIFY_BLOCK'),
                'PRODUCT_SOURCE' => [
                    'ID' => 'vendor.shop',
                    'NAME' => Loc::getMessage('VENDOR_SHOP_NOTIFY_SOURCE'),
                    'DESCRIPTION' => Loc::getMessage('VENDOR_SHOP_NOTIFY_SOURCE_DESC'),
                    'ICON' => ['TYPE' => 'named', 'VALUE' => 'folder'],
                    'SORT' => 2000,
                ],
                'NOTIFY' => [
                    'order_new' => ['NAME' => Loc::getMessage('VENDOR_SHOP_NOTIFY_ORDER_NEW'), 'PUSH' => 'Y'],
                ],
            ],
        ];
    }

    /** Вызвать из DoInstall() модуля */
    public static function register(): void
    {
        EventManager::getInstance()->registerEventHandlerCompatible(
            'im', 'OnGetNotifySchema', 'vendor.shop', self::class, 'onGetNotifySchema',
        );
    }

    /** Вызвать из DoUninstall() модуля */
    public static function unregister(): void
    {
        EventManager::getInstance()->unRegisterEventHandler(
            'im', 'OnGetNotifySchema', 'vendor.shop', self::class, 'onGetNotifySchema',
        );
    }
}

    

Deprecated

Замените getPostAuthorsIdsByBlogId

Bitrix\Blog\BlogUser::getPostAuthorsIdsByBlogId($blogId) помечен @deprecated (тикет 24773). Чтобы собрать ID авторов, метод выбирает все посты блога, хотя странице нужны только авторы того, что на ней показано. Докблок советует добавить AUTHOR_ID в select постраничной выборки и собирать ID в том же цикле. Так теперь работает bitrix:blog.blog, в getUsers() у него уходят только авторы текущей страницы. Если выборку трогать не хочется, вызывайте getPostAuthorsIdsByDbFilter() с фильтром страницы.

        <?php declare(strict_types=1);

use Bitrix\Blog\BlogUser;

/** @param list<int> $pagePostIds ID постов, попавших на страницу */
function getPageAuthors(int $blogId, array $pagePostIds): array|false
{
    if ($pagePostIds === []) {
        return [];
    }

    // было: BlogUser::getPostAuthorsIdsByBlogId($blogId), то есть авторы всего блога
    $authorIds = BlogUser::getPostAuthorsIdsByDbFilter(['ID' => $pagePostIds]);

    $blogUser = new BlogUser(3600);
    $blogUser->setBlogId($blogId);

    return $blogUser->getUsers($authorIds);
}

    

В коробке БУС обновление поменяло только копию компонента в папке модуля (install/components), а /bitrix/components/bitrix/blog.blog/component.php по-прежнему вызывает старый метод. Копия компонента в local/ или в вашем namespace правку тоже не получит, переносите её вручную.

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

  • Права в уведомлениях. CAllBlogPost::getCurrentUserType() хранил тип пользователя в статической переменной без привязки к ID, и все, кого проверяли в том же хите после первого, получали его тип. NotifyIm вызывает GetSocNetPostPerms() для каждого упомянутого и для получателей благодарности, а от типа зависит, дадут ли запись в посты для G2/AU и чтение постов открытых групп. Если в посте упомянуты экстранет-пользователь и сотрудник, права второго считались по типу первого. Теперь тип запоминается по userId. Если ваш код за один хит проверяет CBlogPost::GetSocNetPostPerms() для разных пользователей, на портале с модулем intranet ошибка задевала и его, потому что все получали тип первого проверенного.
  • Опечатки в именах полей UF_BLOG_POST_IMPRTNT и UF_IMPRTANT_DATE_END остались, новый ImportantPostQuery их повторяет. В своих фильтрах пишите так же.

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

Символ Статус Чем заменять
Bitrix\Blog\BlogUser::getPostAuthorsIdsByBlogId() Deprecated Bitrix\Blog\BlogUser::getPostAuthorsIdsByDbFilter()

Новая версия вышла — разбор уже в Telegram

В канале @bxmax_updates публикуем каждый свежий разбор: что сломается, что устарело и что появилось в API. Узнаете до того, как обновите прод.

Подписаться

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

landing 26.1600.0 Безопасность Свежее

Landing 26.1300.200–26.1600.0: закрыты дыры с PHP и правами групп, поля редактора стали ES-классами

С прошлого разбора вышли четыре версии landing: 26.1300.200, 26.1400.0, 26.1500.0 и 26.1600.0. В каждой закрыты дыры, от сборки PHP-тега при импорте сайта до лишних прав у участников групп соцсети. Попутно в режиме Битрикс24 превью черновика переехало на маршрут раздела «Сайты», а поля редактора ста…

7 мин
calendar 26.300.0 Безопасность Свежее

Calendar 26.300.0: закрыты дыры в правах на календари и переговорки, дельта в REST

Calendar 26.300.0 закрывает три дыры в правах: перенос события в чужой календарь без права на добавление, подмену чужой брони переговорки через `LOCATION[’OLD’]` или `room_event_id` и добавление в участники проектов, где пользователь не состоит. Для интеграций в `calendar.event.get` появилось инкрем…

2 мин
anonymizer 26.100.100 Рутинное Свежее

Anonymizer 26.100.100: исправлена установка на PostgreSQL

В PostgreSQL слово `END` зарезервировано, поэтому `CREATE TABLE` для `b_anonymizer_replacements` с колонкой `END int NOT NULL` падал с синтаксической ошибкой. `InstallDB()` в этом случае возвращает `false` раньше `registerModule(’anonymizer’)`, и на PostgreSQL модуль не устанавливался. В 26.100.100…

1 мин
timeman 26.400.0 Безопасность Свежее

Timeman 26.400.0: LOGIC в фильтре больше не обходит права в timeman.worktimerecord.list

В timeman 26.400.0 для коробочного Битрикс24 закрыта дыра в REST-методе `timeman.worktimerecord.list`: пользователь без права видеть всех мог через `LOGIC` в фильтре получить записи чужих сотрудников. Ещё боты и другие служебные учётки пропали из `CTimeMan::GetAccess()`, `CTimeMan::GetDirectAccess()…

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

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

на связи

пишет…

Можно закрыть чат и перейти на другую страницу. Когда ответ будет готов, на кнопке Домового появится отметка.

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

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

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

Войти