Overriding a theme function in a module

UPDATE: The comment by jtsnow resolves the general problem of overriding theme functions in a module using hook_theme_registry_alter(). Woohoo! But the specific problem described below to override the rendering of menu items remains.

I am trying to instruct the menu system to display each item's description underneath the item text, in a smaller font. I located the theme_menu_item() function in menu.inc that currently performs this task. What I want is to write my own theme_menu_item() that overrides the original function by adding the item description on a new line. To achieve this, I can use the function hook_theme_registry_alter() to manually edit that function's registered implementation and replace it with my own. Neat!

But the plot thickens: theme_menu_item does not take the menu item itself as parameter! Instead, it accepts a few attributes of the menu item, as passed to it by non-theme function menu_tree_output. This function cannot be overridden using hook_theme_registry_alter(). Shucks!

For the stubborn and impatient, here's the ugly solution: use PECL runkit to redefine menu_tree_output in your own module. You need to do the redefinition in hook_init:

<?php
function mymodule_init() {
 
runkit_function_redefine('menu_tree_output', '$tree', 'return mymodule_menu_tree_output($tree);');
}

function
mymodule_menu_tree_output($tree) {
 
// Do your thing.
}
?>

Find info on installing runkit on Linux (I got the source from SVN as described in one of the post's comments).

Comments

A module can easily override any theme function by implementing hook_theme_registry_alter().

See http://api.drupal.org/api/function/hook_theme_registry_alter/6

Thanks for the great tip - that solves the general concern of letting a module override a theme function. In the case of the menu item, though, the specific function to be overridden is not a theme function, so one would still have to use the runkit technique above.

I updated the post to reflect this information.

You are correct that theme_menu_item does not take the menu item itself as a parameter. The $link parameter that theme_menu_item does accept is rendered by theme_menu_item_link (http://api.drupal.org/api/function/theme_menu_item_link/6) which does take the actual menu item as a parameter. I think that is the actual function that you are looking to override, which can be done with hook_theme_registry_alter.

So, even for this particular case, runkit is unnecessary.