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

jasonsafro’s picture

I 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.

mstrelan’s picture

Version: 6.20 » 6.22

Subscribe. This is still present in 6.22.

jchatard’s picture

I confirm this issue on Drupal 6.22.

nd987’s picture

Issue still exists in D 7.9

Status: Active » Closed (outdated)

Automatically closed because Drupal 6 is no longer supported. If the issue verifiably applies to later versions, please reopen with details and update the version.