? 457450-menu-item-hooks.patch ? 457450-menu-objects-ext.patch ? 457450-menu-objects_7.patch ? 557148-drupal-htmlspecialchars.patch ? test.patch ? sites/default/files ? sites/default/private Index: includes/menu.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/menu.inc,v retrieving revision 1.337 diff -u -p -r1.337 menu.inc --- includes/menu.inc 22 Aug 2009 19:58:27 -0000 1.337 +++ includes/menu.inc 23 Aug 2009 20:21:54 -0000 @@ -2139,6 +2139,9 @@ function _menu_delete_item($item, $force } db_delete('menu_links')->condition('mlid', $item['mlid'])->execute(); + // Notify modules we have deleted the item. + module_invoke_all('menu_item_delete', $item); + // Update the has_children status of the parent. _menu_update_parental_status($item); menu_cache_clear($item['menu_name']); @@ -2333,7 +2336,13 @@ function menu_link_save(&$item) { if ($existing_item && $menu_name != $existing_item['menu_name']) { menu_cache_clear($existing_item['menu_name']); } - + // Notify modules we have acted on a menu item. + $hook = 'menu_item_insert'; + if ($existing_item) { + $hook = 'menu_item_update'; + } + module_invoke_all($hook, $item); + // Now clear the cache. _menu_clear_page_cache(); } return $item['mlid']; @@ -2436,21 +2445,11 @@ function menu_link_maintain($module, $op return menu_link_save($menu_link); break; case 'update': - db_update('menu_links') - ->fields(array('link_title' => $link_title)) - ->condition('link_path', $link_path) - ->condition('customized', 0) - ->condition('module', $module) - ->execute(); - $result = db_select('menu_links') - ->fields('menu_links', array('menu_name')) - ->condition('link_path', $link_path) - ->condition('customized', 0) - ->condition('module', $module) - ->groupBy('menu_name') - ->execute()->fetchCol(); - foreach ($result as $menu_name) { - menu_cache_clear($menu_name); + $result = db_query("SELECT * FROM {menu_links} WHERE link_path = :link_path AND module = :module AND customized = 0", array(':link_path' => $link_path, ':module' => $module))->fetchAll(PDO::FETCH_ASSOC); + foreach ($result as $item) { + $item['link_title'] = $link_title; + $item['options'] = unserialize($item['options']); + menu_link_save($item); } break; case 'delete': Index: modules/menu/menu.api.php =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.api.php,v retrieving revision 1.9 diff -u -p -r1.9 menu.api.php --- modules/menu/menu.api.php 11 Jul 2009 13:56:21 -0000 1.9 +++ modules/menu/menu.api.php 23 Aug 2009 20:22:31 -0000 @@ -147,6 +147,78 @@ function hook_translated_menu_link_alter } } + /** + * Inform modules that a menu link has been created. + * + * This hook is used to notify module that menu items have been + * created. Contributed modules may use the information to perform + * actions based on the information entered into the menu system. + * + * @param $item + * The $item record saved into the {menu_links} table. + * @return + * None. + * + * @see hook_menu_item_update() + * @see hook_menu_item_delete() + */ +function hook_menu_item_insert($item) { + // In our sample case, we track menu items as editing sections + // of the site. These are stored in our table as 'disabled' items. + $record['mlid'] = $item['mlid']; + $record['menu_name'] = $item['menu_name']; + $record['status'] = 0; + drupal_write_record('menu_example', $record); +} + +/** + * Inform modules that a menu link has been updated. + * + * This hook is used to notify module that menu items have been + * updated. Contributed modules may use the information to perform + * actions based on the information entered into the menu system. + * + * @param $item + * The $item record saved into the {menu_links} table. + * @return + * None. + * + * @see hook_menu_item_insert() + * @see hook_menu_item_delete() + */ +function hook_menu_item_update($item) { + // If the parent menu has changed, update our record. + $menu_name = db_result(db_query("SELECT mlid, menu_name, status FROM {menu_example} WHERE mlid = :mlid", array(':mlid' => $item['mlid']))); + if ($menu_name != $item['menu_name']) { + db_update('menu_example') + ->fields(array('menu_name' => $item['menu_name'])) + ->condition('mlid', $item['mlid']) + ->execute(); + } +} + +/** + * Inform modules that a menu link has been deleted. + * + * This hook is used to notify module that menu items have been + * deleted. Contributed modules may use the information to perform + * actions based on the information entered into the menu system. + * + * @param $item + * The $item record saved into the {menu_links} table. + * @return + * None. + * + * @see hook_menu_item_insert() + * @see hook_menu_item_update() + */ +function hook_menu_item_delete($item) { + // Delete the record from our table. + db_delete('menu_example') + ->condition('mlid', $item['mlid']) + ->execute(); +} + /** * @} End of "addtogroup hooks". */ Index: modules/simpletest/tests/menu.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/menu.test,v retrieving revision 1.13 diff -u -p -r1.13 menu.test --- modules/simpletest/tests/menu.test 14 Jul 2009 20:53:16 -0000 1.13 +++ modules/simpletest/tests/menu.test 23 Aug 2009 20:22:49 -0000 @@ -125,6 +125,21 @@ class MenuIncTestCase extends DrupalWebT $this->assertEqual($compare_item, $item, t('Modified menu item is equal to newly retrieved menu item.'), 'menu'); } + /** + * Test menu maintainance hooks. + */ + function testMenuItemHooks() { + // Create an item. + menu_link_maintain('menu_test', 'insert', 'menu_test_maintain/4', 'Menu link #4'); + $this->assertEqual(menu_test_static_variable(), 'insert', t('hook_menu_item_insert() fired correctly')); + // Update the item. + menu_link_maintain('menu_test', 'update', 'menu_test_maintain/4', 'Menu link updated'); + $this->assertEqual(menu_test_static_variable(), 'update', t('hook_menu_item_update() fired correctly')); + // Delete the item. + menu_link_maintain('menu_test', 'delete', 'menu_test_maintain/4', ''); + $this->assertEqual(menu_test_static_variable(), 'delete', t('hook_menu_item_delete() fired correctly')); + } + } /** Index: modules/simpletest/tests/menu_test.module =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/menu_test.module,v retrieving revision 1.6 diff -u -p -r1.6 menu_test.module --- modules/simpletest/tests/menu_test.module 14 Jul 2009 20:53:16 -0000 1.6 +++ modules/simpletest/tests/menu_test.module 23 Aug 2009 20:22:49 -0000 @@ -73,3 +73,49 @@ function menu_test_menu_name($new_name = } return $name; } + +/** + * Implement hook_menu_item_insert(). + * + * @return + * A random string. + */ +function menu_test_menu_item_insert($item) { + menu_test_static_variable('insert'); +} + +/** + * Implement hook_menu_item_update(). + * + * @return + * A random string. + */ +function menu_test_menu_item_update($item) { + menu_test_static_variable('update'); +} + +/** + * Implement hook_menu_item_delete(). + * + * @return + * A random string. + */ +function menu_test_menu_item_delete($item) { + menu_test_static_variable('delete'); +} + +/** + * Static function for testing hook results. + * + * @param $value + * The value to set or NULL to return the current value. + * @return + * A text string for comparison to test assertions. + */ +function menu_test_static_variable($value = NULL) { + static $variable; + if (!empty($value)) { + $variable = $value; + } + return $variable; +}