| 1 |
<?php
|
| 2 |
// $Id: menu_trim.module,v 1.2 2007/01/13 00:59:05 davidlesieur Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file Allows menu hierarchies to be trimmed when navigated. By trimming, here
|
| 6 |
* we mean skipping the display of parent menu items when any of some designated
|
| 7 |
* items becomes active.
|
| 8 |
*
|
| 9 |
* At the simplest level, this module allows to hide a menu until some of its
|
| 10 |
* items has become the active item (by reaching the corresponding url). This is
|
| 11 |
* easier than configuring the menu's block visibility for each possible path
|
| 12 |
* contained in the menu.
|
| 13 |
*
|
| 14 |
* This module can be used to make a "contextual secondary menu" based on the
|
| 15 |
* primary links (e.g. you set the Primary links menu for "Allow trimming for
|
| 16 |
* this menu, hide menu when no item is active", activate the "Primary links
|
| 17 |
* (menu_trim)" block, then edit the menu's top-level items and check the "Trim
|
| 18 |
* parent items" option). After that, when an item is selected in the primary
|
| 19 |
* links, the contextual menu will appear, showing only the subitems of the
|
| 20 |
* selected item. Drupal already allows contextual "secondary links" based on
|
| 21 |
* the primary links, but these secondary links are limited to a depth of one
|
| 22 |
* level. Menu Trim, on the other hand, can display complete menu subtrees.
|
| 23 |
*
|
| 24 |
* This module can also be used in any menu to trim parents when reaching deep
|
| 25 |
* menu items. This can make deep menus more usable, and the breadcrumb will
|
| 26 |
* still show the full path.
|
| 27 |
*/
|
| 28 |
|
| 29 |
// TODO: When a menu item is deleted, remove the corresponding menu_trim_item_mid variable, if any.
|
| 30 |
|
| 31 |
define ('MENU_TRIM_DISABLED', 0);
|
| 32 |
define ('MENU_TRIM_ENABLED_SHOW_MENU_ALWAYS', 1);
|
| 33 |
define ('MENU_TRIM_ENABLED_SHOW_MENU_ACTIVE', 2);
|
| 34 |
|
| 35 |
/**
|
| 36 |
* Implementation for hook_menu().
|
| 37 |
*/
|
| 38 |
function menu_trim_menu($may_cache) {
|
| 39 |
$items = array();
|
| 40 |
|
| 41 |
if ($may_cache) {
|
| 42 |
$items[] = array(
|
| 43 |
'path' => 'admin/settings/menu_trim',
|
| 44 |
'title' => t('Menu trim'),
|
| 45 |
'description' => t('Choose what menus need trimming.'),
|
| 46 |
'callback' => 'drupal_get_form',
|
| 47 |
'callback arguments' => array('menu_trim_admin_settings'),
|
| 48 |
'access' => user_access('administer site configuration'),
|
| 49 |
'type' => MENU_NORMAL_ITEM,
|
| 50 |
);
|
| 51 |
}
|
| 52 |
|
| 53 |
return $items;
|
| 54 |
}
|
| 55 |
|
| 56 |
/**
|
| 57 |
* Administration page callback.
|
| 58 |
*/
|
| 59 |
function menu_trim_admin_settings() {
|
| 60 |
$form['menu_trim'] = array(
|
| 61 |
'#type' => 'fieldset',
|
| 62 |
'#title' => t('Trim menus'),
|
| 63 |
'#description' => t('Choose the menus that need to be trimmed. Each of the menus where trimming is allowed will get a corresponding <em>Menu trim</em> block. You should then !enable, and !edit that need to have their parents trimmed.', array('!enable' => l(t('enable those blocks'), 'admin/build/block'), '!edit' => l(t('edit the menu items'), 'admin/build/menu'))),
|
| 64 |
);
|
| 65 |
|
| 66 |
$menus = menu_get_root_menus();
|
| 67 |
foreach ($menus as $mid => $title) {
|
| 68 |
$form['menu_trim']['menu_trim_menu_'. $mid] = array(
|
| 69 |
'#type' => 'select',
|
| 70 |
'#title' => check_plain($title),
|
| 71 |
'#options' => array(
|
| 72 |
MENU_TRIM_DISABLED => t('Never trim'),
|
| 73 |
MENU_TRIM_ENABLED_SHOW_MENU_ALWAYS => t('Allow trimming'),
|
| 74 |
MENU_TRIM_ENABLED_SHOW_MENU_ACTIVE => t('Allow trimming, hide when inactive'),
|
| 75 |
),
|
| 76 |
'#default_value' => variable_get('menu_trim_menu_'. $mid, MENU_TRIM_DISABLED),
|
| 77 |
);
|
| 78 |
}
|
| 79 |
|
| 80 |
return system_settings_form($form);
|
| 81 |
}
|
| 82 |
|
| 83 |
/**
|
| 84 |
* Implementation of hook_block().
|
| 85 |
*/
|
| 86 |
function menu_trim_block($op = 'list', $delta = 0, $edit = array()) {
|
| 87 |
switch ($op) {
|
| 88 |
case 'list':
|
| 89 |
$blocks = array();
|
| 90 |
$menus = menu_get_root_menus();
|
| 91 |
foreach ($menus as $mid => $title) {
|
| 92 |
if (variable_get('menu_trim_menu_'. $mid, MENU_TRIM_DISABLED) != MENU_TRIM_DISABLED) {
|
| 93 |
$blocks[$mid]['info'] = check_plain($title) .' ('. t('Menu trim') .')';
|
| 94 |
}
|
| 95 |
}
|
| 96 |
return $blocks;
|
| 97 |
|
| 98 |
case 'view':
|
| 99 |
if (($mode = variable_get('menu_trim_menu_'. $delta, MENU_TRIM_DISABLED)) != MENU_TRIM_DISABLED) {
|
| 100 |
// Get the trail of the active item in the $delta menu. If the active
|
| 101 |
// item is not in that menu, the menu won't be shown at all.
|
| 102 |
$trail = _menu_get_active_trail_in_submenu($delta);
|
| 103 |
if (is_array($trail)) {
|
| 104 |
// The active item is child of this menu, check for trimming
|
| 105 |
while ($mid = array_pop($trail)) {
|
| 106 |
if (variable_get('menu_trim_item_'. $mid, FALSE)) {
|
| 107 |
// Show the menu using the item as root
|
| 108 |
$item = menu_get_item($mid);
|
| 109 |
$data['subject'] = check_plain($item['title']);
|
| 110 |
$data['content'] = theme('menu_tree', $mid);
|
| 111 |
break;
|
| 112 |
}
|
| 113 |
}
|
| 114 |
if (!$data) {
|
| 115 |
// No trim flag found in the trail, show the full menu
|
| 116 |
$item = menu_get_item($delta);
|
| 117 |
$data['subject'] = check_plain($item['title']);
|
| 118 |
$data['content'] = theme('menu_tree', $delta);
|
| 119 |
}
|
| 120 |
}
|
| 121 |
elseif ($mode == MENU_TRIM_ENABLED_SHOW_MENU_ALWAYS) {
|
| 122 |
// The active item is not child of this menu, show the plain menu
|
| 123 |
$item = menu_get_item($delta);
|
| 124 |
$data['subject'] = check_plain($item['title']);
|
| 125 |
$data['content'] = theme('menu_tree', $delta);
|
| 126 |
}
|
| 127 |
// Otherwise, $mode == MENU_TRIM_ENABLED_MENU_SHOW_ACTIVE, do not show
|
| 128 |
// the menu since it has to be shown only when it contains an active
|
| 129 |
// item
|
| 130 |
}
|
| 131 |
return $data;
|
| 132 |
}
|
| 133 |
}
|
| 134 |
|
| 135 |
/**
|
| 136 |
* Implementation of hook_form_alter().
|
| 137 |
*/
|
| 138 |
function menu_trim_form_alter($form_id, &$form) {
|
| 139 |
if ($form_id == 'menu_edit_item_form') {
|
| 140 |
$mid = $form['mid']['#value'];
|
| 141 |
$item = menu_get_item($mid);
|
| 142 |
// Check if this item is in a menu that is set for trimming
|
| 143 |
while ($item['pid']) {
|
| 144 |
$root_mid = $item['pid'];
|
| 145 |
$item = menu_get_item($item['pid']);
|
| 146 |
}
|
| 147 |
if (variable_get('menu_trim_menu_'. $root_mid, MENU_TRIM_DISABLED) != MENU_TRIM_DISABLED) {
|
| 148 |
$form['trim_item'] = array(
|
| 149 |
'#type' => 'checkbox',
|
| 150 |
'#title' => t('Trim parent items.'),
|
| 151 |
'#description' => t('Check this option to trim the parent items when this item or any of its children becomes active.') .'<br />'. t('Trimming applies only to the menu\'s corresponding <em>Menu trim</em> !block, not to its normal block. When trimming occurs, this item\'s title will become the menu\'s title. Note also that if this item has no children, has its parents trimmed, and becomes active, then no menu will be displayed at all since such menu would be empty.', array('!block' => l(t('block'), 'admin/build/block'))),
|
| 152 |
'#default_value' => variable_get('menu_trim_item_'. $mid, FALSE),
|
| 153 |
'#weight' => 1,
|
| 154 |
);
|
| 155 |
$form['#submit']['menu_trim_edit_item_form_submit'] = current($form['#submit']);
|
| 156 |
|
| 157 |
// Make sure the button remains at the form's bottom
|
| 158 |
$form['submit']['#weight'] = 10;
|
| 159 |
}
|
| 160 |
}
|
| 161 |
}
|
| 162 |
|
| 163 |
function menu_trim_edit_item_form_submit($form_id, $form_values) {
|
| 164 |
variable_set('menu_trim_item_'. $form_values['mid'], $form_values['trim_item']);
|
| 165 |
}
|
| 166 |
|