Code coverage for /20080809/modules/menu/menu.admin.inc

Line #Times calledCode
1
<?php
2
// $Id: menu.admin.inc,v 1.32 2008/07/16 21:59:27 dries Exp $
3
4
/**
5
 * @file
6
 * Administrative page callbaks for menu module.
7
 */
8
9
/**
10
 * Menu callback which shows an overview page of all the custom menus and
their descriptions.
11
 */
12189
function menu_overview_page() {
132
  $result = db_query("SELECT * FROM {menu_custom} ORDER BY title");
142
  $content = array();
152
  while ($menu = db_fetch_array($result)) {
162
    $menu['href'] = 'admin/build/menu-customize/' . $menu['menu_name'];
172
    $menu['localized_options'] = array();
182
    $content[] = $menu;
192
  }
202
  return theme('admin_block_content', $content);
210
}
22
23
/**
24
 * Form for editing an entire menu tree at once.
25
 *
26
 * Shows for one menu the menu items accessible to the current user and
27
 * relevant operations.
28
 */
29189
function menu_overview_form(&$form_state, $menu) {
3031
  global $menu_admin;
31
  $sql = "
32
    SELECT m.load_functions, m.to_arg_functions, m.access_callback,
m.access_arguments, m.page_callback, m.page_arguments, m.title,
m.title_callback, m.title_arguments, m.type, m.description, ml.*
33
    FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path =
ml.router_path
34
    WHERE ml.menu_name = '%s'
3531
    ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8
ASC, p9 ASC";
3631
  $result = db_query($sql, $menu['menu_name']);
3731
  $tree = menu_tree_data($result);
3831
  $node_links = array();
3931
  menu_tree_collect_node_links($tree, $node_links);
40
  // We indicate that a menu administrator is running the menu access
check.
4131
  $menu_admin = TRUE;
4231
  menu_tree_check_access($tree, $node_links);
4331
  $menu_admin = FALSE;
44
4531
  $form = _menu_overview_tree_form($tree);
4631
  $form['#menu'] =  $menu;
4731
  if (element_children($form)) {
4829
    $form['submit'] = array(
4929
      '#type' => 'submit',
5029
      '#value' => t('Save configuration'),
51
    );
5229
  }
53
  else {
542
    $form['empty_menu'] = array('#markup' => t('There are no menu items
yet.'));
55
  }
5631
  return $form;
570
}
58
59
/**
60
 * Recursive helper function for menu_overview_form().
61
 */
62189
function _menu_overview_tree_form($tree) {
6331
  static $form = array('#tree' => TRUE);
6431
  foreach ($tree as $data) {
6529
    $title = '';
6629
    $item = $data['link'];
67
    // Don't show callbacks; these have $item['hidden'] < 0.
6829
    if ($item && $item['hidden'] >= 0) {
6929
      $mlid = 'mlid:' . $item['mlid'];
7029
      $form[$mlid]['#item'] = $item;
7129
      $form[$mlid]['#attributes'] = $item['hidden'] ? array('class' =>
'menu-disabled') : array('class' => 'menu-enabled');
7229
      $form[$mlid]['title']['#markup'] = l($item['title'], $item['href'],
$item['localized_options']) . ($item['hidden'] ? ' (' . t('disabled') . ')'
: '');
7329
      $form[$mlid]['hidden'] = array(
7429
        '#type' => 'checkbox',
7529
        '#default_value' => !$item['hidden'],
76
      );
7729
      $form[$mlid]['expanded'] = array(
7829
        '#type' => 'checkbox',
7929
        '#default_value' => $item['expanded'],
80
      );
8129
      $form[$mlid]['weight'] = array(
8229
        '#type' => 'weight',
8329
        '#delta' => 50,
8429
        '#default_value' => isset($form_state[$mlid]['weight']) ?
$form_state[$mlid]['weight'] : $item['weight'],
85
      );
8629
      $form[$mlid]['mlid'] = array(
8729
        '#type' => 'hidden',
8829
        '#value' => $item['mlid'],
89
      );
9029
      $form[$mlid]['plid'] = array(
9129
        '#type' => 'textfield',
9229
        '#default_value' => isset($form_state[$mlid]['plid']) ?
$form_state[$mlid]['plid'] : $item['plid'],
9329
        '#size' => 6,
94
      );
95
      // Build a list of operations.
9629
      $operations = array();
9729
      $operations['edit'] = l(t('edit'), 'admin/build/menu/item/' .
$item['mlid'] . '/edit');
98
      // Only items created by the menu module can be deleted.
9929
      if ($item['module'] == 'menu' || $item['updated'] == 1) {
10022
        $operations['delete'] = l(t('delete'), 'admin/build/menu/item/' .
$item['mlid'] . '/delete');
10122
      }
102
      // Set the reset column.
10318
      elseif ($item['module'] == 'system' && $item['customized']) {
1043
        $operations['reset'] = l(t('reset'), 'admin/build/menu/item/' .
$item['mlid'] . '/reset');
1053
      }
106
10729
      $form[$mlid]['operations'] = array();
10829
      foreach ($operations as $op => $value) {
10929
        $form[$mlid]['operations'][$op] = array('#markup' => $value);
11029
      }
11129
    }
112
11329
    if ($data['below']) {
11427
      _menu_overview_tree_form($data['below']);
11527
    }
11629
  }
11731
  return $form;
1180
}
119
120
/**
121
 * Submit handler for the menu overview form.
122
 *
123
 * This function takes great care in saving parent items first, then items
124
 * underneath them. Saving items in the incorrect order can break the menu
tree.
125
 *
126
 * @see menu_overview_form()
127
 */
128189
function menu_overview_form_submit($form, &$form_state) {
129
  // When dealing with saving menu items, the order in which these items
are
130
  // saved is critical. If a changed child item is saved before its
parent,
131
  // the child item could be saved with an invalid path past its immediate
132
  // parent. To prevent this, save items in the form in the same order
they
133
  // are sent by $_POST, ensuring parents are saved first, then their
children.
134
  // See http://drupal.org/node/181126#comment-632270
1351
  $order = array_flip(array_keys($form['#post'])); // Get the $_POST
order.
1361
  $form = array_merge($order, $form); // Update our original form with the
new order.
137
1381
  $updated_items = array();
1391
  $fields = array('expanded', 'weight', 'plid');
1401
  foreach (element_children($form) as $mlid) {
1411
    if (isset($form[$mlid]['#item'])) {
1421
      $element = $form[$mlid];
143
      // Update any fields that have changed in this menu item.
1441
      foreach ($fields as $field) {
1451
        if ($element[$field]['#value'] !=
$element[$field]['#default_value']) {
1460
          $element['#item'][$field] = $element[$field]['#value'];
1470
          $updated_items[$mlid] = $element['#item'];
1480
        }
1491
      }
150
      // Hidden is a special case, the value needs to be reversed.
1511
      if ($element['hidden']['#value'] !=
$element['hidden']['#default_value']) {
1521
        $element['#item']['hidden'] = !$element['hidden']['#value'];
1531
        $updated_items[$mlid] = $element['#item'];
1541
      }
1551
    }
1561
  }
157
158
  // Save all our changed items to the database.
1591
  foreach ($updated_items as $item) {
1601
    $item['customized'] = 1;
1611
    menu_link_save($item);
1621
  }
1631
}
164
165
/**
166
 * Theme the menu overview form into a table.
167
 *
168
 * @ingroup themeable
169
 */
170189
function theme_menu_overview_form($form) {
17130
  drupal_add_tabledrag('menu-overview', 'match', 'parent', 'menu-plid',
'menu-plid', 'menu-mlid', TRUE, MENU_MAX_DEPTH - 1);
17230
  drupal_add_tabledrag('menu-overview', 'order', 'sibling',
'menu-weight');
173
174
  $header = array(
17530
    t('Menu item'),
17630
    array('data' => t('Enabled'), 'class' => 'checkbox'),
17730
    array('data' => t('Expanded'), 'class' => 'checkbox'),
17830
    t('Weight'),
17930
    array('data' => t('Operations'), 'colspan' => '3'),
18030
  );
181
18230
  $rows = array();
18330
  foreach (element_children($form) as $mlid) {
18430
    if (isset($form[$mlid]['hidden'])) {
18528
      $element = &$form[$mlid];
186
      // Build a list of operations.
18728
      $operations = array();
18828
      foreach (element_children($element['operations']) as $op) {
18928
        $operations[] = drupal_render($element['operations'][$op]);
19028
      }
19128
      while (count($operations) < 2) {
19217
        $operations[] = '';
19317
      }
194
195
      // Add special classes to be used for tabledrag.js.
19628
      $element['plid']['#attributes']['class'] = 'menu-plid';
19728
      $element['mlid']['#attributes']['class'] = 'menu-mlid';
19828
      $element['weight']['#attributes']['class'] = 'menu-weight';
199
200
      // Change the parent field to a hidden. This allows any value but
hides the field.
20128
      $element['plid']['#type'] = 'hidden';
202
20328
      $row = array();
20428
      $row[] = theme('indentation', $element['#item']['depth'] - 1) .
drupal_render($element['title']);
20528
      $row[] = array('data' => drupal_render($element['hidden']), 'class'
=> 'checkbox');
20628
      $row[] = array('data' => drupal_render($element['expanded']), 'class'
=> 'checkbox');
20728
      $row[] = drupal_render($element['weight']) .
drupal_render($element['plid']) . drupal_render($element['mlid']);
20828
      $row = array_merge($row, $operations);
209
21028
      $row = array_merge(array('data' => $row), $element['#attributes']);
21128
      $row['class'] = !empty($row['class']) ? $row['class'] . ' draggable'
: 'draggable';
21228
      $rows[] = $row;
21328
    }
21430
  }
21530
  $output = '';
21630
  if ($rows) {
21728
    $output .= theme('table', $header, $rows, array('id' =>
'menu-overview'));
21828
  }
21930
  $output .= drupal_render($form);
22030
  return $output;
2210
}
222
223
/**
224
 * Menu callback; Build the menu link editing form.
225
 */
226189
function menu_edit_item(&$form_state, $type, $item, $menu) {
227
22846
  $form['menu'] = array(
22946
    '#type' => 'fieldset',
23046
    '#title' => t('Menu settings'),
23146
    '#collapsible' => FALSE,
23246
    '#tree' => TRUE,
23346
    '#weight' => -2,
23446
    '#attributes' => array('class' => 'menu-item-form'),
23546
    '#item' => $item,
236
  );
23746
  if ($type == 'add' || empty($item)) {
238
    // This is an add form, initialize the menu link.
23920
    $item = array('link_title' => '', 'mlid' => 0, 'plid' => 0, 'menu_name'
=> $menu['menu_name'], 'weight' => 0, 'link_path' => '', 'options' =>
array(), 'module' => 'menu', 'expanded' => 0, 'hidden' => 0, 'has_children'
=> 0);
24020
  }
24146
  foreach (array('link_path', 'mlid', 'module', 'has_children', 'options')
as $key) {
24246
    $form['menu'][$key] = array('#type' => 'value', '#value' =>
$item[$key]);
24346
  }
244
  // Any item created or edited via this interface is considered
"customized".
24546
  $form['menu']['customized'] = array('#type' => 'value', '#value' => 1);
24646
  $form['menu']['original_item'] = array('#type' => 'value', '#value' =>
$item);
247
24846
  $path = $item['link_path'];
24946
  if (isset($item['options']['query'])) {
2500
    $path .= '?' . $item['options']['query'];
2510
  }
25246
  if (isset($item['options']['fragment'])) {
2530
    $path .= '#' . $item['options']['fragment'];
2540
  }
25546
  if ($item['module'] == 'menu') {
25644
    $form['menu']['link_path'] = array(
25744
      '#type' => 'textfield',
25844
      '#title' => t('Path'),
25944
      '#default_value' => $path,
26044
      '#description' => t('The path this menu item links to. This can be an
internal Drupal path such as %add-node or an external URL such as %drupal.
Enter %front to link to the front page.', array('%front' => '<front>',
'%add-node' => 'node/add', '%drupal' => 'http://drupal.org')),
26144
      '#required' => TRUE,
262
    );
26344
    $form['delete'] = array(
26444
      '#type' => 'submit',
26544
      '#value' => t('Delete'),
26644
      '#access' => $item['mlid'],
26744
      '#submit' => array('menu_item_delete_submit'),
26844
      '#weight' => 10,
269
    );
27044
  }
271
  else {
2722
    $form['menu']['_path'] = array(
2732
      '#type' => 'item',
2742
      '#title' => t('Path'),
2752
      '#description' => l($item['link_title'], $item['href'],
$item['options']),
276
    );
277
  }
27846
  $form['menu']['link_title'] = array('#type' => 'textfield',
27946
    '#title' => t('Menu link title'),
28046
    '#default_value' => $item['link_title'],
28146
    '#description' => t('The link text corresponding to this item that
should appear in the menu.'),
28246
    '#required' => TRUE,
283
  );
28446
  $form['menu']['description'] = array(
28546
    '#type' => 'textarea',
28646
    '#title' => t('Description'),
28746
    '#default_value' => isset($item['options']['attributes']['title']) ?
$item['options']['attributes']['title'] : '',
28846
    '#rows' => 1,
28946
    '#description' => t('The description displayed when hovering over a
menu item.'),
290
  );
29146
  $form['menu']['enabled'] = array(
29246
    '#type' => 'checkbox',
29346
    '#title' => t('Enabled'),
29446
    '#default_value' => !$item['hidden'],
29546
    '#description' => t('Menu items that are not enabled will not be listed
in any menu.'),
296
  );
29746
  $form['menu']['expanded'] = array(
29846
    '#type' => 'checkbox',
29946
    '#title' => t('Expanded'),
30046
    '#default_value' => $item['expanded'],
30146
    '#description' => t('If selected and this menu item has children, the
menu will always appear expanded.'),
302
  );
303
304
  // Generate a list of possible parents (not including this item or
descendants).
30546
  $options = menu_parent_options(menu_get_menus(), $item);
30646
  $default = $item['menu_name'] . ':' . $item['plid'];
30746
  if (!isset($options[$default])) {
3080
    $default = 'navigation:0';
3090
  }
31046
  $form['menu']['parent'] = array(
31146
    '#type' => 'select',
31246
    '#title' => t('Parent item'),
31346
    '#default_value' => $default,
31446
    '#options' => $options,
31546
    '#description' => t('The maximum depth for an item and all its children
is fixed at !maxdepth. Some menu items may not be available as parents if
selecting them would exceed this limit.', array('!maxdepth' =>
MENU_MAX_DEPTH)),
31646
    '#attributes' => array('class' => 'menu-title-select'),
317
  );
31846
  $form['menu']['weight'] = array(
31946
    '#type' => 'weight',
32046
    '#title' => t('Weight'),
32146
    '#delta' => 50,
32246
    '#default_value' => $item['weight'],
32346
    '#description' => t('Optional. In the menu, the heavier items will sink
and the lighter items will be positioned nearer the top.'),
324
  );
32546
  $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
326
327
32846
  return $form;
3290
}
330
331
/**
332
 * Validate form values for a menu link being added or edited.
333
 */
334189
function menu_edit_item_validate($form, &$form_state) {
33521
  $item = &$form_state['values']['menu'];
33621
  $normal_path = drupal_get_normal_path($item['link_path']);
33721
  if ($item['link_path'] != $normal_path) {
3380
    drupal_set_message(t('The menu system stores system paths only, but
will use the URL alias for display. %link_path has been stored as
%normal_path', array('%link_path' => $item['link_path'], '%normal_path' =>
$normal_path)));
3390
    $item['link_path'] = $normal_path;
3400
  }
34121
  if (!menu_path_is_external($item['link_path'])) {
34221
    $parsed_link = parse_url($item['link_path']);
34321
    if (isset($parsed_link['query'])) {
3440
      $item['options']['query'] = $parsed_link['query'];
3450
    }
34621
    if (isset($parsed_link['fragment'])) {
3470
      $item['options']['fragment'] = $parsed_link['fragment'];
3480
    }
34921
    if ($item['link_path'] != $parsed_link['path']) {
3500
      $item['link_path'] = $parsed_link['path'];
3510
    }
35221
  }
35321
  if (!trim($item['link_path']) || !menu_valid_path($item)) {
3544
    form_set_error('link_path', t("The path '@link_path' is either invalid
or you do not have access to it.", array('@link_path' =>
$item['link_path'])));
3554
  }
35621
}
357
358
/**
359
 * Submit function for the delete button on the menu item editing form.
360
 */
361189
function menu_item_delete_submit($form, &$form_state) {
3620
  $form_state['redirect'] = 'admin/build/menu/item/' .
$form_state['values']['menu']['mlid'] . '/delete';
3630
}
364
365
/**
366
 * Process menu and menu item add/edit form submissions.
367
 */
368189
function menu_edit_item_submit($form, &$form_state) {
36917
  $item = $form_state['values']['menu'];
370
371
  // The value of "hidden" is the opposite of the value
372
  // supplied by the "enabled" checkbox.
37317
  $item['hidden'] = (int) !$item['enabled'];
37417
  unset($item['enabled']);
375
37617
  $item['options']['attributes']['title'] = $item['description'];
37717
  list($item['menu_name'], $item['plid']) = explode(':', $item['parent']);
37817
  if (!menu_link_save($item)) {
3790
    drupal_set_message(t('There was an error saving the menu link.'),
'error');
3800
  }
38117
  $form_state['redirect'] = 'admin/build/menu-customize/' .
$item['menu_name'];
38217
}
383
384
/**
385
 * Menu callback; Build the form that handles the adding/editing of a
custom menu.
386
 */
387189
function menu_edit_menu(&$form_state, $type, $menu = array()) {
3883
  if ($type == 'edit') {
3890
    $form['menu_name'] = array('#type' => 'value', '#value' =>
$menu['menu_name']);
3900
    $form['#insert'] = FALSE;
3910
    $form['delete'] = array(
3920
      '#type' => 'submit',
3930
      '#value' => t('Delete'),
3940
      '#access' => !in_array($menu['menu_name'],
menu_list_system_menus()),
3950
      '#submit' => array('menu_custom_delete_submit'),
3960
      '#weight' => 10,
397
    );
3980
  }
399
  else {
4003
    $menu = array('menu_name' => '', 'title' => '', 'description' => '');
4013
    $form['menu_name'] = array(
4023
      '#type' => 'textfield',
4033
      '#title' => t('Menu name'),
4043
      '#maxsize' => MENU_MAX_MENU_NAME_LENGTH_UI,
4053
      '#description' => t('The machine-readable name of this menu. This
text will be used for constructing the URL of the <em>menu overview</em>
page for this menu. This name must contain only lowercase letters, numbers,
and hyphens, and must be unique.'),
4063
      '#required' => TRUE,
407
    );
4083
    $form['#insert'] = TRUE;
409
  }
4103
  $form['#title'] = $menu['title'];
4113
  $form['title'] = array(
4123
    '#type' => 'textfield',
4133
    '#title' => t('Title'),
4143
    '#default_value' => $menu['title'],
4153
    '#required' => TRUE,
416
  );
4173
  $form['description'] = array(
4183
    '#type' => 'textarea',
4193
    '#title' => t('Description'),
4203
    '#default_value' => $menu['description'],
421
  );
4223
  $form['submit'] = array(
4233
    '#type' => 'submit',
4243
    '#value' => t('Save'),
425
  );
426
4273
  return $form;
4280
}
429
430
/**
431
 * Submit function for the 'Delete' button on the menu editing form.
432
 */
433189
function menu_custom_delete_submit($form, &$form_state) {
4340
  $form_state['redirect'] = 'admin/build/menu-customize/' .
$form_state['values']['menu_name'] . '/delete';
4350
}
436
437
/**
438
 * Menu callback; check access and get a confirm form for deletion of a
custom menu.
439
 */
440189
function menu_delete_menu_page($menu) {
441
  // System-defined menus may not be deleted.
4422
  if (in_array($menu['menu_name'], menu_list_system_menus())) {
4430
    drupal_access_denied();
4440
    return;
4450
  }
4462
  return drupal_get_form('menu_delete_menu_confirm', $menu);
4470
}
448
449
/**
450
 * Build a confirm form for deletion of a custom menu.
451
 */
452189
function menu_delete_menu_confirm(&$form_state, $menu) {
4532
  $form['#menu'] = $menu;
4542
  $caption = '';
4552
  $num_links = db_result(db_query("SELECT COUNT(*) FROM {menu_links} WHERE
menu_name = '%s'", $menu['menu_name']));
4562
  if ($num_links) {
4570
    $caption .= '<p>' . format_plural($num_links,
'<strong>Warning:</strong> There is currently 1 menu item in %title. It
will be deleted (system-defined items will be reset).',
'<strong>Warning:</strong> There are currently @count menu items in %title.
They will be deleted (system-defined items will be reset).', array('%title'
=> $menu['title'])) . '</p>';
4580
  }
4592
  $caption .= '<p>' . t('This action cannot be undone.') . '</p>';
4602
  return confirm_form($form, t('Are you sure you want to delete the custom
menu %title?', array('%title' => $menu['title'])),
'admin/build/menu-customize/' . $menu['menu_name'], $caption,
t('Delete'));
4610
}
462
463
/**
464
 * Delete a custom menu and all items in it.
465
 */
466189
function menu_delete_menu_confirm_submit($form, &$form_state) {
4671
  $menu = $form['#menu'];
4681
  $form_state['redirect'] = 'admin/build/menu';
469
  // System-defined menus may not be deleted - only menus defined by this
module.
4701
  if (in_array($menu['menu_name'], menu_list_system_menus())  ||
!db_result(db_query("SELECT COUNT(*) FROM {menu_custom} WHERE menu_name =
'%s'", $menu['menu_name']))) {
4710
    return;
4720
  }
473
  // Reset all the menu links defined by the system via hook_menu.
4741
  $result = db_query("SELECT * FROM {menu_links} ml INNER JOIN
{menu_router} m ON ml.router_path = m.path WHERE ml.menu_name = '%s' AND
ml.module = 'system' ORDER BY m.number_parts ASC", $menu['menu_name']);
4751
  while ($item = db_fetch_array($result)) {
4760
    menu_reset_item($item);
4770
  }
478
  // Delete all links to the overview page for this menu.
4791
  $result = db_query("SELECT mlid FROM {menu_links} ml WHERE ml.link_path =
'%s'", 'admin/build/menu-customize/' . $menu['menu_name']);
4801
  while ($m = db_fetch_array($result)) {
4811
    menu_link_delete($m['mlid']);
4821
  }
483
  // Delete all the links in the menu and the menu from the list of custom
menus.
4841
  db_query("DELETE FROM {menu_links} WHERE menu_name = '%s'",
$menu['menu_name']);
4851
  db_query("DELETE FROM {menu_custom} WHERE menu_name = '%s'",
$menu['menu_name']);
486
  // Delete all the blocks for this menu.
4871
  db_query("DELETE FROM {blocks} WHERE module = 'menu' AND delta = '%s'",
$menu['menu_name']);
4881
  db_query("DELETE FROM {blocks_roles} WHERE module = 'menu' AND delta =
'%s'", $menu['menu_name']);
4891
  menu_cache_clear_all();
4901
  cache_clear_all();
4911
  $t_args = array('%title' => $menu['title']);
4921
  drupal_set_message(t('The custom menu %title has been deleted.',
$t_args));
4931
  watchdog('menu', 'Deleted custom menu %title and all its menu items.',
$t_args, WATCHDOG_NOTICE);
4941
}
495
496
/**
497
 * Validates the human and machine-readable names when adding or editing a
menu.
498
 */
499189
function menu_edit_menu_validate($form, &$form_state) {
5001
  $item = $form_state['values'];
5011
  if (preg_match('/[^a-z0-9-]/', $item['menu_name'])) {
5020
    form_set_error('menu_name', t('The menu name may only consist of
lowercase letters, numbers, and hyphens.'));
5030
  }
5041
  if (strlen($item['menu_name']) > MENU_MAX_MENU_NAME_LENGTH_UI) {
5050
    form_set_error('menu_name', format_plural(MENU_MAX_MENU_NAME_LENGTH_UI,
"The menu name can't be longer than 1 character.", "The menu name can't be
longer than @count characters."));
5060
  }
5071
  if ($form['#insert']) {
508
    // We will add 'menu-' to the menu name to help avoid name-space
conflicts.
5091
    $item['menu_name'] = 'menu-' . $item['menu_name'];
5101
    if (db_result(db_query("SELECT menu_name FROM {menu_custom} WHERE
menu_name = '%s'", $item['menu_name'])) ||
5111
      db_result(db_query_range("SELECT menu_name FROM {menu_links} WHERE
menu_name = '%s'", $item['menu_name'], 0, 1))) {
5120
      form_set_error('menu_name', t('The menu already exists.'));
5130
    }
5141
  }
5151
}
516
517
/**
518
 * Submit function for adding or editing a custom menu.
519
 */
520189
function menu_edit_menu_submit($form, &$form_state) {
5211
  $menu = $form_state['values'];
5221
  $path = 'admin/build/menu-customize/';
5231
  if ($form['#insert']) {
524
    // Add 'menu-' to the menu name to help avoid name-space conflicts.
5251
    $menu['menu_name'] = 'menu-' . $menu['menu_name'];
5261
    $link['link_title'] = $menu['title'];
5271
    $link['link_path'] = $path . $menu['menu_name'];
5281
    $link['router_path'] = $path . '%';
5291
    $link['module'] = 'menu';
5301
    $link['plid'] = db_result(db_query("SELECT mlid FROM {menu_links} WHERE
link_path = '%s' AND module = '%s'", 'admin/build/menu', 'system'));
5311
    menu_link_save($link);
5321
    db_query("INSERT INTO {menu_custom} (menu_name, title, description)
VALUES ('%s', '%s', '%s')", $menu['menu_name'], $menu['title'],
$menu['description']);
5331
  }
534
  else {
5350
    db_query("UPDATE {menu_custom} SET title = '%s', description = '%s'
WHERE menu_name = '%s'", $menu['title'], $menu['description'],
$menu['menu_name']);
5360
    $result = db_query("SELECT mlid FROM {menu_links} WHERE link_path =
'%s'", $path . $menu['menu_name']);
5370
    while ($m = db_fetch_array($result)) {
5380
      $link = menu_link_load($m['mlid']);
5390
      $link['link_title'] = $menu['title'];
5400
      menu_link_save($link);
5410
    }
542
  }
5431
  $form_state['redirect'] = $path . $menu['menu_name'];
5441
}
545
546
/**
547
 * Menu callback; Check access and present a confirm form for deleting a
menu link.
548
 */
549189
function menu_item_delete_page($item) {
550
  // Links defined via hook_menu may not be deleted. Updated items are an
551
  // exception, as they can be broken.
5528
  if ($item['module'] == 'system' && !$item['updated']) {
5530
    drupal_access_denied();
5540
    return;
5550
  }
5568
  return drupal_get_form('menu_item_delete_form', $item);
5570
}
558
559
/**
560
 * Build a confirm form for deletion of a single menu link.
561
 */
562189
function menu_item_delete_form(&$form_state, $item) {
5638
  $form['#item'] = $item;
5648
  return confirm_form($form, t('Are you sure you want to delete the custom
menu item %item?', array('%item' => $item['link_title'])),
'admin/build/menu-customize/' . $item['menu_name']);
5650
}
566
567
/**
568
 * Process menu delete form submissions.
569
 */
570189
function menu_item_delete_form_submit($form, &$form_state) {
5714
  $item = $form['#item'];
5724
  menu_link_delete($item['mlid']);
5734
  $t_args = array('%title' => $item['link_title']);
5744
  drupal_set_message(t('The menu item %title has been deleted.',
$t_args));
5754
  watchdog('menu', 'Deleted menu item %title.', $t_args, WATCHDOG_NOTICE);
5764
  $form_state['redirect'] = 'admin/build/menu-customize/' .
$item['menu_name'];
5774
}
578
579
/**
580
 * Menu callback; reset a single modified item.
581
 */
582189
function menu_reset_item_confirm(&$form_state, $item) {
5832
  $form['item'] = array('#type' => 'value', '#value' => $item);
5842
  return confirm_form($form, t('Are you sure you want to reset the item
%item to its default values?', array('%item' => $item['link_title'])),
'admin/build/menu-customize/' . $item['menu_name'], t('Any customizations
will be lost. This action cannot be undone.'), t('Reset'));
5850
}
586
587
/**
588
 * Process menu reset item form submissions.
589
 */
590189
function menu_reset_item_confirm_submit($form, &$form_state) {
5911
  $item = $form_state['values']['item'];
5921
  $new_item = menu_reset_item($item);
5931
  drupal_set_message(t('The menu item was reset to its default
settings.'));
5941
  $form_state['redirect'] = 'admin/build/menu-customize/' .
$new_item['menu_name'];
5951
}
596
597
/**
598
 * Menu callback; Build the form presenting menu configuration options.
599
 */
600189
function menu_configure() {
6010
  $form['intro'] = array(
6020
    '#type' => 'item',
6030
    '#markup' => t('The menu module allows on-the-fly creation of menu
links in the content authoring forms. The following option sets the default
menu in which a new link will be added.'),
604
  );
605
6060
  $menu_options = menu_get_menus();
6070
  $form['menu_default_node_menu'] = array(
6080
    '#type' => 'select',
6090
    '#title' => t('Default menu for content'),
6100
    '#default_value' => variable_get('menu_default_node_menu',
'main-menu'),
6110
    '#options' => $menu_options,
6120
    '#description' => t('Choose the menu to be the default in the menu
options in the content authoring form.'),
613
  );
614
6150
  $main = variable_get('menu_main_menu_source', 'main-menu');
6160
  $main_options = array_merge($menu_options, array('' => t('No Main
menu')));
6170
  $form['menu_main_menu_source'] = array(
6180
    '#type' => 'select',
6190
    '#title' => t('Source for the Main menu'),
6200
    '#default_value' => $main,
6210
    '#options' => $main_options,
6220
    '#tree' => FALSE,
6230
    '#description' => t('Select what should be displayed as the Main
menu.'),
624
  );
625
6260
  $secondary_options = array_merge($menu_options, array('' => t('No
Secondary menu')));
6270
  $form["menu_secondary_menu_source"] = array(
6280
    '#type' => 'select',
6290
    '#title' => t('Source for the Secondary menu'),
6300
    '#default_value' => variable_get('menu_secondary_menu_source',
'secondary-menu'),
6310
    '#options' => $secondary_options,
6320
    '#tree' => FALSE,
6330
    '#description' => t("Select the source for the Secondary menu. An
advanced option allows you to use the same source for both Main menu
(currently %main) and Secondary menu: if your source menu has two levels of
hierarchy, the top level menu items will appear in the Main menu, and the
children of the active item will appear in the Secondary menu." ,
array('%main' => $main_options[$main])),
634
  );
635
6360
  return system_settings_form($form);
6370
}
638189