Index: includes/menu.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/menu.inc,v retrieving revision 1.346 diff -u -p -r1.346 menu.inc --- includes/menu.inc 18 Sep 2009 10:54:20 -0000 1.346 +++ includes/menu.inc 24 Sep 2009 01:54:35 -0000 @@ -1409,7 +1409,13 @@ function menu_get_names() { * Return an array containing the names of system-defined (default) menus. */ function menu_list_system_menus() { - return array('navigation' => 'Navigation', 'management' => 'Management', 'user-menu' => 'User menu', 'main-menu' => 'Main menu', 'secondary-menu' => 'Secondary menu'); + return array( + 'navigation' => 'Navigation', + 'management' => 'Management', + 'user-menu' => 'User menu', + 'main-menu' => 'Main menu', + 'secondary-menu' => 'Secondary menu', + ); } /** Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.379 diff -u -p -r1.379 block.module --- modules/block/block.module 22 Sep 2009 07:50:15 -0000 1.379 +++ modules/block/block.module 24 Sep 2009 01:02:31 -0000 @@ -808,6 +808,20 @@ function block_filter_format_delete($for } /** + * Implement hook_menu_custom_delete(). + */ +function block_menu_custom_delete($menu) { + db_delete('block') + ->condition('module', 'menu') + ->condition('delta', $menu['menu_name']) + ->execute(); + db_delete('block_role') + ->condition('module', 'menu') + ->condition('delta', $menu['menu_name']) + ->execute(); +} + +/** * Implement hook_form_FORM_ID_alter(). */ function block_form_system_performance_settings_alter(&$form, &$form_state) { Index: modules/menu/menu.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.admin.inc,v retrieving revision 1.59 diff -u -p -r1.59 menu.admin.inc --- modules/menu/menu.admin.inc 18 Sep 2009 00:12:46 -0000 1.59 +++ modules/menu/menu.admin.inc 24 Sep 2009 01:42:45 -0000 @@ -514,39 +514,28 @@ function menu_delete_menu_confirm($form, function menu_delete_menu_confirm_submit($form, &$form_state) { $menu = $form['#menu']; $form_state['redirect'] = 'admin/structure/menu'; + // System-defined menus may not be deleted - only menus defined by this module. $system_menus = menu_list_system_menus(); if (isset($system_menus[$menu['menu_name']]) || !(db_query("SELECT 1 FROM {menu_custom} WHERE menu_name = :menu", array(':menu' => $menu['menu_name']))->fetchField())) { return; } - // Reset all the menu links defined by the system via hook_menu. + + // Reset all the menu links defined by the system via hook_menu(). $result = db_query("SELECT * FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.menu_name = :menu AND ml.module = 'system' ORDER BY m.number_parts ASC", array(':menu' => $menu['menu_name']), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $item) { menu_reset_item($item); } + // Delete all links to the overview page for this menu. $result = db_query("SELECT mlid FROM {menu_links} ml WHERE ml.link_path = :link", array(':link' => 'admin/structure/menu-customize/' . $menu['menu_name']), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $m) { menu_link_delete($m['mlid']); } - // Delete all the links in the menu and the menu from the list of custom menus. - db_delete('menu_links') - ->condition('menu_name', $menu['menu_name']) - ->execute(); - db_delete('menu_custom') - ->condition('menu_name', $menu['menu_name']) - ->execute(); - // Delete all the blocks for this menu. - if (module_exists('block')) { - db_delete('block') - ->condition('module', 'menu') - ->condition('delta', $menu['menu_name']) - ->execute(); - db_delete('block_role') - ->condition('module', 'menu') - ->condition('delta', $menu['menu_name']) - ->execute(); - } + + // Delete the custom menu and all its menu links. + menu_custom_delete($menu); + menu_cache_clear_all(); cache_clear_all(); $t_args = array('%title' => $menu['title']); @@ -597,22 +586,10 @@ function menu_edit_menu_submit($form, &$ ->fetchField(); menu_link_save($link); - db_insert('menu_custom') - ->fields(array( - 'menu_name' => $menu['menu_name'], - 'title' => $menu['title'], - 'description' => $menu['description'], - )) - ->execute(); + menu_custom_save($menu); } else { - db_update('menu_custom') - ->fields(array( - 'title' => $menu['title'], - 'description' => $menu['description'], - )) - ->condition('menu_name', $menu['menu_name']) - ->execute(); + menu_custom_save($menu); $result = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path", array(':path' => $path . $menu['menu_name']), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $m) { $link = menu_link_load($m['mlid']); Index: modules/menu/menu.install =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.install,v retrieving revision 1.20 diff -u -p -r1.20 menu.install --- modules/menu/menu.install 10 Sep 2009 06:38:19 -0000 1.20 +++ modules/menu/menu.install 24 Sep 2009 01:50:10 -0000 @@ -11,17 +11,21 @@ */ function menu_install() { $system_menus = menu_list_system_menus(); + $t = get_t(); $descriptions = array( - 'navigation' => 'The Navigation menu contains links such as Recent posts (if the Tracker module is enabled). Non-administrative links are added to this menu by default by modules.', - 'user-menu' => "The User menu contains links related to the user's account, as well as the 'Log out' link.", - 'management' => 'The Management menu contains links for content creation, structure, user management, and similar site activities.', - 'main-menu' => 'The Main menu is the default source for the Main links which are often used by themes to show the major sections of a site.', - 'secondary-menu' => 'The Secondary menu is the default source for the Secondary links which are often used for legal notices, contact details, and other navigation items that play a lesser role than the Main links.', + 'navigation' => $t('The Navigation menu contains links such as Recent posts (if the Tracker module is enabled). Non-administrative links are added to this menu by default by modules.'), + 'user-menu' => $t("The User menu contains links related to the user's account, as well as the 'Log out' link."), + 'management' => $t('The Management menu contains links for content creation, structure, user management, and similar site activities.'), + 'main-menu' => $t('The Main menu is the default source for the Main links which are often used by themes to show the major sections of a site.'), + 'secondary-menu' => $t('The Secondary menu is the default source for the Secondary links which are often used for legal notices, contact details, and other navigation items that play a lesser role than the Main links.'), ); - $t = get_t(); - $query = db_insert('menu_custom')->fields(array('menu_name', 'title', 'description')); foreach ($system_menus as $menu_name => $title) { - $query->values(array('menu_name' => $menu_name, 'title' => $t($title), 'description' => $t($descriptions[$menu_name])))->execute(); + $menu = array( + 'menu_name' => $menu_name, + 'title' => $t($title), + 'description' => $descriptions[$menu_name], + ); + menu_custom_save($menu); } } Index: modules/menu/menu.module =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v retrieving revision 1.204 diff -u -p -r1.204 menu.module --- modules/menu/menu.module 18 Sep 2009 00:04:22 -0000 1.204 +++ modules/menu/menu.module 24 Sep 2009 01:43:37 -0000 @@ -78,7 +78,7 @@ function menu_menu() { 'weight' => 5, 'file' => 'menu.admin.inc', ); - $items['admin/structure/menu-customize/%menu'] = array( + $items['admin/structure/menu-customize/%menu_custom'] = array( 'title' => 'Customize menu', 'page callback' => 'drupal_get_form', 'page arguments' => array('menu_overview_form', 3), @@ -88,12 +88,12 @@ function menu_menu() { 'type' => MENU_CALLBACK, 'file' => 'menu.admin.inc', ); - $items['admin/structure/menu-customize/%menu/list'] = array( + $items['admin/structure/menu-customize/%menu_custom/list'] = array( 'title' => 'List links', 'weight' => -10, 'type' => MENU_DEFAULT_LOCAL_TASK, ); - $items['admin/structure/menu-customize/%menu/add'] = array( + $items['admin/structure/menu-customize/%menu_custom/add'] = array( 'title' => 'Add link', 'page callback' => 'drupal_get_form', 'page arguments' => array('menu_edit_item', 'add', NULL, 3), @@ -101,7 +101,7 @@ function menu_menu() { 'type' => MENU_LOCAL_ACTION, 'file' => 'menu.admin.inc', ); - $items['admin/structure/menu-customize/%menu/edit'] = array( + $items['admin/structure/menu-customize/%menu_custom/edit'] = array( 'title' => 'Edit menu', 'page callback' => 'drupal_get_form', 'page arguments' => array('menu_edit_menu', 'edit', 3), @@ -109,7 +109,7 @@ function menu_menu() { 'type' => MENU_LOCAL_TASK, 'file' => 'menu.admin.inc', ); - $items['admin/structure/menu-customize/%menu/delete'] = array( + $items['admin/structure/menu-customize/%menu_custom/delete'] = array( 'title' => 'Delete menu', 'page callback' => 'menu_delete_menu_page', 'page arguments' => array(3), @@ -198,12 +198,68 @@ function menu_overview_title($menu) { /** * Load the data for a single custom menu. + * + * @param $menu_name + * The unique name of a custom menu to load. */ -function menu_load($menu_name) { +function menu_custom_load($menu_name) { return db_query("SELECT * FROM {menu_custom} WHERE menu_name = :menu", array(':menu' => $menu_name))->fetchAssoc(); } /** + * Save a custom menu. + * + * @param $menu + * An array representing a custom menu: + * - menu_name: The unique name of the custom menu. + * - title: The human readable menu title. + * - description: The custom menu description. + * + * Modules should always pass a fully populated $menu when saving a custom + * menu, so other modules are able to output proper status or watchdog messages. + * + * @see menu_custom_load() + */ +function menu_custom_save($menu) { + db_merge('menu_custom') + ->key(array('menu_name' => $menu['menu_name'])) + ->fields(array( + 'title' => $menu['title'], + 'description' => $menu['description'], + )) + ->execute(); + + module_invoke_all('menu_custom_save', $menu); +} + +/** + * Delete a custom menu. + * + * @param $menu + * An array representing a custom menu: + * - menu_name: The unique name of the custom menu. + * - title: The human readable menu title. + * - description: The custom menu description. + * + * Modules should always pass a fully populated $menu when deleting a custom + * menu, so other modules are able to output proper status or watchdog messages. + * + * @see menu_custom_load() + */ +function menu_custom_delete($menu) { + // Delete the custom menu. + db_delete('menu_custom') + ->condition('menu_name', $menu['menu_name']) + ->execute(); + // Delete all links from the menu. + db_delete('menu_links') + ->condition('menu_name', $menu['menu_name']) + ->execute(); + + module_invoke_all('menu_custom_delete', $menu); +} + +/** * Return a list of menu items that are valid possible parents for the given menu item. * * @param $menus @@ -496,3 +552,4 @@ function menu_get_menus($all = TRUE) { return $query->execute()->fetchAllKeyed(); } + Index: modules/menu/menu.test =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.test,v retrieving revision 1.21 diff -u -p -r1.21 menu.test --- modules/menu/menu.test 17 Sep 2009 03:18:30 -0000 1.21 +++ modules/menu/menu.test 24 Sep 2009 01:53:04 -0000 @@ -92,11 +92,38 @@ class MenuTestCase extends DrupalWebTest $this->menu = $this->addCustomMenu(); $this->doMenuTests($this->menu['menu_name']); $this->addInvalidMenuLink($this->menu['menu_name']); + $this->addCustomMenuCRUD(); + } + + /** + * Add custom menu using CRUD functions. + */ + function addCustomMenuCRUD() { + // Add a new custom menu. + $menu_name = substr(md5($this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI); + $title = $this->randomName(16); + + $menu = array( + 'menu_name' => $menu_name, + 'title' => $title, + 'description' => 'Description text', + ); + menu_custom_save($menu); + + // Assert the new menu. + $this->drupalGet('admin/structure/menu-customize/' . $menu_name . '/edit'); + $this->assertText($title, t('Custom menu was added.')); + + // Edit the menu. + $new_title = $this->randomName(16); + $menu['title'] = $new_title; + menu_custom_save($menu); + $this->drupalGet('admin/structure/menu-customize/' . $menu_name . '/edit'); + $this->assertText($new_title, t('Custom menu was edited.')); } /** * Add custom menu. - * */ function addCustomMenu() { // Add custom menu. @@ -135,7 +162,7 @@ class MenuTestCase extends DrupalWebTest $this->assertResponse(200); $this->assertText(t('The block settings have been updated.'), t('Custom menu block was enabled')); - return menu_load($menu_name); + return menu_custom_load($menu_name); } /** @@ -151,7 +178,10 @@ class MenuTestCase extends DrupalWebTest $this->drupalPost("admin/structure/menu-customize/$menu_name/delete", array(), t('Delete')); $this->assertResponse(200); $this->assertRaw(t('The custom menu %title has been deleted.', array('%title' => $title)), t('Custom menu was deleted')); - $this->assertFalse(menu_load($menu_name), 'Custom menu was deleted'); + $this->assertFalse(menu_custom_load($menu_name), 'Custom menu was deleted'); + // Test if all menu links associated to the menu were removed from database. + $result = db_query("SELECT menu_name FROM {menu_links} WHERE menu_name = :menu_name", array(':menu_name' => $menu_name))->fetchField(); + $this->assertFalse($result, t('All menu links associated to the custom menu were deleted.')); } /** Index: modules/toolbar/toolbar.install =================================================================== RCS file: /cvs/drupal/drupal/modules/toolbar/toolbar.install,v retrieving revision 1.4 diff -u -p -r1.4 toolbar.install --- modules/toolbar/toolbar.install 31 Aug 2009 17:09:01 -0000 1.4 +++ modules/toolbar/toolbar.install 24 Sep 2009 01:51:51 -0000 @@ -14,13 +14,12 @@ */ function toolbar_install() { $t = get_t(); - $query = db_insert('menu_custom') - ->fields(array( - 'menu_name' => 'admin_shortcuts', - 'title' => $t('Administration shortcuts'), - 'description' => $t('The Admininstration shortcuts menu contains commonly used links for administrative tasks.') - )) - ->execute(); + $menu = array( + 'menu_name' => 'admin_shortcuts', + 'title' => $t('Administration shortcuts'), + 'description' => $t('The Administration shortcuts menu contains commonly used links for administrative tasks.'), + ); + menu_custom_save($menu); // Add starter convenience shortcuts. menu_rebuild();