Problem: menu_tree_all_data() is returning "has_children" => 1 (ie TRUE) for the first item in any branch that has NO children.
I will include my code below. The short of it:
1. get menu data with menu_tree_all_data()
2. run through it and generate HTML output
If you install the code below as a module, it will generate a block of your primary links menu. The debug code left on in that code will show the menu item titles and their has_children values. Look for a branch of your Primary Links menu where the first element has no children and has_children will still be 1 (true).
<?php
function custom_menu_block($op = 'list', $delta = 0, $edit = array()) {
$block = array();
switch( $op ) {
case 'list':
$block[0]['info'] = t('Custom Menu - Primary Links');
break;
case 'view':
switch( $delta ) {
case 0:
// Get Started
$block['subject'] = 'Custom Menu - Primary Links';
$block['content'] = return_left_menu_html('primary-links');
break;
}
break;
}
return $block;
}
function return_left_menu_html( $menu_name ) {
//print __LINE__; die;
// Init
$out = '';
$menu = menu_tree_all_data( $menu_name );
//var_dump($menu); die;
$active = find_menu_actives( $menu, TRUE, array() );
//var_dump($active); //die;
// Trap out
if( empty($active['top']) || !isset($menu[ $active['top'] ]) ) {
return $out;
}
$menu = $menu[ $active['top'] ]['below'];
//var_dump($menu); die;
return custom_library_menu_tree_output($menu, $active);
}
function custom_library_menu_tree_output($tree, $active) {
$output = '';
$items = array();
$active_path = $active['active_path'];
if( !is_array($tree) ) {
return $output;
}
// Pull out just the menu items we are going to render so that we
// get an accurate count for the first/last classes.
foreach ($tree as $data) {
if (!$data['link']['hidden']) {
$items[] = $data;
}
}
$num_items = count($items);
foreach ($items as $i => $data) {
var_dump($data['link']['title']);
var_dump($data['link']['has_children']);
$extra_class = array();
if ($i == 0) {
$extra_class[] = 'first';
}
if ($i == $num_items - 1) {
$extra_class[] = 'last';
}
$in_active_path = FALSE;
if( array_search($data['link']['mlid'], $active_path) ) {
$extra_class[] = 'active-path';
$in_active_path = TRUE;
}
// JSAFRO: The drupal function does not account for the expanded attribute. This hacks the problem down
if( $data['link']['has_children'] ) {
if( !$data['link']['expanded'] && !$in_active_path && $data['link']['mlid']!= $active['top_mlid']) {
$extra_class[] = 'collapsed coll-';
}
}
$extra_class = implode(' ', $extra_class);
$link = theme('menu_item_link', $data['link']);
if ($data['below']) {
$output .= theme('menu_item', $link, $data['link']['has_children'], custom_library_menu_tree_output($data['below'], $active), $data['link']['in_active_trail'], $extra_class);
}
else {
$output .= theme('menu_item', $link, $data['link']['has_children'], '', $data['link']['in_active_trail'], $extra_class);
}
}
return $output ? theme('menu_tree', $output) : '';
}
function find_menu_actives(&$menu, $is_top, $current) {
$current_page = $_GET['q'];
if( !isset($current['active_path']) ) {
$current['active_path'] = array();
}
foreach( $menu as $one_menu_index => $one_menu ) {
// Update where we are
$current['menu_item'] = $one_menu_index;
if( $is_top ) {
$current['top'] = $one_menu_index;
$current['top_mlid'] = $one_menu['link']['mlid'];
}
array_push( $current['active_path'], $one_menu['link']['mlid'] );
if(
( $current_page == $one_menu['link']['link_path'] && empty($GLOBALS['ffp_menu_route']) )
||
( $current_page == $one_menu['link']['link_path'] && $current['top_mlid'] == $GLOBALS['ffp_menu_route'] )
) {
return $current;
} else if( is_array($one_menu['below']) && count($one_menu['below'])>0 ) {
// Recurse
$active_menu = find_menu_actives( $one_menu['below'], FALSE, $current);
if( !empty($active_menu) ) {
return $active_menu;
}
}
// Remove this from the active path
array_pop($current['active_path']);
}
return FALSE;
}
?>
Comments
Comment #1
jasonsafro commentedI was looking more at the data returned for the first item in a branch. If the first item has no children, then its "below" value is an empty array. For later items that have no children, the "below" value is FALSE.
Comment #3
mstrelan commentedSubscribe. This is still present in 6.22.
Comment #4
jchatard commentedI confirm this issue on Drupal 6.22.
Comment #5
nd987 commentedIssue still exists in D 7.9