First off I love this module. I use it in most of my sites. It's a great way to just have people create a logical menu tree using primary links and still have the different levels show up on parent pages. BRAVO!

I just wanted to share a patch I made for this code though to allow for greater access to the core theming system. Basically I change menu_block_tree_output() to theme_menu_block_tree_output(), inserted the appropriate value for this into hook_theme, and changed all calls to the previous function to call theme('menu_block_output',$tree). This has been great as now I can easily override some of the display and output on the theme level without having to modify the module(which wasn't an option since I work almost exclusively in multisite environments).

Anyway I would hope this would make it into the next release of this module to allow others the ability to do this.

CommentFileSizeAuthor
#6 menu_thools.zip2.29 KBdonquixote
#1 menu_block-59604.patch1.65 KBarcaneadam
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

arcaneadam’s picture

FileSize
1.65 KB

Patch file

armyofda12mnkeys’s picture

Can you give an example how you would use this?

I was looking for overriding a menu block so between the list item and hyperlink, it has a div surrounding it (so i can use sifr to target it easily as sifr seems to have trouble with targetting lists when it has sublists). Something to target between them will allow me to target the sifr css rules better i think

gg4’s picture

subscribing.

donquixote’s picture

+1, I think this is the way to go.
However, in addition to the $tree parameter, I would also let the theme function know about the menu name and the trail (for recursive calls).

I solved this problem for myself with a custom module that creates a duplicate/mirror for each menu blocks. These new blocks use all the settings of the respective menu block, but are easier to theme or alter. The downside is that my block list gets cluttered up.

If this is to be solved by menu_block itself (which it should), I think the functions that generate the tree should be further split up into reusable pieces:

<?php
function _menu_block_view($delta) {
  list($tree, $settings) = _menu_block_load($delta);
  return theme('menu_block_tree_output', $tree, $settings, array());
}

function theme_menu_block_tree_output($tree, $settings, $trail) {
  $items = menu_block_build_items($tree);
  foreach (array_keys($items) as $key) {
    $subtrail = $trail;
    $subtrail[] = array($key, $items[$key]);
    $below = !empty($tree[$key]['below']) ? theme('menu_block_tree_output', $tree[$key]['below'], $settings, $subtrail) : '';
    $items[$key]['link']['localized_options']['attributes']['class'] = menu_block_build_link_class($item);
    $extra_class = menu_block_build_item_class($item);
    $link = theme('menu_item_link', $items[$key]['link']);
    $output .= theme('menu_item', $link, $items[$key]['link']['has_children'], $items[$key]['below'], $items[$key]['link']['in_active_trail'], $extra_class);
    ++$i;
  }
  return $output ? theme('menu_tree', $output) : '';
}
?>

Something like this.
The point is that a theme override shouldn't need to copy all the details.

JohnAlbin’s picture

Status: Needs review » Closed (won't fix)

That function is the heart of the menu tree building code. If you want to override that, just build a different module that uses some of menu_block's supporting APIs.

Fundamentally, this proposal is not the proper way to "override" the building of the tree. Theming is for changing the way the data is displayed, not changing the way the data is built.

Sorry, guys! :-(

donquixote’s picture

Status: Closed (won't fix) » Active
FileSize
2.29 KB

Hey, wait!

Fundamentally, this proposal is not the proper way to "override" the building of the tree. Theming is for changing the way the data is displayed, not changing the way the data is built.

We don't need to do the tree building in a theme function. Instead, extending on the code from #4, we can do the following:
- load the tree.
- send the $tree and $settings through a drupal_alter() hook to allow modifications.
- then call theme('menu_block_tree_output', $tree, $settings, $trail). The tree is already build at this point, but the theme hook would allow to render it in a different way - with more flexibility than the usual theme('menu_item_link') etc.

This would be fundamentally the correct way of doing theme overrides.

Another interesting idea would be callbacks ("handlers") for tree loading and tree rendering. A custom load handler could skip the localize() stuff, or do access checking in a different way, or even merge menu items from two different menus. We would need another alter() hook before the loading, to set the load handler..

For those worried about performance: Doing things for the entire tree is cheap. Doing things for single menu items is expensive. A mytheme_menu_block_tree_output() custom override could be much faster than the usual menu_block_tree_output(), because it doesn't need to call theme('menu_item') and theme('menu_item_link').

That function is the heart of the menu tree building code. If you want to override that, just build a different module that uses some of menu_block's supporting APIs.

I would like to have two modules doing almost the same thing..

For those interested, I can attach the module that I currently use. No guarantees. Works as explained in #4, but with an added alter() hook.

EDIT:
Please ignore the "// Lazy render the tree" comment. This was a funny idea that I discarded for this module.

JohnAlbin’s picture

Issue summary: View changes
Status: Active » Closed (won't fix)