Instantly share code, notes, and snippets.
Created
January 22, 2016 03:23
-
Save amacgregor/1c1ed1626d5804646139 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Catalog navigation | |
* | |
* @category Mage | |
* @package Mage_Catalog | |
* @author Magento Core Team <core@magentocommerce.com> | |
*/ | |
class Mage_Catalog_Block_Navigation extends Mage_Core_Block_Template | |
{ | |
/** | |
* Category instance | |
* | |
* @var Mage_Catalog_Model_Category | |
*/ | |
protected $_categoryInstance; | |
/** | |
* Current category key | |
* | |
* @var string | |
*/ | |
protected $_currentCategoryKey; | |
/** | |
* Array of level position counters | |
* | |
* @var array | |
*/ | |
protected $_itemLevelPositions = array(); | |
/** | |
* Current child categories collection | |
* | |
* @var Mage_Catalog_Model_Resource_Category_Collection | |
*/ | |
protected $_currentChildCategories; | |
/** | |
* Set cache data | |
*/ | |
protected function _construct() | |
{ | |
$this->addData(array('cache_lifetime' => false)); | |
$this->addCacheTag(array( | |
Mage_Catalog_Model_Category::CACHE_TAG, | |
Mage_Core_Model_Store_Group::CACHE_TAG | |
)); | |
} | |
/** | |
* Get Key pieces for caching block content | |
* | |
* @return array | |
*/ | |
public function getCacheKeyInfo() | |
{ | |
$shortCacheId = array( | |
'CATALOG_NAVIGATION', | |
Mage::app()->getStore()->getId(), | |
Mage::getDesign()->getPackageName(), | |
Mage::getDesign()->getTheme('template'), | |
Mage::getSingleton('customer/session')->getCustomerGroupId(), | |
'template' => $this->getTemplate(), | |
'name' => $this->getNameInLayout(), | |
$this->getCurrenCategoryKey() | |
); | |
$cacheId = $shortCacheId; | |
$shortCacheId = array_values($shortCacheId); | |
$shortCacheId = implode('|', $shortCacheId); | |
$shortCacheId = md5($shortCacheId); | |
$cacheId['category_path'] = $this->getCurrenCategoryKey(); | |
$cacheId['short_cache_id'] = $shortCacheId; | |
return $cacheId; | |
} | |
/** | |
* Get current category key | |
* | |
* @return mixed | |
*/ | |
public function getCurrenCategoryKey() | |
{ | |
if (!$this->_currentCategoryKey) { | |
$category = Mage::registry('current_category'); | |
if ($category) { | |
$this->_currentCategoryKey = $category->getPath(); | |
} else { | |
$this->_currentCategoryKey = Mage::app()->getStore()->getRootCategoryId(); | |
} | |
} | |
return $this->_currentCategoryKey; | |
} | |
/** | |
* Get categories of current store | |
* | |
* @return Varien_Data_Tree_Node_Collection | |
*/ | |
public function getStoreCategories() | |
{ | |
$helper = Mage::helper('catalog/category'); | |
return $helper->getStoreCategories(); | |
} | |
/** | |
* Retrieve child categories of current category | |
* | |
* @return Mage_Catalog_Model_Resource_Category_Collection | |
*/ | |
public function getCurrentChildCategories() | |
{ | |
if (null === $this->_currentChildCategories) { | |
$layer = Mage::getSingleton('catalog/layer'); | |
$category = $layer->getCurrentCategory(); | |
$this->_currentChildCategories = $category->getChildrenCategories(); | |
$productCollection = Mage::getResourceModel('catalog/product_collection'); | |
$layer->prepareProductCollection($productCollection); | |
$productCollection->addCountToCategories($this->_currentChildCategories); | |
} | |
return $this->_currentChildCategories; | |
} | |
/** | |
* Check whether specified category is active | |
* | |
* @param Varien_Object $category | |
* @return bool | |
*/ | |
public function isCategoryActive($category) | |
{ | |
return $this->getCurrentCategory() | |
? in_array($category->getId(), $this->getCurrentCategory()->getPathIds()) : false; | |
} | |
/** | |
* Retrieve category instance | |
* | |
* @return Mage_Catalog_Model_Category | |
*/ | |
protected function _getCategoryInstance() | |
{ | |
if (is_null($this->_categoryInstance)) { | |
$this->_categoryInstance = Mage::getModel('catalog/category'); | |
} | |
return $this->_categoryInstance; | |
} | |
/** | |
* Get url for category data | |
* | |
* @param Mage_Catalog_Model_Category $category | |
* @return string | |
*/ | |
public function getCategoryUrl($category) | |
{ | |
if ($category instanceof Mage_Catalog_Model_Category) { | |
$url = $category->getUrl(); | |
} else { | |
$url = $this->_getCategoryInstance() | |
->setData($category->getData()) | |
->getUrl(); | |
} | |
return $url; | |
} | |
/** | |
* Return item position representation in menu tree | |
* | |
* @param int $level | |
* @return string | |
*/ | |
protected function _getItemPosition($level) | |
{ | |
if ($level == 0) { | |
$zeroLevelPosition = isset($this->_itemLevelPositions[$level]) ? $this->_itemLevelPositions[$level] + 1 : 1; | |
$this->_itemLevelPositions = array(); | |
$this->_itemLevelPositions[$level] = $zeroLevelPosition; | |
} elseif (isset($this->_itemLevelPositions[$level])) { | |
$this->_itemLevelPositions[$level]++; | |
} else { | |
$this->_itemLevelPositions[$level] = 1; | |
} | |
$position = array(); | |
for($i = 0; $i <= $level; $i++) { | |
if (isset($this->_itemLevelPositions[$i])) { | |
$position[] = $this->_itemLevelPositions[$i]; | |
} | |
} | |
return implode('-', $position); | |
} | |
/** | |
* Render category to html | |
* | |
* @param Mage_Catalog_Model_Category $category | |
* @param int Nesting level number | |
* @param boolean Whether ot not this item is last, affects list item class | |
* @param boolean Whether ot not this item is first, affects list item class | |
* @param boolean Whether ot not this item is outermost, affects list item class | |
* @param string Extra class of outermost list items | |
* @param string If specified wraps children list in div with this class | |
* @param boolean Whether ot not to add on* attributes to list item | |
* @return string | |
*/ | |
protected function _renderCategoryMenuItemHtml($category, $level = 0, $isLast = false, $isFirst = false, | |
$isOutermost = false, $outermostItemClass = '', $childrenWrapClass = '', $noEventAttributes = false) | |
{ | |
if (!$category->getIsActive()) { | |
return ''; | |
} | |
$html = array(); | |
// get all children | |
// If Flat Data enabled then use it but only on frontend | |
$flatHelper = Mage::helper('catalog/category_flat'); | |
if ($flatHelper->isAvailable() && $flatHelper->isBuilt(true) && !Mage::app()->getStore()->isAdmin()) { | |
$children = (array)$category->getChildrenNodes(); | |
$childrenCount = count($children); | |
} else { | |
$children = $category->getChildren(); | |
$childrenCount = $children->count(); | |
} | |
$hasChildren = ($children && $childrenCount); | |
// select active children | |
$activeChildren = array(); | |
foreach ($children as $child) { | |
if ($child->getIsActive()) { | |
$activeChildren[] = $child; | |
} | |
} | |
$activeChildrenCount = count($activeChildren); | |
$hasActiveChildren = ($activeChildrenCount > 0); | |
// prepare list item html classes | |
$classes = array(); | |
$classes[] = 'level' . $level; | |
$classes[] = 'nav-' . $this->_getItemPosition($level); | |
if ($this->isCategoryActive($category)) { | |
$classes[] = 'active'; | |
} | |
$linkClass = ''; | |
if ($isOutermost && $outermostItemClass) { | |
$classes[] = $outermostItemClass; | |
$linkClass = ' class="'.$outermostItemClass.'"'; | |
} | |
if ($isFirst) { | |
$classes[] = 'first'; | |
} | |
if ($isLast) { | |
$classes[] = 'last'; | |
} | |
if ($hasActiveChildren) { | |
$classes[] = 'parent'; | |
} | |
// prepare list item attributes | |
$attributes = array(); | |
if (count($classes) > 0) { | |
$attributes['class'] = implode(' ', $classes); | |
} | |
if ($hasActiveChildren && !$noEventAttributes) { | |
$attributes['onmouseover'] = 'toggleMenu(this,1)'; | |
$attributes['onmouseout'] = 'toggleMenu(this,0)'; | |
} | |
// assemble list item with attributes | |
$htmlLi = '<li'; | |
foreach ($attributes as $attrName => $attrValue) { | |
$htmlLi .= ' ' . $attrName . '="' . str_replace('"', '\"', $attrValue) . '"'; | |
} | |
$htmlLi .= '>'; | |
$html[] = $htmlLi; | |
$html[] = '<a href="'.$this->getCategoryUrl($category).'"'.$linkClass.'>'; | |
$html[] = '<span>' . $this->escapeHtml($category->getName()) . '</span>'; | |
$html[] = '</a>'; | |
// render children | |
$htmlChildren = ''; | |
$j = 0; | |
foreach ($activeChildren as $child) { | |
$htmlChildren .= $this->_renderCategoryMenuItemHtml( | |
$child, | |
($level + 1), | |
($j == $activeChildrenCount - 1), | |
($j == 0), | |
false, | |
$outermostItemClass, | |
$childrenWrapClass, | |
$noEventAttributes | |
); | |
$j++; | |
} | |
if (!empty($htmlChildren)) { | |
if ($childrenWrapClass) { | |
$html[] = '<div class="' . $childrenWrapClass . '">'; | |
} | |
$html[] = '<ul class="level' . $level . '">'; | |
$html[] = $htmlChildren; | |
$html[] = '</ul>'; | |
if ($childrenWrapClass) { | |
$html[] = '</div>'; | |
} | |
} | |
$html[] = '</li>'; | |
$html = implode("\n", $html); | |
return $html; | |
} | |
/** | |
* Render category to html | |
* | |
* @deprecated deprecated after 1.4 | |
* @param Mage_Catalog_Model_Category $category | |
* @param int Nesting level number | |
* @param boolean Whether ot not this item is last, affects list item class | |
* @return string | |
*/ | |
public function drawItem($category, $level = 0, $last = false) | |
{ | |
return $this->_renderCategoryMenuItemHtml($category, $level, $last); | |
} | |
/** | |
* Enter description here... | |
* | |
* @return Mage_Catalog_Model_Category | |
*/ | |
public function getCurrentCategory() | |
{ | |
if (Mage::getSingleton('catalog/layer')) { | |
return Mage::getSingleton('catalog/layer')->getCurrentCategory(); | |
} | |
return false; | |
} | |
/** | |
* Enter description here... | |
* | |
* @return string | |
*/ | |
public function getCurrentCategoryPath() | |
{ | |
if ($this->getCurrentCategory()) { | |
return explode(',', $this->getCurrentCategory()->getPathInStore()); | |
} | |
return array(); | |
} | |
/** | |
* Enter description here... | |
* | |
* @param Mage_Catalog_Model_Category $category | |
* @return string | |
*/ | |
public function drawOpenCategoryItem($category) { | |
$html = ''; | |
if (!$category->getIsActive()) { | |
return $html; | |
} | |
$html .= '<li'; | |
if ($this->isCategoryActive($category)) { | |
$html .= ' class="active"'; | |
} | |
$html .= '>' . "\n"; | |
$html .= '<a href="'.$this->getCategoryUrl($category).'">' | |
. '<span>' . $this->escapeHtml($category->getName()) . '</span></a>' . "\n"; | |
if (in_array($category->getId(), $this->getCurrentCategoryPath())) { | |
$children = $category->getChildren(); | |
$hasChildren = $children && $children->count(); | |
if ($hasChildren) { | |
$htmlChildren = ''; | |
foreach ($children as $child) { | |
$htmlChildren .= $this->drawOpenCategoryItem($child); | |
} | |
if (!empty($htmlChildren)) { | |
$html .= '<ul>' . "\n" . $htmlChildren . '</ul>'; | |
} | |
} | |
} | |
$html .= '</li>'."\n"; | |
return $html; | |
} | |
/** | |
* Render categories menu in HTML | |
* | |
* @param int Level number for list item class to start from | |
* @param string Extra class of outermost list items | |
* @param string If specified wraps children list in div with this class | |
* @return string | |
*/ | |
public function renderCategoriesMenuHtml($level = 0, $outermostItemClass = '', $childrenWrapClass = '') | |
{ | |
$activeCategories = array(); | |
foreach ($this->getStoreCategories() as $child) { | |
if ($child->getIsActive()) { | |
$activeCategories[] = $child; | |
} | |
} | |
$activeCategoriesCount = count($activeCategories); | |
$hasActiveCategoriesCount = ($activeCategoriesCount > 0); | |
if (!$hasActiveCategoriesCount) { | |
return ''; | |
} | |
$html = ''; | |
$j = 0; | |
foreach ($activeCategories as $category) { | |
$html .= $this->_renderCategoryMenuItemHtml( | |
$category, | |
$level, | |
($j == $activeCategoriesCount - 1), | |
($j == 0), | |
true, | |
$outermostItemClass, | |
$childrenWrapClass, | |
true | |
); | |
$j++; | |
} | |
return $html; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment