* @copyright Copyright (c) 2011 CODNITIVE Co. (http://www.codnitive.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ class Codnitive_Sidenav_Block_Navigation extends Mage_Catalog_Block_Navigation { /** * Extension config model object * */ protected $_config; protected $_productsCount; protected $_refreshData; protected $_filename = 'var/category_navigation_list.txt'; /** * Construct parent and define $_config * */ protected function _construct() { parent::_construct(); $this->_config = Mage::getModel('sidenav/config'); if (file_exists($this->_filename)) { $dateDiff = idate('H') - idate('H', filemtime($this->_filename)); $this->_refreshData = abs($dateDiff) >= 1 ? true : false; $this->_productsCount = json_decode(file_get_contents($this->_filename, true), true); } else { $this->_refreshData = true; } } /** * Retrieves extension's configuration settings * * @return Codnitive_Sidenav_Model_Config */ public function getConfig() { if ($this->_config === null) { $this->_config = Mage::getModel('sidenav/config'); } return $this->_config; } /** * Get store categories navigation menu * * @return string */ public function getCategoriesNavMenu() { $navigationMenu = $this->renderCategoriesMenuHtml(0); return $navigationMenu ? $navigationMenu : false; } /** * We set cache to null when product direct access option is enabled and customer * is in product page to avoid wrong category tree showing with enabled caches * * Adds 1 extra second to page load * Ultra version has caching and best performance * * @return null */ public function getCacheLifetime() { $condition = (Mage::registry('current_product') !== null) && ($this->getConfig()->activeProductCategoriesInDirectAccess()); if ($condition) { return null; } return parent::getCacheLifetime(); } /** * Get catagories of current store * * @return Varien_Data_Tree_Node_Collection */ public function getStoreCategories() { return Mage::helper('sidenav/category')->getStoreCategories(); } /** * Returns category model * * @return Codnitive_Sidenav_Model_Category */ protected function _getCategoryModel() { return Mage::getModel('sidenav/catalog_category'); } /** * Retruns data helper * * @return Codnitive_Sidenav_Helper_Data */ protected function _getHelper() { return Mage::helper('sidenav'); } /** * 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 ''; } $config = $this->getConfig(); $html = array(); $expanded = null; $ulThumb = ''; $image = ''; $thumb = ''; $htmlLi = ''; // get all children if (Mage::helper('catalog/category_flat')->isEnabled()) { $children = (array) $category->getChildrenNodes(); $childrenCount = count($children); } else { $children = $category->getChildren(); if (!$this->_getHelper()->isSearchResultsPage()) { $childrenCount = $children->count(); } else { if (is_string($children)) { $children = explode(',', $children); } $childrenCount = count($children); } } // 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 $thumbWidth = 14; $thumbHeight = 14; $thumbPosition = $config->getThumbPosition(); $liMarginLeft = 0; $ulMarginLeft = 5; $ulPaddingLeft = 10; $collapsibleClass = ''; if ($config->isCollapsible()) { $collapsibleClass = ' collapsible'; } // add collapsible arrow and wrraper $arrow = ''; $extraStyle = ''; $collapsibleIconPosition = $config->getCollapsibleIconPosition(); if ($config->isCollapsible()) { $width = $config->getCollapsibleIconType() === 'arrow' ? 8 : 16; $height = 0; $expanded = 0; if ($hasActiveChildren) { $width = $config->getCollapsibleIconType() === 'arrow' ? 8 : 16; $height = 16; } if ($height == 0) { $extraStyle = ' display:none;'; } if ($height == 0 && $collapsibleIconPosition === 'left') { $liMarginLeft += $width; } if ($this->isCategoryActive($category)) { $expanded = 1; } $expanded = ' expanded="' . $expanded .'"'; $spanOnclick = 'onclick="Codnitive.expandMenu(this.parentNode)'; $spanClass = $config->getCollapsibleIconType() . '-' . $collapsibleIconPosition; $arrow = ''; } $htmlLi .= ' $attrValue) { $htmlLi .= ' ' . $attrName . '="' . str_replace('"', '\"', $attrValue) . $thumb . $collapsibleClass . '"'; } $htmlLi .= ' style="margin-left: ' . $liMarginLeft . 'px;' . '">'; $html[] = $htmlLi; $html[] = $arrow; // add wrapper $aClass = ''; $aStyle = ''; $onclick = ''; if ($config->isCollapsible() || $config->isThumbImageActive()) { $wrapperMargin = ($config->isCollapsible() && $collapsibleIconPosition === 'left') ? 14 : 0; $extraMargin = !$config->isThumbImageActive() ? 0 : (!empty($thumbnail) && ($thumbPosition === 'left')) ? $thumbWidth + 3 : 0; $collWrapper = $wrapperMargin + $extraMargin; // makes parent category name clickable to open/close collapsible menus if option is enabled $collapseName = ''; if ($hasActiveChildren && $config->isCollapsible() && $config->expandByParentName()) { $onclick = ' onclick="Codnitive.expandMenu(this.parentNode);return false;"'; $collapseName = ' collapse-name'; } $aClass = 'class="collapsible-wrapper' . $collapseName . '"'; $aStyle = ' style="margin-left: ' . $collWrapper . 'px;"'; } $html[] = '' . '' . $this->escapeHtml($category->getName()) . ''; // add thumbnail image $html[] = $image; // add product count if ($config->showProductCount()) { if ($this->_refreshData) { $this->_productsCount[$category->getID()] = count($category->getProductCollection() ->addAttributeToSelect('entity_id') ->addAttributeToFilter('status', 1) ->addAttributeToFilter('visibility', 4)); } if (($config->removeZeroCount() && $this->_productsCount[$category->getID()] > 0) || !$config->removeZeroCount()) { $html[] = '(' . $this->_productsCount[$category->getID()] . ')'; } } // 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[] = '
'; } $html[] = ''; if ($childrenWrapClass) { $html[] = '
'; } } $html[] = ''; $html = implode("\n", $html); 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 = '') { $currentId = Mage::app()->getStore()->getRootCategoryId(); $currentLevel = $this->_getCategoryModel()->load($currentId)->getLevel(); if ($registerdCategory = Mage::registry('current_category')) { $currentId = $registerdCategory->getId(); $currentLevel = $registerdCategory->getLevel(); } $config = $this->getConfig(); $paretnType = $config->getParent(); $categories = $this->getStoreCategories(); $activeCategories = array(); foreach ($categories as $child) { // this condition use for "Current Category and Children" option $condition = ($paretnType == 'current') && ($child->getLevel() == $currentLevel) && ($child->getId() != $currentId); if ($child->getIsActive() && !$condition) { $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++; } if ($this->_refreshData) { file_put_contents($this->_filename, json_encode($this->_productsCount)); } return $html; } /** * Get category title * * @return string */ public function getTitle() { $title = ''; $currentCategory = Mage::registry('current_category'); switch ($this->getConfig()->getTitleType()) { case 'current': if ($currentCategory) { $title = $currentCategory->getName(); } break; case 'parent': if ($currentCategory) { $parent = $currentCategory->getParentCategory(); $rootId = Mage::app()->getStore()->getRootCategoryId(); if ($parent->getId() != $rootId) { $title = $parent->getName(); } } break; case 'static': $title = $this->getConfig()->getStaticTitle(); } if (!$title) { $title = $this->getConfig()->getStaticTitle(); } return $title; } /** * Retrieves home page link must show * * @return boolean */ public function showHome() { if ($this->_getHelper()->isHome() && $this->getConfig()->removeHomeInHome()) { return false; } return $this->getConfig()->showHome(); } /** * Returns all classes for home link * * @return string */ public function getHomeClasses() { $classes = 'level0 nav-0 parent home'; if ($this->getConfig()->isCollapsible()) { $classes .= ' collapsible'; } if ($this->_getHelper()->isHome()) { $classes .= ' active'; } return $classes; } /** * Retrieves which CODNITIVE logo must show or not * * @return boolean */ public function showSupportLogo() { return $this->getConfig()->showSupportLogo(); } /** * Retrieves which CODNITIVE logo must show as image or text * * @return boolean */ public function showAsImage() { return $this->getConfig()->showAsImage(); } /** * Get extension enable status * * @deprecated after 1.7.20 * We don't need to check for module activation option * in template, we check it in layout. * * @return boolean */ public function isActive() { return $this->getConfig()->isActive(); } /** * Get selected column * * @deprecated after 1.7.20 * We don't need to check for selected column option * in template, we check it in layout. * * @return string */ public function getColumn() { return $this->getConfig()->getColumn(); } }