Версия ядра: 20.600.100
Баг с версионностью в документообороте заглчается в том, что при откате на более старую версию данные не пишутся в таблицу b_iblock_iproperty.
Решение. Привязываемся к событию обновления элемента OnAfterIBlockElementUpdate.
public static function OnAfterIBlockElementUpdateHandler(&$arFields)
{
// Это мой модуль, у вас он будет свой, если вы используете моудли для регистрации событий.
// Или не быть вообще, если пишите в init.php
// Loader::includeModule('engine');
$items = ElementTable::getLastVersions('Structure', $arFields['WF_STATUS_ID']);
$page = ElementStructureTable::query()
->addSelect('NAME')
->addSelect('CODE')
->addSelect('ID')
->addSelect('WF_PARENT_ELEMENT_ID')
->whereIn('ID', array_column($items, 'MAX_ID'))
->fetchObject();
$iblock = new ElementValues($page->getIblockId(), $page->getId());
$values['TITLE'] = $iblock->getValue('ELEMENT_META_TITLE');
$values['KEYWORDS'] = $iblock->getValue('ELEMENT_META_KEYWORDS');
$values['DESCRIPTION'] = $iblock->getValue('ELEMENT_META_DESCRIPTION');
$allElement = self::getListVersions($arFields['ID']);
$arId = [];
foreach ($allElement as $element) {
$arId[] = $element['ID'];
}
$iProps = InheritedPropertyTable::query()
->addSelect('*')
->where('IBLOCK_ID', $arFields['IBLOCK_ID'])
->whereIn('ENTITY_ID', $arId)
->addOrder('ENTITY_ID','DESC')
->fetchAll();
$arIProp = [];
$maxKey = -1;
if( $page->getId() == $iProps[0]['ENTITY_ID']) {
return true;
}
foreach ($iProps as $itemProp) {
if ($itemProp['ENTITY_ID'] >= $maxKey) {
$maxKey = $itemProp['ENTITY_ID'];
$arIProp[] = $itemProp;
InheritedPropertyTable::createObject()
->setIblockId($itemProp['IBLOCK_ID'])
->setCode($itemProp['CODE'])
->setEntityType($itemProp['ENTITY_TYPE'])
->setEntityId($page->getId())
->setTemplate($itemProp['TEMPLATE'])
->save();
}
}
}
/**
* Получаем список версий
* @param false $parentInputId
* @return array
* @throws \Bitrix\Main\ArgumentException
* @throws \Bitrix\Main\ObjectPropertyException
* @throws \Bitrix\Main\SystemException
*/
public static function getListVersions($parentInputId = false): array
{
$query = \Bitrix\Iblock\ElementTable::query()
->addSelect('WF_STATUS_ID')
->addSelect('WF_PARENT_ELEMENT_ID')
->addSelect('ACTIVE')
->addSelect('ID')
->addSelect('NAME')
->addSelect('CODE')
->addSelect('IBLOCK_ID')
->addOrder('ID','ASC');
if ($parentInputId) {
$query->where('WF_PARENT_ELEMENT_ID', $parentInputId);
} else {
$query->where('WF_PARENT_ELEMENT_ID', '>', 0);
}
$items = $query->fetchAll();
$result = [];
foreach ($items as $item) {
$result[] = $item;
}
/**
* Фильтруем, оставляя только активные элементы
* Фильтр в запросе работать не будет, поскольку станут возвращаться
* активные, но неактуальные (старые) версии
*/
return array_filter($result, function ($item) {
return $item['ACTIVE'] === 'Y';
});
}
Не забываем подключать наши классы
use Bitrix\Iblock\InheritedProperty\ElementValues;
use Bitrix\Iblock\InheritedPropertyTable;
use Bitrix\Iblock\Elements\ElementStructureTable;
use Bitrix\Iblock\InheritedPropertyTable;