Default menu option when item in multiple blocks
| Project: | Local Menu |
| Version: | 6.x-1.5 |
| Component: | Code |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | reviewed & tested by the community |
When an item appears in multiple menus, currently the Local Menu module doesn't know which menu to make the active menu for that item/page and therefore display the proper links in the block. For example, I have a page that appears in both the 'primary-links' menu as well as in a custom 'menu-utility-links' menu that I created. By default the module just shows the first menu it finds, but this often results in the proper menu links not being showed in the block on this page. In this case, I want it to show the relative/local links from the 'primary-links' menu, not the other custom one (because there are none). I've altered the code to create a "Default Menu" option on the block configuration page so that you can set which menu it should default to when there is more than one for a particular item. If other pages don't belong to this menu, no problem, they'll select the menu they belong to. This is not a real patch, but here's the code that I've altered. Search for // PATCH AND // END PATCH to see where I've altered the code.
<?php
// $Id: local_menu.module,v 1.7 2008/03/19 11:27:00 fokke Exp $
define('LOCAL_MENU_TOP', 1);
define('LOCAL_MENU_PARENT', 10);
define('LOCAL_MENU_FAMILY', 11);
define('LOCAL_MENU_CHILDREN', 12);
define('LOCAL_MENU_UNLIMITED', 99);
// PATCH
define('LOCAL_MENU_DEFAULT_MENU', 'primary-links');
// END PATCH
function local_menu_block($op = 'list', $delta = 0, $edit = array()) {
if ($op == 'list') {
$blocks[0] = array(
'info' => t('Local Menu'),
);
return $blocks;
}
switch ($op) {
case 'configure':
// PATCH TO ALLOW TO SPECIFY DEFAULT MENU WHEN AN ITEM SHOWS UP IN MORE THAN ONE MENU
$form['local_menu_default_menu'] = array(
'#type' => 'textfield',
'#title' => t('Default Menu'),
'#description' => t('Enter the computer readable name for the menu this block should display if an item shows up in more than one menu. By default this is set to "primary-links".'),
'#default_value' => variable_get('local_menu_default_menu', LOCAL_MENU_DEFAULT_MENU),
);
// END PATCH
$form['local_menu_start'] = array(
'#type' => 'select',
'#title' => t('Starting depth'),
'#description' => t('At what depth we need to start draw the menu.'),
'#options' => array(
LOCAL_MENU_TOP => t('Top level (like a normal menu)'),
2 => t('Level #2'),
3 => t('Level #3'),
4 => t('Level #4'),
LOCAL_MENU_PARENT => t('Parent depth (of current page)'),
LOCAL_MENU_FAMILY => t('Current depth'),
LOCAL_MENU_CHILDREN => t('One level deeper (children)'),
),
'#default_value' => variable_get('local_menu_start', 2),
);
$form['local_menu_depth'] = array(
'#type' => 'select',
'#title' => t('Rendered depth'),
'#description' => t('How deep we should allow the menu to be.'),
'#options' => array(
1 => t('One level (like primary links)'),
2 => t('Two levels'),
3 => t('Three levels'),
LOCAL_MENU_UNLIMITED => t('All levels (unlimited)'),
),
'#default_value' => variable_get('local_menu_depth', LOCAL_MENU_UNLIMITED),
);
return $form;
case 'save':
variable_set('local_menu_start', $edit['local_menu_start']);
variable_set('local_menu_depth', $edit['local_menu_depth']);
// PATCH
variable_set('local_menu_default_menu', $edit['local_menu_default_menu']);
// END PATCH
return;
case 'view':
default:
$item = menu_get_item();
// Local Task
if ($item && $item['tab_root']) {
$path_root = preg_replace('!^('.preg_replace('!%[^/]*!', '[^/]+', $item['tab_root']).').*$!', '\\1', $item['href']);
$item = menu_get_item($path_root);
}
//dpr($item);
// Not found
if (!$item) {
return FALSE;
}
// Get the menu link and set the active menu to the menu it's in, so Drupal can find it's way and make correct breadcrumbs at the same time
// PATCH TO NOT SELECT ADMIN MENU AS ACTIVE MENU BECAUSE OF CONFLICT AS WELL AS TO ALLOW FOR DEFAULT MENU WHEN LINK IS PART OF TWO OR MORE MENUS
if ($mlid = db_result(db_query("SELECT mlid FROM {menu_links} WHERE link_path = '%s' AND hidden <> 1 AND menu_name = '%s'", $item['href'], variable_get('local_menu_default_menu', LOCAL_MENU_DEFAULT_MENU)))) {
$link = menu_link_load($mlid);
} else {
$link = menu_link_load(db_result(db_query("SELECT mlid FROM {menu_links} WHERE link_path = '%s' AND hidden <> 1 AND menu_name != 'admin_menu'", $item['href'])));
}
menu_set_active_menu_name($link['menu_name']);
// END PATCH
// Set current path temporarily to the root of the possible local task we might be, so Drupal finds it's way
$q = $_GET['q'];
$_GET['q'] = $item['href'];
$tree = menu_tree_page_data(menu_get_active_menu_name());
$_GET['q'] = $q;
$depth = variable_get('local_menu_depth', LOCAL_MENU_UNLIMITED);
$start = variable_get('local_menu_start', 2);
$title = db_result(db_query("SELECT title FROM {menu_custom} WHERE menu_name = '%s'", $menu));
if ($start == LOCAL_MENU_TOP && $depth == LOCAL_MENU_UNLIMITED) {
$block['subject'] = check_plain($title);
$block['content'] = menu_tree_output($tree);
} else {
if ($start == LOCAL_MENU_PARENT) {
$start = max(1, $link['depth'] - 1);
} elseif ($start == LOCAL_MENU_FAMILY) {
$start = $link['depth'];
} elseif ($start == LOCAL_MENU_CHILDREN) {
$start = $link['depth'] + 1;
}
$block['content'] = local_menu_content($tree, $start, $depth);
$block['subject'] = check_plain(($local_title = local_menu_title()) ? $local_title : $title);
}
return $block;
}
}
function local_menu_content(&$tree, $start, $depth) {
$items = array();
$output = '';
foreach ($tree as $data) {
if (!$data['link']['hidden']) {
$items[] = $data;
}
}
$num_items = count($items);
foreach ($items as $i => $data) {
if ($start <= $data['link']['depth']) {
$extra_class = NULL;
if ($i == 0) {
$extra_class = 'first';
}
if ($i == $num_items - 1) {
$extra_class .= ' last';
}
$link = theme('menu_item_link', $data['link']);
$below = ($depth > 1 && $data['below']) ? local_menu_content($data['below'], $start, $depth - 1) : '';
$output .= theme('menu_item', $link, $data['link']['has_children'], $below, $data['link']['in_active_trail'], $extra_class);
} elseif ($data['link']['in_active_trail'] && $data['below']) {
if ($start == $data['link']['depth'] + 1) {
local_menu_title($data['link']['title']);
}
$output = local_menu_content($data['below'], $start, $depth - 1);
}
}
if ($start <= $data['link']['depth']) {
$output = $output ? theme('menu_tree', $output) : '';
}
return $output;
}
function local_menu_title($set_title = '') {
static $title;
if ($set_title) {
$title = $set_title;
}
return $title;
}
?>
#1
subscribing
#2
This is an alternative solution to #272786: Multiple menu items uncertainty.
#3
Is this feature already implemented? Or is a patch available somewhere?
I tried putting this in my local_menu.module but i don't see any difference.
My localmenu is empty when i have a primary and secondary link(which is primary link but 2nd level) linking to the same node
#4
Attached is a patch that implements this feature.
#5
I've changed the patch from above to show a select list with all your menus in it. Instead of needing to type in the name of the menu in the block config, the user can select from a list.
#6
#7
I tried the patch of drupal 6.9 and it works as supposed to. Very nice!
#8
The patch in #5 worked for me. BTW, this resolves a related bug: #280208: How about menu items that point to a view?
The reason, I think, is that menu items defined by a module get their own "system" entry in the menu_links table.