Index: menu_helper.php
===================================================================
--- menu_helper.php (revision 15384)
+++ menu_helper.php (working copy)
@@ -20,15 +20,17 @@
* Cached version of site menu
*
* @var Array
+ * @access protected
*/
- var $Menu = null;
+ protected $Menu = NULL;
/**
* Parent path mapping used in CachedMenu tag
*
* @var Array
+ * @access protected
*/
- var $parentPaths = Array ();
+ protected $parentPaths = Array ();
/**
* Builds site menu
@@ -49,11 +51,11 @@
$levels = explode('|', trim($parent_path, '|'));
- if ($levels[0] === '') {
+ if ( $levels[0] === '' ) {
$levels = Array ();
}
- if (array_key_exists('level', $params) && $params['level'] > count($levels)) {
+ if ( array_key_exists('level', $params) && $params['level'] > count($levels) ) {
// current level is deeper, then requested level
return '';
}
@@ -74,7 +76,7 @@
$this->Application->SetVar('cur_parent_path', $parent_path);
$real_cat_id = $this->Application->GetVar('m_cat_id');
- if (!is_array($cur_menu) || !$cur_menu) {
+ if ( !is_array($cur_menu) || !$cur_menu ) {
// no menus on this level
return '';
}
@@ -85,10 +87,7 @@
$block_params['total_items'] = count($cur_menu);
foreach ($cur_menu as $page) {
- $block_params = array_merge(
- $block_params,
- $this->_prepareMenuItem($page, $real_cat_id, $root_path)
- );
+ $block_params = array_merge($block_params, $this->_prepareMenuItem($page, $real_cat_id, $root_path));
$block_params['is_last'] = $cur_item == $block_params['total_items'];
$block_params['is_first'] = $cur_item == 1;
@@ -106,18 +105,18 @@
* Builds cached menu version
*
* @return Array
+ * @access protected
*/
- function _prepareMenu()
+ protected function _prepareMenu()
{
- static $root_cat = null;
- static $root_path = null;
+ static $root_cat = NULL, $root_path = NULL;
- if (!$root_cat) {
+ if ( !$root_cat ) {
$root_cat = $this->Application->getBaseCategory();
$cache_key = 'parent_paths[%CIDSerial:' . $root_cat . '%]';
$root_path = $this->Application->getCache($cache_key);
- if ($root_path === false) {
+ if ( $root_path === false ) {
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT ParentPath
FROM ' . TABLE_PREFIX . 'Categories
@@ -135,15 +134,15 @@
$menu = $this->Application->getDBCache('cms_menu', CacheSettings::$cmsMenuRebuildTime);
}
- if ($menu) {
+ if ( $menu ) {
$menu = unserialize($menu);
$this->parentPaths = $menu['parentPaths'];
}
else {
- $menu = $this->_altBuildMenuStructure(Array ('CategoryId' => $root_cat, 'ParentPath' => $root_path));
+ $menu = $this->_buildMenuStructure($root_cat);
$menu['parentPaths'] = $this->parentPaths;
- if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
+ if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) {
$this->Application->setCache('master:cms_menu', serialize($menu));
}
else {
@@ -167,13 +166,14 @@
function _getCategoryId($params)
{
$cat = isset($params['category_id']) && $params['category_id'] != '' ? $params['category_id'] : $this->Application->GetVar('m_cat_id');
- if ("$cat" == 'parent') {
+
+ if ( "$cat" == 'parent' ) {
$this_category = $this->Application->recallObject('c');
/* @var $this_category kDBItem */
$cat = $this_category->GetDBField('ParentId');
}
- elseif ($cat == 0) {
+ elseif ( $cat == 0 ) {
$cat = $this->Application->getBaseCategory();
}
@@ -187,14 +187,13 @@
* @param int $real_cat_id
* @param string $root_path
* @return Array
+ * @access protected
*/
- function _prepareMenuItem($page, $real_cat_id, $root_path)
+ protected function _prepareMenuItem($page, $real_cat_id, $root_path)
{
- static $language_id = null;
- static $primary_language_id = null;
- static $template = null;
+ static $language_id = NULL, $primary_language_id = NULL, $template = NULL;
- if (!isset($language_id)) {
+ if ( !isset($language_id) ) {
$language_id = $this->Application->GetVar('m_lang');
$primary_language_id = $this->Application->GetDefaultLanguageId();
$template = $this->Application->GetVar('t');
@@ -203,11 +202,11 @@
$active = $category_active = false;
$title = $page['l' . $language_id . '_ItemName'] ? $page['l' . $language_id . '_ItemName'] : $page['l' . $primary_language_id . '_ItemName'];
- if ($page['ItemType'] == 'cat') {
- if (array_key_exists($real_cat_id, $this->parentPaths)) {
+ if ( $page['ItemType'] == 'cat' ) {
+ if ( array_key_exists($real_cat_id, $this->parentPaths) ) {
$active = strpos($this->parentPaths[$real_cat_id], $page['ParentPath']) !== false;
}
- elseif ($page['ItemPath'] == $template) {
+ elseif ( $page['ItemPath'] == $template ) {
// physical template in menu
$active = true;
}
@@ -215,12 +214,12 @@
$category_active = $page['CategoryId'] == $real_cat_id;
}
- /*if ($page['ItemType'] == 'cat_index') {
+ /*if ( $page['ItemType'] == 'cat_index' ) {
$check_path = str_replace($root_path, '', $page['ParentPath']);
$active = strpos($parent_path, $check_path) !== false;
}
- if ($page['ItemType'] == 'page') {
+ if ( $page['ItemType'] == 'page' ) {
$active = $page['ItemPath'] == preg_replace('/^Content\//i', '', $this->Application->GetVar('t'));
}*/
@@ -253,14 +252,15 @@
*
* @param Array $menu
* @return Array
+ * @access protected
*/
- function _removeNonMenuItems($menu)
+ protected function _removeNonMenuItems($menu)
{
$theme_id = $this->Application->GetVar('m_theme');
foreach ($menu as $menu_index => $menu_item) {
// $menu_index is in "cN" format, where N is category id
- if (!$menu_item['IsMenu'] || $menu_item['Status'] != STATUS_ACTIVE || ($menu_item['ThemeId'] != $theme_id && $menu_item['ThemeId'] != 0)) {
+ if ( !$menu_item['IsMenu'] || $menu_item['Status'] != STATUS_ACTIVE || ($menu_item['ThemeId'] != $theme_id && $menu_item['ThemeId'] != 0) ) {
// don't show sections, that are not from menu OR system templates from other themes
unset($menu[$menu_index]);
}
@@ -270,52 +270,61 @@
}
/**
- * Builds cache for children of given category (no matter, what menu status is)
+ * Builds cache of all menu items and their parent categories
*
- * @param Array $parent
+ * @param int $top_category_id
* @return Array
+ * @access protected
*/
- function _altBuildMenuStructure($parent)
+ protected function _buildMenuStructure($top_category_id)
{
- static $lang_part = null;
+ // 1. get parent paths of leaf categories, that are in menu (across all themes)
+ $sql = 'SELECT ParentPath, CategoryId
+ FROM ' . $this->Application->getUnitOption('c', 'TableName') . '
+ WHERE IsMenu = 1 AND Status = ' . STATUS_ACTIVE;
+ $this->parentPaths = $this->Conn->GetCol($sql ,'CategoryId');
- if (!isset($lang_part)) {
- $ml_helper = $this->Application->recallObject('kMultiLanguageHelper');
- /* @var $ml_helper kMultiLanguageHelper */
+ // 2. figure out parent paths of all categories in path to leaf categories
+ foreach ($this->parentPaths as $leaf_parent_path) {
+ $parent_categories = explode('|', substr($leaf_parent_path, 1, -1));
- $lang_part = '';
- $languages = $ml_helper->getLanguages();
-
- foreach ($languages as $language_id) {
- $lang_part .= 'c.l' . $language_id . '_MenuTitle AS l' . $language_id . '_ItemName,' . "\n";
+ foreach ($parent_categories as $index => $parent_category_id) {
+ if ( !isset($this->parentPaths[$parent_category_id]) ) {
+ $parent_path = array_slice($parent_categories, 0, $index + 1);
+ $this->parentPaths[$parent_category_id] = '|' . implode('|', $parent_path) . '|';
+ }
}
}
+ return $this->_altBuildMenuStructure($top_category_id, implode(',', array_keys($this->parentPaths)));
+ }
+
+ /**
+ * Builds cache for children of given category (no matter, what menu status is)
+ *
+ * @param int $parent_category_id
+ * @param string $category_limit
+ * @return Array
+ * @access protected
+ */
+ protected function _altBuildMenuStructure($parent_category_id, $category_limit = NULL)
+ {
// Sub-categories from current category
- $items = $this->getSubCategories( $parent['CategoryId'] );
+ $items = $this->_getSubCategories($parent_category_id, $category_limit);
// sort menu items
uasort($items, Array (&$this, '_menuSort'));
- // store menu items
- $the_items = Array();
- foreach ($items as $index => $an_item) {
- $the_items[ $an_item['ItemId'] ] = $an_item;
-
- $this->parentPaths[ $an_item['CategoryId'] ] = $an_item['ParentPath'];
- }
-
- // process submenus of each menu
- $items = $the_items;
+ // process sub-menus of each menu
foreach ($items as $key => $menu_item) {
- if ($menu_item['CategoryId'] == $parent['CategoryId']) {
+ if ( $menu_item['CategoryId'] == $parent_category_id ) {
// don't process myself - prevents recursion
continue;
}
- $sub_items = $this->_altBuildMenuStructure($menu_item);
+ $sub_items = $this->_altBuildMenuStructure($menu_item['CategoryId'], $category_limit);
- if ($sub_items) {
+ if ( $sub_items ) {
$items[$key]['sub_items'] = $sub_items;
}
}
@@ -323,22 +332,33 @@
return $items;
}
- function getSubCategories($parent_id)
+ /**
+ * Returns given category sub-categories
+ *
+ * @param int $parent_id
+ * @param string $category_limit
+ * @return Array
+ * @access protected
+ */
+ protected function _getSubCategories($parent_id, $category_limit = NULL)
{
- static $items_by_parent = null;
+ static $items_by_parent = NULL, $lang_part = NULL;
- if (!isset($items_by_parent)) {
+ if ( !isset($lang_part) ) {
$ml_helper = $this->Application->recallObject('kMultiLanguageHelper');
/* @var $ml_helper kMultiLanguageHelper */
$lang_part = '';
- $items_by_parent = Array ();
$languages = $ml_helper->getLanguages();
foreach ($languages as $language_id) {
$lang_part .= 'c.l' . $language_id . '_MenuTitle AS l' . $language_id . '_ItemName,' . "\n";
}
+ }
+ if ( !isset($items_by_parent) ) {
+ $items_by_parent = Array ();
+
// Sub-categories from current category
$sql = 'SELECT
c.CategoryId AS CategoryId,
@@ -353,6 +373,11 @@
c.IsMenu, c.Type, c.ThemeId, c.UseExternalUrl, c.ExternalUrl, c.UseMenuIconUrl, c.MenuIconUrl,
c.Status
FROM ' . TABLE_PREFIX . 'Categories AS c';
+
+ if ( isset($category_limit) && $category_limit ) {
+ $sql .= ' WHERE c.CategoryId IN (' . $category_limit . ')';
+ }
+
$items = $this->Conn->Query($sql, 'ItemId');
foreach ($items as $item_id => $item_data) {
@@ -370,7 +395,7 @@
}
/**
- * Method for sorting pages by priority in decending order
+ * Method for sorting pages by priority in descending order
*
* @param Array $a
* @param Array $b
@@ -378,10 +403,10 @@
*/
function _menuSort($a, $b)
{
- if ($a['ItemPriority'] == $b['ItemPriority']) {
+ if ( $a['ItemPriority'] == $b['ItemPriority'] ) {
return 0;
}
- return ($a['ItemPriority'] < $b['ItemPriority']) ? 1 : -1; //descending
+ return ($a['ItemPriority'] < $b['ItemPriority']) ? 1 : -1; // descending
}
}