Автоматическое снятие меток "Новинка" в Bitrix: два подхода
В интернет-магазинах на 1С-Битрикс часто возникает задача регулярно очищать метки "Новинка" у товаров. Рассмотрим два готовых решения для агентов Bitrix, которые автоматически снимают нужные флажки раз в 3 месяца.
Задача
У товаров в инфоблоке есть несколько способов отметки "Новинка":
- Свойство OFFERS — флажок "Новинка" в списке предложений
- Свойство NEW — значение "Да", отдельная метка на товаре
- Свойство CATEGORY — значение "Новое", отвечающее за вывод в блок "Новинки" на главной странице
Первая задача — снимать флажок "Новинка" у свойства OFFERS. Вторая — комплексная очистка свойств NEW и CATEGORY, что используется в линейке решений от Intec, где разделяются понятия метки на товаре (NEW = Да) и попадания в список новинок на главной (CATEGORY = Новое).
Оба решения поддерживают работу с несколькими инфоблоками — достаточно указать их ID в массиве.
Решение 1: Снятие флажка "Новинка" в свойстве OFFERS
Файл local/php_interface/include/uncheck_offers_agent.php:
<?php
class UncheckOffersAgent
{
const IBLOCK_IDS = [16, 17];
const PROPERTY_CODE = 'OFFERS';
const VALUE_TO_REMOVE = 'Новинка';
public static function run(): string
{
CModule::IncludeModule('iblock');
foreach (self::IBLOCK_IDS as $iblockId) {
$targetEnumId = self::getTargetEnumId($iblockId);
if (!$targetEnumId) {
AddMessage2Log("UncheckOffersAgent: значение 'Новинка' не найдено в свойстве OFFERS для ИБ {$iblockId}", 'main');
continue;
}
$rsElements = CIBlockElement::GetList(
['ID' => 'ASC'],
['IBLOCK_ID' => $iblockId],
false,
false,
['ID', 'NAME']
);
while ($element = $rsElements->GetNext()) {
$currentValues = [];
$rsProps = CIBlockElement::GetProperty(
$iblockId,
$element['ID'],
[],
['CODE' => self::PROPERTY_CODE]
);
while ($prop = $rsProps->GetNext()) {
$currentValues[] = $prop['VALUE_ENUM_ID'];
}
if (in_array($targetEnumId, $currentValues)) {
$newValues = array_diff($currentValues, [$targetEnumId]);
CIBlockElement::SetPropertyValuesEx(
$element['ID'],
$iblockId,
[self::PROPERTY_CODE => array_values($newValues)]
);
}
}
}
return self::class . '::run();';
}
private static function getTargetEnumId(int $iblockId): ?int
{
$propertyEnums = CIBlockPropertyEnum::GetList([], [
'IBLOCK_ID' => $iblockId,
'CODE' => self::PROPERTY_CODE,
]);
while ($enum = $propertyEnums->GetNext()) {
if (mb_stripos($enum['VALUE'], self::VALUE_TO_REMOVE) !== false) {
return (int)$enum['ID'];
}
}
return null;
}
}
Решение 2: Снятие флажков NEW и CATEGORY
Этот подход используется в решениях Intec: товар может одновременно иметь метку "Новинка" (свойство NEW = Да) и состоять в категории "Новинки" для вывода на главной (свойство CATEGORY = Новое). При регулярной очистке снимаются оба флажка одновременно.
Файл local/php_interface/include/clear_new_flags_agent.php:
<?php
class ClearNewFlagsAgent
{
const IBLOCK_IDS = [16, 17];
const PROPERTIES = [
'CATEGORY' => 'Новое',
'NEW' => 'Да',
];
public static function run(): string
{
CModule::IncludeModule('iblock');
foreach (self::IBLOCK_IDS as $iblockId) {
foreach (self::PROPERTIES as $code => $valueToRemove) {
self::uncheckValue($iblockId, $code, $valueToRemove);
}
}
return self::class . '::run();';
}
private static function uncheckValue(int $iblockId, string $propertyCode, string $valueToRemove): void
{
$targetEnumId = self::getTargetEnumId($iblockId, $propertyCode, $valueToRemove);
if (!$targetEnumId) {
AddMessage2Log(
"ClearNewFlagsAgent: значение '{$valueToRemove}' не найдено в свойстве {$propertyCode} для ИБ {$iblockId}",
'main'
);
return;
}
$rsElements = CIBlockElement::GetList(
['ID' => 'ASC'],
['IBLOCK_ID' => $iblockId],
false,
false,
['ID', 'NAME']
);
while ($element = $rsElements->GetNext()) {
$currentValues = [];
$rsProps = CIBlockElement::GetProperty(
$iblockId,
$element['ID'],
[],
['CODE' => $propertyCode]
);
while ($prop = $rsProps->GetNext()) {
$currentValues[] = $prop['VALUE_ENUM_ID'];
}
if (in_array($targetEnumId, $currentValues)) {
$newValues = array_diff($currentValues, [$targetEnumId]);
CIBlockElement::SetPropertyValuesEx(
$element['ID'],
$iblockId,
[$propertyCode => array_values($newValues)]
);
}
}
}
private static function getTargetEnumId(int $iblockId, string $propertyCode, string $valueToRemove): ?int
{
$propertyEnums = CIBlockPropertyEnum::GetList([], [
'IBLOCK_ID' => $iblockId,
'CODE' => $propertyCode,
]);
while ($enum = $propertyEnums->GetNext()) {
if (mb_stripos($enum['VALUE'], $valueToRemove) !== false) {
return (int)$enum['ID'];
}
}
return null;
}
}
Подключение и регистрация агентов
Файл local/php_interface/init.php — автозагрузка классов:
<?php
require_once __DIR__ . '/include/uncheck_offers_agent.php';
require_once __DIR__ . '/include/clear_new_flags_agent.php';
Регистрация агентов на 90 дней (запустить однократно):
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';
$interval = 90 * 24 * 60 * 60; // 7776000 секунд
CAgent::AddAgent(
'UncheckOffersAgent::run();',
'',
'N',
$interval,
'',
'Y',
'',
100
);
CAgent::AddAgent(
'ClearNewFlagsAgent::run();',
'',
'N',
$interval,
'',
'Y',
'',
100
);
Как это работает
- Агент проходит по всем указанным ID инфоблоков
- Для каждого инфоблока находит ID значения списка (например, "Новинка" в свойстве OFFERS)
- Перебирает все элементы инфоблока, проверяя, установлен ли нужный флажок
- Если флажок установлен — удаляет его из множества значений свойства и сохраняет
Оба агента возвращают строку с именем своего метода (ClassName::run();), благодаря чему Bitrix автоматически перезапускает их через заданный интервал.
Настройка под свой проект
Достаточно изменить константы в начале каждого класса:
- IBLOCK_IDS — массив ID инфоблоков, в которых нужно снимать флажки
- Для UncheckOffersAgent:
PROPERTY_CODEиVALUE_TO_REMOVE— код свойства и значение для поиска - Для ClearNewFlagsAgent: массив
PROPERTIES— пары код свойства => значение для удаления