Based on the solution provided by Marius and some code I had locally i put the below together.
Since the categories are added via an observer we simply disable the default observer and create own own version based on the original that adds the new filters in and pops the default categories under a "By Category" node when the Category level is 2.
<page_block_html_topmenu_gethtml_before>
<observers>
<catalog_add_topmenu_items>
<type>disabled</type>
</catalog_add_topmenu_items>
<neo_topnav>
<class>neo_topnav/observer</class>
<method>pageBlockHtmlTopmenuGethtmlBefore</method>
</neo_topnav>
</observers>
</page_block_html_topmenu_gethtml_before>
/**
* Adds catalog categories to top menu
*
* @param Varien_Event_Observer $observer
*/
public function pageBlockHtmlTopmenuGethtmlBefore(Varien_Event_Observer $observer)
{
$block = $observer->getEvent()->getBlock();
$block->addCacheTag(Mage_Catalog_Model_Category::CACHE_TAG);
$this->_addCategoriesToMenu(
Mage::helper('catalog/category')->getStoreCategories(), $observer->getMenu(), $block, true
);
}
/**
* Recursively adds categories to top menu
*
* @param Varien_Data_Tree_Node_Collection|array $categories
* @param Varien_Data_Tree_Node $parentCategoryNode
* @param Mage_Page_Block_Html_Topmenu $menuBlock
* @param bool $addTags
*/
protected function _addCategoriesToMenu($categories, $parentCategoryNode, $menuBlock, $addTags = false)
{
$categoryModel = Mage::getModel('catalog/category');
foreach ($categories as $category) {
if (!$category->getIsActive()) {
continue;
}
$nodeId = 'category-node-' . $category->getId();
$categoryModel->setId($category->getId());
if ($addTags) {
$menuBlock->addModelTags($categoryModel);
}
$tree = $parentCategoryNode->getTree();
$categoryData = array(
'name' => $category->getName(),
'id' => $nodeId,
'url' => Mage::helper('catalog/category')->getCategoryUrl($category),
'is_active' => $this->_isActiveMenuCategory($category)
);
$categoryNode = new Varien_Data_Tree_Node($categoryData, 'id', $tree, $parentCategoryNode);
$parentCategoryNode->addChild($categoryNode);
$flatHelper = Mage::helper('catalog/category_flat');
if ($flatHelper->isEnabled() && $flatHelper->isBuilt(true)) {
$subcategories = (array)$category->getChildrenNodes();
} else {
$subcategories = $category->getChildren();
}
switch($category->getLevel()){
case 2:
$byCategoryNode = $this->_addShopByCategory($parentCategoryNode, $category, $tree, $categoryNode);
$this->_addCategoriesToMenu($subcategories, $byCategoryNode, $menuBlock, $addTags);
$this->_addFiltersToMenu($category->getId(),$categoryNode,$tree,$parentCategoryNode);
break;
default:
$this->_addCategoriesToMenu($subcategories, $categoryNode, $menuBlock, $addTags);
break;
}
}
}
/**
* @param $parentCategoryNode
* @param $category
* @param $tree
* @param $categoryNode
* @return Varien_Data_Tree_Node
*/
protected function _addShopByCategory($parentCategoryNode, $category, $tree, $categoryNode)
{
$byCategoryNodeId = 'by-category-node-' . $category->getId();
$byCategoryData = array(
'name' => Mage::helper('neo_topnav')->__('By Category'),
'id' => $byCategoryNodeId,
'url' => '#',
'is_active' => false
);
$byCategoryNode = new Varien_Data_Tree_Node($byCategoryData, 'id', $tree, $parentCategoryNode);
$categoryNode->addChild($byCategoryNode);
return $byCategoryNode;
}
/**
* @param $id
* @param $category
* @param $tree
* @param $parentCategoryNode
*/
function _addFiltersToMenu($id,$category,$tree,$parentCategoryNode){
$attributes = $this->getAttributes($id);
$mainUrl = $category->getUrl();
foreach ($attributes as $attribute) {
//get the options for each attribute
$options = $attribute->getSource()->getAllOptions();
if (count($options) > 0) {
//add "By ..." menu item - non clickable
$attrNodeId = 'attribute-'.$id.'-'.$attribute->getId();
$data = array(
'name' => Mage::helper('neo_topnav')->__('By %s', $attribute->getFrontendLabel()),
'id' => $attrNodeId,
'url' => '#',
'is_active' => false
);
$attrNode = new Varien_Data_Tree_Node($data, 'id', $tree,$parentCategoryNode);
//for each option add a new sub menu
foreach ($options as $option) {
if ($option['value']) {
$optionNodeId = 'attribute-'.$id.'-'.$attribute->getId().'-'.$option['value'];
$data = array(
'name' => $option['label'],
'id' => $optionNodeId,
'url' => $mainUrl.'?'.$attribute->getAttributeCode().'='.$option['value'],
'is_active' => false
);
$optionNode = new Varien_Data_Tree_Node($data, 'id', $tree,$parentCategoryNode);
$attrNode->addChild($optionNode);
}
}
$category->addChild($attrNode);
}
}
}
//get allowed attributes in that category
public function getAttributes($categoryId) {
$layer = Mage::getModel("catalog/layer");
$layer->setCurrentCategory(Mage::getModel('catalog/category')->load($categoryId));
$validAttributes = array();
foreach ($layer->getFilterableAttributes() as $attribute) {
//allow only select attributes - you can implement your additional filters here
if ($attribute->getFrontendInput() == 'select'){
$validAttributes[] = $attribute;
}
}
return $validAttributes;
}
/**
* Checks whether category belongs to active category's path
*
* @param Varien_Data_Tree_Node $category
* @return bool
*/
protected function _isActiveMenuCategory($category)
{
$catalogLayer = Mage::getSingleton('catalog/layer');
if (!$catalogLayer) {
return false;
}
$currentCategory = $catalogLayer->getCurrentCategory();
if (!$currentCategory) {
return false;
}
$categoryPathIds = explode(',', $currentCategory->getPathInStore());
return in_array($category->getId(), $categoryPathIds);
}
}
Best Answer
i did myself with the following code and just sharing the code which may be helpful to others here