Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Thu, Feb 6, 1:04 AM

in-portal

Index: branches/5.0.x/core/units/helpers/menu_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/menu_helper.php (revision 12950)
+++ branches/5.0.x/core/units/helpers/menu_helper.php (revision 12951)
@@ -1,335 +1,335 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class MenuHelper extends kHelper {
/**
* Cached version of site menu
*
* @var Array
*/
var $Menu = null;
/**
* Parent path mapping used in CachedMenu tag
*
* @var Array
*/
var $parentPaths = Array ();
/**
* Builds site menu
*
* @param Array $params
* @return string
*/
function menuTag($prefix_special, $params)
{
list ($menu, $root_path) = $this->_prepareMenu();
$cat = $this->_getCategoryId($params);
$parent_path = array_key_exists($cat, $this->parentPaths) ? $this->parentPaths[$cat] : '';
$parent_path = str_replace($root_path, '', $parent_path); // menu starts from module path
$levels = explode('|', trim($parent_path, '|'));
if ($levels[0] === '') {
$levels = Array ();
}
if (array_key_exists('level', $params) && $params['level'] > count($levels)) {
// current level is deeper, then requested level
return ;
}
$level = max(array_key_exists('level', $params) ? $params['level'] - 1 : count($levels) - 1, 0);
$parent = array_key_exists($level, $levels) ? $levels[$level] : 0;
$cur_menu =& $menu;
$menu_path = array_slice($levels, 0, $level + 1);
foreach ($menu_path as $elem) {
$cur_menu =& $cur_menu['c' . $elem]['sub_items'];
}
$block_params = $this->prepareTagParams($prefix_special, $params);
$block_params['name'] = $params['render_as'];
$this->Application->SetVar('cur_parent_path', $parent_path);
$real_cat_id = $this->Application->GetVar('m_cat_id');
if (!is_array($cur_menu) || !$cur_menu) {
// no menus on this level
return '';
}
$ret = '';
$cur_item = 1;
$cur_menu = $this->_removeNonMenuItems($cur_menu);
$block_params['total_items'] = count($cur_menu);
foreach ($cur_menu as $page) {
$block_params = array_merge_recursive2(
$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;
// bug #1: this breaks active section highlighting when 2 menu levels are printed on same page (both visible)
// bug #2: people doesn't pass cat_id parameter to m_Link tags in their blocks, so this line helps them; when removed their links will lead to nowhere
$this->Application->SetVar('m_cat_id', $page['CategoryId']);
$ret .= $this->Application->ParseBlock($block_params);
$cur_item++;
}
$this->Application->SetVar('m_cat_id', $real_cat_id);
return $ret;
}
/**
* Builds cached menu version
*
* @return Array
*/
function _prepareMenu()
{
static $root_cat = null;
static $root_path = null;
if (!$root_cat) {
$root_cat = $this->Application->ModuleInfo['Core']['RootCat'];
$sql = 'SELECT ParentPath
FROM ' . TABLE_PREFIX . 'Category
WHERE CategoryId = ' . $root_cat;
$root_path = $this->Conn->GetOne($sql);
}
if (!$this->Menu) {
$menu = $this->Conn->GetRow('SELECT Data, Cached FROM '.TABLE_PREFIX.'Cache WHERE VarName = "cms_menu"');
if ($menu && $menu['Cached'] > 0) {
$menu = unserialize($menu['Data']);
$this->parentPaths = $menu['parentPaths'];
}
else {
$menu = $this->_altBuildMenuStructure(Array ('CategoryId' => $root_cat, 'ParentPath' => $root_path));
$menu['parentPaths'] = $this->parentPaths;
$this->Conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("cms_menu", '.$this->Conn->qstr(serialize($menu)).', '.adodb_mktime().')');
}
unset($menu['parentPaths']);
$this->Menu = $menu;
}
return Array ($this->Menu, $root_path);
}
/**
* Returns category id based tag parameters
*
* @param Array $params
* @return int
*/
function _getCategoryId($params)
{
$cat = isset($params['category_id']) && $params['category_id'] != '' ? $params['category_id'] : $this->Application->GetVar('m_cat_id');
if ("$cat" == 'parent') {
$this_category =& $this->Application->recallObject('c');
/* @var $this_category kDBItem */
$cat = $this_category->GetDBField('ParentId');
}
elseif ($cat == 0) {
$cat = $this->Application->ModuleInfo['Core']['RootCat'];
}
return $cat;
}
/**
* Prepares cms menu item block parameters
*
* @param Array $page
* @param int $real_cat_id
* @param string $root_path
* @return Array
*/
function _prepareMenuItem($page, $real_cat_id, $root_path)
{
static $language_id = null;
static $primary_language_id = null;
static $template = null;
if (!isset($language_id)) {
$language_id = $this->Application->GetVar('m_lang');
$primary_language_id = $this->Application->GetDefaultLanguageId();
$template = $this->Application->GetVar('t');
}
$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)) {
$active = strpos($this->parentPaths[$real_cat_id], $page['ParentPath']) !== false;
}
elseif ($page['ItemPath'] == $template) {
// physical template in menu
$active = true;
}
$category_active = $page['CategoryId'] == $real_cat_id;
}
/*if ($page['ItemType'] == 'cat_index') {
$check_path = str_replace($root_path, '', $page['ParentPath']);
$active = strpos($parent_path, $check_path) !== false;
}
if ($page['ItemType'] == 'page') {
$active = $page['ItemPath'] == preg_replace('/^Content\//i', '', $this->Application->GetVar('t'));
}*/
$block_params = Array (
'title' => $title,
'template' => $page['ItemPath'],
'active' => $active,
'category_active' => $category_active, // new
'parent_path' => $page['ParentPath'],
'parent_id' => $page['ParentId'],
'cat_id' => $page['CategoryId'],
'item_type' => $page['ItemType'],
'page_id' => $page['ItemId'],
- 'use_section' => (int)$page['IsSystem'],
+ 'use_section' => (int)$page['IsSystem'] && ($page['ItemPath'] != 'index'),
'has_sub_menu' => isset($page['sub_items']) && count($page['sub_items']) > 0,
'external_url' => $page['UseExternalUrl'] ? $page['ExternalUrl'] : false, // for backward compatibility
'menu_icon' => $page['UseMenuIconUrl'] ? $page['MenuIconUrl'] : false,
);
return $block_params;
}
/**
* Returns only items, that are visible in menu
*
* @param Array $menu
* @return Array
*/
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['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]);
}
}
return $menu;
}
/**
* Builds cache for children of given category (no matter, what menu status is)
*
* @param Array $parent
* @return Array
*/
function _altBuildMenuStructure($parent)
{
static $lang_part = null;
if (!isset($lang_part)) {
$sql = 'SELECT COUNT(*)
FROM ' . TABLE_PREFIX . 'Language';
$languages_count = ceil($this->Conn->GetOne($sql) / 5) * 5;
$lang_part = '';
for ($i = 1; $i <= $languages_count; $i++) {
$lang_part .= 'c.l' . $i . '_MenuTitle AS l' . $i . '_ItemName,' . "\n";
}
}
$items = Array ();
// Sub-categories from current category
$sql = 'SELECT
c.CategoryId AS CategoryId,
CONCAT(\'c\', c.CategoryId) AS ItemId,
c.Priority AS ItemPriority,
' . $lang_part . '
IF(c.IsSystem, c.Template, CONCAT("id:", c.CategoryId)) AS ItemPath,
c.ParentPath AS ParentPath,
c.ParentId As ParentId,
\'cat\' AS ItemType,
c.IsMenu, c.IsSystem, c.ThemeId, c.UseExternalUrl, c.ExternalUrl, c.UseMenuIconUrl, c.MenuIconUrl
FROM ' . TABLE_PREFIX . 'Category AS c
WHERE (c.Status = ' . STATUS_ACTIVE . ') AND (c.ParentId = ' . $parent['CategoryId'] . ')';
$items = array_merge($items, $this->Conn->Query($sql, 'ItemId'));
// 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;
foreach ($items as $key => $menu_item) {
if ($menu_item['CategoryId'] == $parent['CategoryId']) {
// don't process myself - prevents recursion
continue;
}
$sub_items = $this->_altBuildMenuStructure($menu_item);
if ($sub_items) {
$items[$key]['sub_items'] = $sub_items;
}
}
return $items;
}
/**
* Method for sorting pages by priority in decending order
*
* @param Array $a
* @param Array $b
* @return int
*/
function _menuSort($a, $b)
{
if ($a['ItemPriority'] == $b['ItemPriority']) {
return 0;
}
return ($a['ItemPriority'] < $b['ItemPriority']) ? 1 : -1; //descending
}
}

Event Timeline