Investigation of Drupal's Menu System Uncovers Unexpected Treasure

Today, I spent quite a bit of time wandering drupal's menu system in search of answers. But instead, I uncovered two techniques which made me rethink the questions I was asking. As the latter sentence suggested, I'm a professional writer of fortune cookies on the side (there aren't many of us left...).

 Firstly, we have a very simple technique of locating any menu item (works best with large trees, like "administration", "settings") that exists in the user, node, or admin interface. For me, at least, exploring these techniques has really begun to shift my thinking on the relationship between theming and menus.

I'm probably just tired, but I have this vision of free range administration, user, and publish menus (which, like their chicken cousins, are more healthy, and happier). These menus can be placed in any site's page.tpl.php file, and you're user interfaces will sprout like chia-pets.

Below, is a screenshot of "ghettotacular", which I am naming this early version of an all-theme based dashboard

1. The "duh" technique (will fetch an adminstration menu by path in this example):
<?php $sqlquery = db_fetch_object(db_query("SELECT mid FROM {menu} WHERE path = 'admin' "))$adminmenu = theme_menu_tree($sqlquery->mid);?>

This works well for trees such as "content", "settings", "logs" etc. if you are styling an admin interface. When combined with global $user; $user->id, this technique becomes particularly effective for theming a "special little place" for your each user. You do want your users to feel at home, don't know?

2. The "whoa" technique -- named after my reaction. This technique was stolen from node.module's theming function that generates the node/add definition  list(out of all things), and the variable $publishmenu can then easily be passed to page.tpl.php. I rewrote it to generate an unordedlist that uses the $node->type value to generate a CSS class, hints, the icons on what nevertheless behaves like a menu, and has been coded entirely in the theme. "Events", is CCK content type, by the way. The class is .content-events.
<?php     foreach (node_get_types() as $type => $name) {if (module_invoke(node_get_base($type), 'access', 'create', $type)) {$out = '<li>'. l($name, "node/add/$type", array('class' => $type, 'title' => t('Add a new %s.', array('%s' => $name)))) .'</li>';        $item[$name] = $out;      }    }    if (isset($item)) {      uasort($item, 'strnatcasecmp');      $publishmenu = '<ul>' . implode('', $item) .'</ul>';    }print $publishmenu; ?>

Comments

theme(foo) instead of theme_foo

The proper usage is theme('foo',...) instead of theme_foo(...) because the former can be overwritten by Drupal.

Use menu API

It's great that you've discovered how to grab an individual menu item, but getting it directly with a database query is not the best way to do it. Instead, if you're running CVS/4.7 Drupal, you should use the menu_get_item() function:

Original code:

<?php
$sqlquery
= db_fetch_object(db_query("SELECT mid FROM {menu} WHERE path = 'admin' "))
$adminmenu = theme_menu_tree($sqlquery->mid);
?>

New code:

<?php
// First argument is the MID, second is path - if you're searching by path, set arg 1 to NULL.
$item = menu_get_item(NULL, 'admin');
$adminmenu = theme_menu_tree($item['mid']);
?>

Should this new code output

Should this new code output something if i'm putting this code to my php template? I tried, but nothing happens :(

Nah, Adrian said sometime to

Nah, Adrian said sometime to me in a IM conversation about a $global_menu or some jazz.. but I haven't tried it yet. I saved it somewhere. Will say something if I find something out as a result.

BRILLIANT!

BRILLIANT!