'admin/menu', 'title' => t('menus'), 'callback' => 'menu_overview', 'access' => user_access('administer menu')); $items[] = array('path' => 'admin/menu/item/edit', 'title' => t('edit menu item'), 'callback' => 'menu_edit_item', 'access' => user_access('administer menu'), 'type' => MENU_CALLBACK); $items[] = array('path' => 'admin/menu/item/reset', 'title' => t('reset menu item'), 'callback' => 'menu_reset_item', 'access' => user_access('administer menu'), 'type' => MENU_CALLBACK); $items[] = array('path' => 'admin/menu/item/disable', 'title' => t('disable menu item'), 'callback' => 'menu_disable_item', 'access' => user_access('administer menu'), 'type' => MENU_CALLBACK); $items[] = array('path' => 'admin/menu/item/delete', 'title' => t('delete menu item'), 'callback' => 'menu_delete_item', 'access' => user_access('administer menu'), 'type' => MENU_CALLBACK); $items[] = array('path' => 'admin/menu/list', 'title' => t('list'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10); $items[] = array('path' => 'admin/menu/menu/add', 'title' => t('add menu'), 'callback' => 'menu_add_menu', 'access' => user_access('administer menu'), 'type' => MENU_LOCAL_TASK); $items[] = array('path' => 'admin/menu/item/add', 'title' => t('add menu item'), 'callback' => 'menu_edit_item', 'access' => user_access('administer menu'), 'type' => MENU_LOCAL_TASK); $items[] = array('path' => 'admin/menu/reset', 'title' => t('reset menus'), 'callback' => 'menu_reset', 'access' => user_access('administer menu'), 'type' => MENU_LOCAL_TASK); } return $items; } /** * Implementation of hook_help(). */ function menu_help($section) { switch ($section) { case 'admin/modules#description': return t('Allows administrators to customize the site navigation menu.'); case 'admin/menu': return t('

Select an operation from the list to move, change, or delete a menu item.

'); case 'admin/menu/menu/add': return t('

Enter the name for your new menu. Remember to enable the newly created block in the %blocks administration page.

', array('%blocks' => l(t('blocks'), 'admin/block'))); case 'admin/menu/item/add': return t('

Enter the title, path, position and the weight for your new menu item.

'); case 'admin/help#menu': return t('

The menu module allows for customization of the menus. Menus are useful for providing navigation in your site. The main menu for navigation is the navigation menu. Menus appear in blocks on your site.

You can

For more information, read the configuration and customization handbook menu page.

', array('%admin-menus' => url('admin/menus'), '%admin-block' => url('admin/block'), '%admin-menu-menu-add' => url('admin/menu/menu/add'), '%admin-menu-item-add' => url('admin/menu/item/add'))); } } /** * Implementation of hook_block(). */ function menu_block($op = 'list', $delta = 0) { $menu = menu_get_menu(); if ($op == 'list') { $blocks = array(); foreach ($menu['items'][0]['children'] as $mid) { // Default "Navigation" block is handled by user.module. if ($mid != 1) { $blocks[$mid]['info'] = $menu['items'][$mid]['title']; } } return $blocks; } else if ($op == 'view') { $data['subject'] = $menu['items'][$delta]['title']; $data['content'] = '' ; return $data; } } /** * Implementation of hook_perm(). */ function menu_perm() { return array('administer menu'); } /** * Menu callback; present the main menu management page. */ function menu_overview() { menu_rebuild(); print theme('page', menu_overview_tree()); } /** * Menu callback; clear the database, resetting the menu to factory defaults. */ function menu_reset() { $op = $_POST['op']; switch ($op) { case t('Reset all'): db_query('DELETE FROM {menu}'); drupal_set_message(t('All menu items reset.')); drupal_goto('admin/menu'); break; default: $output = theme('confirm', t('Are you sure you want to reset all menu items to their default settings?'), 'admin/menu', t('Any custom additions or changes to the menu will be lost.'), t('Reset all')); print theme('page', $output); } } /** * Menu callback; handle the adding of a new menu. */ function menu_add_menu() { $op = $_POST['op']; $edit = $_POST['edit']; $output = ''; switch ($op) { case t('Submit'): menu_edit_item_validate($edit); if (!form_get_errors()) { menu_edit_item_save($edit); drupal_goto('admin/menu'); } // Fall through. default: $edit['pid'] = 0; $edit['type'] = MENU_CUSTOM_MENU; $output .= menu_edit_item_form($edit); } print theme('page', $output); } /** * Menu callback; reset a single modified item. */ function menu_reset_item($mid) { $op = $_POST['op']; switch ($op) { case t('Reset'): db_query('DELETE FROM {menu} WHERE mid = %d', $mid); drupal_set_message(t('Menu item reset.')); drupal_goto('admin/menu'); break; default: $title = db_result(db_query('SELECT title FROM {menu} WHERE mid = %d', $mid)); $output = theme('confirm', t('Are you sure you want to reset the item %item to its default values?', array('%item' => theme('placeholder', $title))), 'admin/menu', t('Any customizations will be lost. This action cannot be undone.'), t('Reset')); print theme('page', $output); } } /** * Menu callback; delete a single custom item. */ function menu_delete_item($mid) { $op = $_POST['op']; $result = db_query('SELECT type, title FROM {menu} WHERE mid = %d', $mid); $menu = db_fetch_object($result); if (!$menu) { drupal_goto('admin/menu'); } switch ($op) { case t('Delete'): db_query('DELETE FROM {menu} WHERE mid = %d', $mid); if ($menu->type & MENU_IS_ROOT) { drupal_set_message(t('Menu deleted.')); } else { drupal_set_message(t('Menu item deleted.')); } drupal_goto('admin/menu'); break; default: if ($menu->type & MENU_IS_ROOT) { $message = t('Are you sure you want to delete the menu %item?', array('%item' => theme('placeholder', $menu->title))); } else { $message = t('Are you sure you want to delete the custom menu item %item?', array('%item' => theme('placeholder', $menu->title))); } $output = theme('confirm', $message, 'admin/menu', t('This action cannot be undone.'), t('Delete')); print theme('page', $output); } } /** * Menu callback; hide a menu item. */ function menu_disable_item($mid) { $menu = menu_get_menu(); $type = $menu['items'][$mid]['type']; $type &= ~MENU_VISIBLE_IN_TREE; $type &= ~MENU_VISIBLE_IN_BREADCRUMB; $type |= MENU_MODIFIED_BY_ADMIN; db_query('UPDATE {menu} SET type = %d WHERE mid = %d', $type, $mid); drupal_set_message(t('Menu item disabled.')); drupal_goto('admin/menu'); } /** * Menu callback; dispatch to the appropriate menu item edit function. */ function menu_edit_item($mid = 0) { $op = $_POST['op']; $edit = $_POST['edit']; $output = ''; switch ($op) { case t('Submit'): menu_edit_item_validate($edit); if (!form_get_errors()) { menu_edit_item_save($edit); drupal_goto('admin/menu'); } $output .= menu_edit_item_form($edit); break; default: if ($mid > 0) { $item = db_fetch_object(db_query('SELECT * FROM {menu} WHERE mid = %d', $mid)); $edit['mid'] = $item->mid; $edit['pid'] = $item->pid; $edit['path'] = $item->path; $edit['title'] = $item->title; $edit['description'] = $item->description; $edit['weight'] = $item->weight; $edit['type'] = $item->type; } else { $edit['mid'] = 0; // In case a negative ID was passed in. $edit['pid'] = 1; // default to "Navigation" menu. $edit['type'] = MENU_CUSTOM_ITEM; } $output .= menu_edit_item_form($edit); } print theme('page', $output); } /** * Present the menu item editing form. */ function menu_edit_item_form($edit) { $menu = menu_get_menu(); $form .= form_textfield(t('Title'), 'title', $edit['title'], 60, 128, t('The name to display for this link.'), NULL, TRUE); if ($edit['pid'] == 0) { // Display a limited set of fields for menus (not items). $form .= form_hidden('path', ''); $form .= form_hidden('pid', 0); $form .= form_hidden('weight', 0); } else { $form .= form_textfield(t('Description'), 'description', $edit['description'], 60, 128, t('The description displayed when hovering over a menu item.')); $path_description = t('The Drupal path this menu item links to.'); if (isset($edit['path']) && array_key_exists($edit['path'], $menu['path index']) && $menu['path index'][$edit['path']] != $edit['mid']) { $old_mid = $menu['path index'][$edit['path']]; $old_item = $menu['items'][$old_mid]; $path_description .= "\n". t('Since a menu item "%old" already exists for "%path", this menu item is shortcut to that location.', array('%old' => l($old_item['title'], 'admin/menu/item/edit/'. $old_mid), '%path' => $edit['path'])); } if ($edit['type'] & MENU_CREATED_BY_ADMIN) { $form .= form_textfield(t('Path'), 'path', $edit['path'], 60, 128, $path_description, NULL, TRUE); } else { $form .= form_item(t('Path'), l($edit['path'], $edit['path'])); $form .= form_hidden('path', $edit['path']); } $form .= form_checkbox(t('Expanded'), 'expanded', 1, ($edit['type'] & MENU_EXPANDED), t('If selected and this menu item has children, the menu will always appear expanded.')); // Generate a list of possible parents (not including this item or descendants). $options = menu_parent_options($edit['mid']); $form .= form_select(t('Parent item'), 'pid', $edit['pid'], $options); $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('Optional. In the menu, the heavier items will sink and the lighter items will be positioned nearer the top.')); } $form .= form_submit(t('Submit')); $form .= form_hidden('mid', $edit['mid']); // Always enable menu items (but not menus) when editing them. if (!($edit['type'] & MENU_IS_ROOT)) { $edit['type'] |= MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IN_BREADCRUMB; } $form .= form_hidden('type', $edit['type']); return form($form); } /** * Confirm that an edited menu item has fields properly filled in. */ function menu_edit_item_validate($edit) { if (empty($edit['title'])) { form_set_error('title', t('You must specify a title.')); } if ($edit['pid'] != 0) { if (empty($edit['path'])) { form_set_error('path', t('You must specify a path.')); } } } /** * Save changes to a menu item into the database. */ function menu_edit_item_save($edit) { $menu = menu_get_menu(); if ($edit['expanded']) { $edit['type'] |= MENU_EXPANDED; } else { $edit['type'] &= ~MENU_EXPANDED; } if ($edit['mid']) { db_query("UPDATE {menu} SET pid = %d, path = '%s', title = '%s', description = '%s', weight = %d, type = %d WHERE mid = %d", $edit['pid'], $edit['path'], $edit['title'], $edit['description'], $edit['weight'], $edit['type'] | MENU_MODIFIED_BY_ADMIN, $edit['mid']); drupal_set_message(t('Updated menu item %title.', array('%title' => theme('placeholder', $edit['title'])))); } else { $mid = db_next_id('{menu}_mid'); db_query("INSERT INTO {menu} (mid, pid, path, title, description, weight, type) VALUES (%d, %d, '%s', '%s', '%s', %d, %d)", $mid, $edit['pid'], $edit['path'], $edit['title'], $edit['description'], $edit['weight'], $edit['type'] | MENU_MODIFIED_BY_ADMIN); drupal_set_message(t('Created new menu item %title.', array('%title' => theme('placeholder', $edit['title'])))); if (array_key_exists($edit['path'], $menu['path index'])) { $old_mid = $menu['path index'][$edit['path']]; $old_item = $menu['items'][$old_mid]; drupal_set_message(t('Since a menu item %old already exists for %path, this new menu item was created as a shortcut to that location.', array('%old' => l(theme('placeholder', $old_item['title']), 'admin/menu/item/edit/'. $old_mid, array(), NULL, NULL, FALSE, TRUE), '%path' => theme('placeholder', $edit['path'])))); } } } /** * Present the menu tree, rendered along with links to edit menu items. */ function menu_overview_tree() { $menu = menu_get_menu(); $header = array(t('Menu item'), t('Expanded'), array('data' => t('Operations'), 'colspan' => '3')); $output = ''; foreach ($menu['items'][0]['children'] as $mid) { $operations = array(); if ($menu['items'][$mid]['type'] & MENU_MODIFIABLE_BY_ADMIN) { $operations[] = l(t('edit'), 'admin/menu/item/edit/'. $mid); } if ($menu['items'][$mid]['type'] & MENU_CREATED_BY_ADMIN) { $operations[] = l(t('delete'), 'admin/menu/item/delete/'. $mid); } $table = theme('item_list', $operations); $table .= theme('table', $header, menu_overview_tree_rows($mid)); $output .= theme('box', $menu['items'][$mid]['title'], $table); } return $output; } function menu_overview_tree_rows($pid = 0, $depth = 0) { $menu = menu_get_menu(); $rows = array(); if (isset($menu['items'][$pid]) && $menu['items'][$pid]['children']) { usort($menu['items'][$pid]['children'], '_menu_sort'); foreach ($menu['items'][$pid]['children'] as $mid) { // Populate the title field. $title = ''; if ($pid == 0) { // Top-level items are menu names, and don't have an associated path. $title .= $menu['items'][$mid]['title']; } else { $title .= l($menu['items'][$mid]['title'], $menu['items'][$mid]['path']); } if ($depth > 0) { $title = '- '. $title; } for ($i = 1; $i < $depth; $i++) { $title = '  '. $title; } // Populate the operations field. $operations = array(); if (!($menu['items'][$mid]['type'] & MENU_MODIFIABLE_BY_ADMIN)) { $operations[] = array('data' => t('locked'), 'colspan' => '3', 'align' => 'center'); } else { if ($menu['items'][$mid]['type'] & MENU_VISIBLE_IN_TREE) { $operations[] = array('data' => l(t('edit'), 'admin/menu/item/edit/'. $mid)); if ($menu['items'][$mid]['type'] & MENU_IS_ROOT) { // Disabling entire menus is done from block admin page. $operations[] = array('data' => ''); } else { $operations[] = array('data' => l(t('disable'), 'admin/menu/item/disable/'. $mid)); } } else { $operations[] = array('data' => ''); $operations[] = array('data' => l(t('enable'), 'admin/menu/item/edit/'. $mid)); } if ($menu['items'][$mid]['type'] & MENU_CREATED_BY_ADMIN) { $operations[] = array('data' => l(t('delete'), 'admin/menu/item/delete/'. $mid)); } else if ($menu['items'][$mid]['type'] & MENU_MODIFIED_BY_ADMIN) { $operations[] = array('data' => l(t('reset'), 'admin/menu/item/reset/'. $mid)); } else { $operations[] = array('data' => ''); } } // Call out disabled items. if ($menu['items'][$mid]['type'] & MENU_VISIBLE_IN_TREE) { $class = 'menu-enabled'; } else { $title .= ' ('. t('disabled') .')'; $class = 'menu-disabled'; } if ($menu['items'][$mid]['type'] & (MENU_MODIFIABLE_BY_ADMIN | MENU_VISIBLE_IN_TREE)) { $row = array(array('data' => $title, 'class' => $class), array('data' => ($menu['items'][$mid]['children'] ? (($menu['items'][$mid]['type'] & MENU_EXPANDED) ? t('Yes') : t('No')) : ''), 'class' => $class)); foreach ($operations as $operation) { $operation['class'] = $class; $row[] = $operation; } $rows[] = $row; $rows = array_merge($rows, menu_overview_tree_rows($mid, $depth + 1)); } else { // Skip items that are hidden and locked; admins will never care about them. $rows = array_merge($rows, menu_overview_tree_rows($mid, $depth)); } } } return $rows; } /** * Return a list of menu items that are valid possible parents for the * given menu item. */ function menu_parent_options($mid, $pid = 0, $depth = 0) { $menu = menu_get_menu(); $options = array(); if (isset($menu['items'][$pid]) && $menu['items'][$pid]['children']) { usort($menu['items'][$pid]['children'], '_menu_sort'); foreach ($menu['items'][$pid]['children'] as $child) { if ($child != $mid) { if ($child > 0 && ($menu['items'][$child]['type'] & (MENU_MODIFIABLE_BY_ADMIN | MENU_IS_ROOT))) { $title = ' '. $menu['items'][$child]['title']; for ($i = 0; $i < $depth; $i++) { $title = '--'. $title; } if (!($menu['items'][$child]['type'] & MENU_VISIBLE_IN_TREE)) { $title .= ' ('. t('disabled') .')'; } $options[$child] = $title; } $options += menu_parent_options($mid, $child, $depth + 1); } } } return $options; } ?>