[spoiler]
Постановка задачи
В издательстве используется "самописная" учетная система, в которой товары (в основном, книги) не имеют разделов-родителей, а обладают набором свойств - "жанр", "серия", "возраст", "бренд" и т.п.; при этом каждое значение свойства фактически является родителем для тех или иных товаров, например:
| Книга "Огниво": жанр - "Художественная литература для детей", автор - "Андерсен", серия - "В гостях у сказки" |
| Книга "Лунтик. Водная раскраска": тип - "Раскраска", жанр - "Подготовка к школе", бренд - "Лунтик" |
Идея
Как известно, в архитектуре "Битрикса" все рассчитано на то, что есть древовидная структура каталога (инфоблока) - разделы-родители и "вложенные" в них элементы (товары). Свойства в "Битриксе" не могут быть родителями элементов инфоблока. Но почему бы использовать значения свойств - в качестве названий разделов каталога? На основе этой идеи мы составили схему регулярного импорта данных из учетной системы издательства - в "Битрикс". Для того, чтобы отличать "ветки" каталога, созданные на основе свойств, мы использовали "хэштэги" наименований свойств - в качестве названий разделов. Часть схемы приведена ниже: красным - разделы 1-го уровня, оранжевым - разделы 2-го уровня ("хэштэги", созданные на основе свойств), желтым - разделы 3-го уровня, зеленым - товары.

Реализация
Поскольку каталог издательства создается и обновляется собственным скриптом импорта, мы добавили функции, которые создают и обновляют структуру разделов каталога на основе значений свойств товаров и привязывают товары к соответствующим разделам. Полные коды всех функций приводить здесь не буду, основных моментов два, (1) - привязка товаров c созданием новых разделов внутри "хэштэгов" и (2) - обновление структуры разделов:
Привязка товаров и создание новых разделов внутри "хэштэгов":
function SetElementHashSections($arElement,$arProperties,$arBrand) {
$arHashSectionsResult = array('RESULT'=>true,'MESSAGE'=>'');
if($arElement['IBLOCK_SECTION_ID']) {
if(!is_array($arElement['IBLOCK_SECTION_ID']))
$arElementGroups = $arElement['IBLOCK_SECTION_ID'] = array($arElement['IBLOCK_SECTION_ID']);
else
$arElementGroups = $arElement['IBLOCK_SECTION_ID'];
foreach($arElement['IBLOCK_SECTION_ID'] as $iblock_section_id) {
$nav = CIBlockSection::GetNavChain(false, $iblock_section_id);
while($ar_nav = $nav->GetNext())
$sect_path[] = $ar_nav['ID'];
$rsHashSections = CIBlockSection::GetList(
array(),
array(
"NAME"=>"#%",
"SECTION_ID"=>$sect_path[0],
"IBLOCK_ID"=>$arElement['IBLOCK_ID']
)
);
while($arHashSection = $rsHashSections->GetNext()) {
$arHashName = explode('/',$arHashSection['NAME']);
$arHashName[0] = substr($arHashName[0],1);
foreach($arHashName as $depth=>$hashname) {
$PropCode = $arProperties[$hashname];
if($PropCode == 'BRAND')
$PropValue = $arBrand[$arElement['PROPERTY_VALUES'][$PropCode]];
else
$PropValue = $arElement['PROPERTY_VALUES'][$PropCode];
if($PropCode && $PropValue) {
if(is_array($PropValue))
$arPropValue=$PropValue;
else
$arPropValue=array($PropValue);
foreach($arPropValue as $PropValue) {
$rsHashSubSection = CIBlockSection::GetList(
array(),
array(
"=NAME" => $PropValue,
"SECTION_ID" => ($depth == 0)? $arHashSection['ID']:$subsection_parent_id,
"IBLOCK_ID"=>$arElement['IBLOCK_ID']
)
);
if($arHashSubSection = $rsHashSubSection->GetNext()) {
$arElementGroups[] = $subsection_id = $arHashSubSection["ID"];
}
else {
$bs = new CIBlockSection;
$subsection_id = $bs->Add(array(
"ACTIVE" => 'Y',
"NAME" => $PropValue,
"CODE" => GetSymCode($PropValue),
"IBLOCK_SECTION_ID" => ($depth == 0)? $arHashSection['ID']:$subsection_parent_id,
"IBLOCK_ID" => $arElement['IBLOCK_ID']
));
if($subsection_id) {
$arElementGroups[] = $subsection_id;
$arHashSectionsResult = array(
'RESULT' => true,
'MESSAGE' => "Создан подраздел \"".
$PropValue.
"\" внутри хэштэга ".$arHashSection['NAME']."\n"
);
}
else
$arHashSectionsResult = array(
'RESULT' => false,
'MESSAGE' => "Создание подраздела \"".
$PropValue.
"\" внутри хэштэга ".$arHashSection['NAME']." не получилось: ".
$bs->LAST_ERROR."\n"
);
}
}
}
if($depth == 0)
$subsection_parent_id = $subsection_id;
}
}
}
if(count($arElementGroups)>1)
CIBlockElement::SetElementSection($arElement['ID'], $arElementGroups);
}
return $arHashSectionsResult;
} |
function MakeHashSubSectionsActive($IBLOCK_ID) {
$rsHashSections = CIBlockSection::GetList(array(),array("NAME"=>"#%","DEPTH_LEVEL"=>2,"IBLOCK_ID"=>$IBLOCK_ID));
while($arHashSection = $rsHashSections->GetNext()) {
$rsHashSubSection = CIBlockSection::GetList(
array(),
array(
"SECTION_ID"=>$arHashSection['ID'],
"IBLOCK_ID"=>$arElement['IBLOCK_ID']
),
true
);
while($arHashSubSection = $rsHashSubSection->GetNext()) {
if(!$arHashSubSection['ELEMENT_CNT'] && $arHashSubSection['ACTIVE']=='Y') {
$bs = new CIBlockSection;
$bs->Update($arHashSubSection['ID'], array("ACTIVE"=>"N"));
echo "ОК Деактивирован подраздел \"".$arHashSubSection['NAME']."\" хэштэга ".$arHashSection['NAME']."\n";
}
elseif($arHashSubSection['ELEMENT_CNT'] && $arHashSubSection['ACTIVE']=='N') {
$bs = new CIBlockSection;
$bs->Update($arHashSubSection['ID'], array("ACTIVE"=>"Y"));
echo "ОК Активирован подраздел \"".$arHashSubSection['NAME']."\" хэштэга ".$arHashSection['NAME']."\n";
}
}
}
}
|