Набросал такой код. Местами сыроват, можно написать оптимальнее.
public function getRubricTree() {
$sel = new selector('pages');
$sel->types('hierarchy-type')->name('catalog', 'category');
$arTree = array();
$arRoots = array();
$arCategories = array();
$hierarchy = umiHierarchy::getInstance();
foreach($sel as $category) {
if(!$category instanceof umiHierarchyElement)
continue;
$parent_id = $category->getParentId();
$category_id = $category->getId();
if($parent_id == 0) {
$arRoots[] = $category_id;
}
if(!isset($arTree[$parent_id])) {
$arTree[$parent_id] = array();
}
$arTree[$parent_id][] = $category_id;
$arCategory = $this->prepareCategory($category, $hierarchy);
$arCategories[$category_id] = $arCategory;
}
$return = array();
foreach($arRoots as $root_id) {
$return[] = $this->renderCategory($root_id, $arTree, $arCategories);
}
return array(
'items' => array('nodes:item' => $return)
);
}
public function prepareCategory($category, $hierarchy) {
$category_id = $category->getId();
$arCategory = array(
'attribute:id' => $category_id,
'attribute:name' => $category->getName(),
'attribute:link' => $hierarchy->getPathById($category_id),
);
return $arCategory;
}
public function renderCategory($id, $arTree, $arCategories) {
$items = array();
$line = isset($arCategories[$id]) ? $arCategories[$id] : array();
if(count($arTree[$id]) > 0) {
foreach($arTree[$id] as $child_id) {
$items[] = $this->renderCategory($child_id, $arTree, $arCategories);
}
}
if(count($items) > 0)
$line['items'] = array('nodes:item' => $items);
return self::parseTemplate('default', $line);
}
}
if(count($items) > 0)
$line['items'] = array('nodes:item' => $items);
return self::parseTemplate('default', $line);
}
Работает только в xslt-шаблонизаторе.
Пример работы макроса - http://demo.umispec.ru/udata://custom/getRubricTree/
public function getRubricTree($root_category_id, $i_need_deep = 1) {
if((string) $root_category_id != '0') $root_category_id = $this->analyzeRequiredPath($root_category_id);
if (!$i_need_deep) $i_need_deep = intval(getRequest('param2'));
if (!$i_need_deep) $i_need_deep = 0;
$i_need_deep = intval($i_need_deep);
if ($i_need_deep === -1) $i_need_deep = 100;
$sel = new selector('pages');
$sel->types('hierarchy-type')->name('catalog', 'category');
$sel->where('hierarchy')->page($root_category_id)->childs($i_need_deep);
$arTree = array();
$arRoots = array();
$arCategories = array();
$hierarchy = umiHierarchy::getInstance();
foreach($sel as $category) {
if(!$category instanceof umiHierarchyElement)
continue;
$parent_id = $category->getParentId();
$category_id = $category->getId();
if($parent_id == $root_category_id) {
$arRoots[] = $category_id;
}
if(!isset($arTree[$parent_id])) {
$arTree[$parent_id] = array();
}
$arTree[$parent_id][] = $category_id;
$arCategory = $this->prepareCategory($category, $hierarchy);
$arCategories[$category_id] = $arCategory;
}
$return = array();
foreach($arRoots as $root_id) {
$return[] = $this->renderCategory($root_id, $arTree, $arCategories);
}
return array(
'items' => array('nodes:item' => $return)
);
}
public function prepareCategory($category, $hierarchy) {
$category_id = $category->getId();
$arCategory = array(
'attribute:id' => $category_id,
'attribute:name' => $category->getName(),
'attribute:link' => $hierarchy->getPathById($category_id),
);
return $arCategory;
}
public function renderCategory($id, $arTree, $arCategories) {
$items = array();
$line = isset($arCategories[$id]) ? $arCategories[$id] : array();
if(count($arTree[$id]) > 0) {
foreach($arTree[$id] as $child_id) {
$items[] = $this->renderCategory($child_id, $arTree, $arCategories);
}
}
if(count($items) > 0)
$line['items'] = array('nodes:item' => $items);
return self::parseTemplate('default', $line);
}
Версия 2.0 с возможностью выбора начального уровня и глубины. Оптимально сочетается с custom/xsltCache для построения меню на сайте. За примерами - в ЛС,