menutrails.module in Menu TrailsMenu Trails 5
Same filename and directory in other branches
Menutrails allows the assigment of "trails" which will keep menu items active for individual node views.
File
menutrails.moduleView source
<?php
/**
* @file
* Menutrails allows the assigment of "trails" which will keep menu items
* active for individual node views.
*/
/**
* Implementation of hook_menu().
*
* For settings page.
*/
function menutrails_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'admin/settings/menutrails',
'title' => t('Menu Trails'),
'description' => t('Configure your menu trails.'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'menutrails_settings_form',
),
'access' => user_access('administer site configuration'),
'type' => MENU_NORMAL_ITEM,
);
}
return $items;
}
/**
* Implementation of hook_nodeapi().
*
* This will evaluate individual nodes when being viewed and take the necessary
* steps to set the active_trail for menus.
*
* This will retain menu state at the node/view level. For instance, forum nodes
* would maintain an active trail to the forum menu item.
*/
// TODO: this too cries out for an admin configuration screen
function menutrails_nodeapi(&$node, $op, $a3 = NULL, $page = FALSE) {
if ($op == 'view' && $page == TRUE) {
$location = menutrails_node_location($node);
menu_set_location($location);
}
}
/**
* Determine the menu location of a node.
*
* Inspired by _menu_get_active_trail().
*/
function menutrails_node_location($node) {
// This should only fire if the menu isn't already active.
$item = menu_get_item(NULL, 'node/' . $node->nid);
// type = 4 is for a callback
if ($item['type'] == 4) {
$type_trails = variable_get('menutrails_node_types', array());
$mid = $type_trails[$node->type];
$term_trails = variable_get('menutrails_terms', array());
if (isset($node->taxonomy)) {
foreach ($node->taxonomy as $tid => $term) {
if ($term_trails[$tid] > 0) {
$mid = $term_trails[$tid];
}
}
}
if ($mid > 0) {
// Follow the parents up the chain to get the trail.
while ($mid && ($item = menu_get_item($mid))) {
$location[] = $item;
$mid = $mid = $item['pid'];
}
$location = array_reverse($location);
$location[] = array(
'path' => 'node/' . $node->nid,
'title' => $node->title,
);
}
return $location;
}
}
/**
* This implements the same functionality as the nodeapi, but for comment urls.
*/
function menutrails_comment($comment, $op) {
if ($op == 'form' && arg(0) == 'comment') {
$node = node_load($comment['nid']['#value']);
$location = menutrails_node_location($node);
$location[] = array(
'path' => "comment/reply/{$node->nid}",
);
menu_set_location($location);
}
}
/**
* Form builder function for settings.
*
* This is where menutrails rules are set. The interface here could definitely
* stand for some improvement. It's especially unhelpful for tagging
* vocabularies with lots and lots of terms.
*/
function menutrails_settings_form() {
$options = array(
'NONE',
);
$options = $options + menu_parent_options($item['mid'], variable_get('menu_parent_items', 0));
$node_types = node_get_types('names');
$node_trails = variable_get('menutrails_node_types', array());
if (module_exists('taxonomy')) {
$vocabs = taxonomy_get_vocabularies();
}
$term_trails = variable_get('menutrails_terms', array());
$form['description'] = array(
'#type' => 'markup',
'#weight' => '-100',
'#value' => t('Use these settings to configure the "menu trails" for your nodes. This determines what menu items are activated when viewing an individual node. For instance, if you have a menu item for "Blog," you may want to have all blog posts fall under that menu.'),
'#prefix' => '<p>',
'#suffix' => '</p>',
);
$form['order'] = array(
'#type' => 'markup',
'#weight' => '-99',
'#value' => t('<p>Menu trials are evaluated in the following order:</p> <ol><li>Node type</li><li>Taxonomy category</li><li>Node-specific menu setting</li></ol><p>In other words, category-based menu trails override node-type, and specific settings made on the node itself override both. Category-based menu trails are evaluated by weight in the order shown here, so settings in lower vocabularies take precidence.</p>'),
);
$form['menutrails_node_types'] = array(
'#tree' => TRUE,
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#title' => t('Menu trails by node type'),
);
foreach ($node_types as $key => $value) {
$form['menutrails_node_types'][$key] = array(
'#type' => 'select',
'#title' => t('Parent item for') . " {$value}",
'#default_value' => $node_trails[$key],
'#options' => $options,
);
}
if (isset($vocabs)) {
foreach ($vocabs as $vocab) {
$form[$vocab->vid]['menutrails_terms'] = array(
'#tree' => TRUE,
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#title' => t('Menu trails by category:') . " {$vocab->name}",
);
$terms = taxonomy_get_tree($vocab->vid);
foreach ($terms as $term) {
$form[$vocab->vid]['menutrails_terms'][$term->tid] = array(
'#type' => 'select',
'#title' => t('Parent item for') . " {$term->name}",
'#default_value' => $term_trails[$term->tid],
'#options' => $options,
);
}
}
}
return system_settings_form($form);
}
/***
* This is an example _phptemplate_variables() implementation.
*
* You need to add this code (or something like it) to your template.php file
* for this module to do anything useful. Obviously in template.php you don't
* want the code commented out.
*/
/*
function _phptemplate_variables($hook, $vars = array()) {
switch ($hook) {
case 'page': // page is where menu comes into play
// set the primary links
$vars['primary_links'] = menutrails_primary_links(1);
// you may want to also override secondary_links
$vars['secondary_links'] = menutrails_primary_links(2);
break;
}
}
*/
/**
* SUBSTITUTE MENU FUNCTIONS
*/
/**
* This is a substitute function for menu_primary_links()
*
* The important difference is a different criteria for determining if an item
* is "active" or not, and the use of our own _menu_item() function to make use
* of that active status.
*/
function menutrails_primary_links($start_level = 1, $pid = 0) {
if (!module_exists('menu')) {
return NULL;
}
if (!$pid) {
$pid = variable_get('menu_primary_menu', 0);
}
if (!$pid) {
return NULL;
}
if ($start_level < 1) {
$start_level = 1;
}
if ($start_level > 1) {
$trail = _menu_get_active_trail_in_submenu($pid);
if (!$trail) {
return NULL;
}
else {
$pid = $trail[$start_level - 1];
}
}
$menu = menu_get_menu();
$links = array();
// Custom data for use down the line
$trail = _menu_get_active_trail();
if ($pid && is_array($menu['visible'][$pid]) && isset($menu['visible'][$pid]['children'])) {
$count = 1;
foreach ($menu['visible'][$pid]['children'] as $cid) {
$index = "menu-{$start_level}-{$count}-{$pid}";
// this needs to be unset
unset($active);
// changed from menu_in_active_subtrail
if (in_array($cid, $trail)) {
$index .= "-active";
// we use this below
$active = TRUE;
}
// use $active
$links[$index] = menutrails_item_link($cid, FALSE, $active);
$count++;
}
}
// Special case - provide link to admin/build/menu if primary links is empty.
if (empty($links) && $start_level == 1 && $pid == variable_get('menu_primary_menu', 0) && user_access('administer menu')) {
$links['1-1'] = array(
'title' => t('Edit primary links'),
'href' => 'admin/build/menu',
);
}
return $links;
}
/**
* This is a substitute function for menu_item_link()
*
* The important difference is that this will pick up the $active bit from the
* function above, and assign the "active" class to the link if it is present.
*/
function menutrails_item_link($mid, $theme = TRUE, $active = FALSE) {
$item = menu_get_item($mid);
$link_item = $item;
$link = '';
while ($link_item['type'] & MENU_LINKS_TO_PARENT) {
$link_item = menu_get_item($link_item['pid']);
}
if ($theme) {
$link = theme('menu_item_link', $item, $link_item);
}
else {
$link = array(
'title' => $item['title'],
'href' => $link_item['path'],
'attributes' => !empty($item['description']) ? array(
'title' => $item['description'],
) : array(),
);
if ($active) {
$link['attributes']['class'] = 'active';
}
}
$link['mid'] = $mid;
return $link;
}
Functions
Name![]() |
Description |
---|---|
menutrails_comment | This implements the same functionality as the nodeapi, but for comment urls. |
menutrails_item_link | This is a substitute function for menu_item_link() |
menutrails_menu | Implementation of hook_menu(). |
menutrails_nodeapi | |
menutrails_node_location | Determine the menu location of a node. |
menutrails_primary_links | This is a substitute function for menu_primary_links() |
menutrails_settings_form | Form builder function for settings. |