'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.

'); } } /** * 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; } ?>