diff --git a/includes/menu.inc b/includes/menu.inc index 060c354c95b9619a300c939b6584e379019943de..ad6090b25287224b66bc6c5e62dd64e0a187075b 100644 --- a/includes/menu.inc +++ b/includes/menu.inc @@ -2140,6 +2140,9 @@ function _menu_delete_item($item, $force = FALSE) { } db_delete('menu_links')->condition('mlid', $item['mlid'])->execute(); + // Notify modules we have deleted the item. + module_invoke_all('menu_link_delete', $item); + // Update the has_children status of the parent. _menu_update_parental_status($item); menu_cache_clear($item['menu_name']); @@ -2334,7 +2337,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_link_insert'; + if ($existing_item) { + $hook = 'menu_link_update'; + } + module_invoke_all($hook, $item); + // Now clear the cache. _menu_clear_page_cache(); } return $item['mlid']; @@ -2437,21 +2446,11 @@ function menu_link_maintain($module, $op, $link_path, $link_title) { 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 $link) { + $link['link_title'] = $link_title; + $link['options'] = unserialize($link['options']); + menu_link_save($link); } break; case 'delete': diff --git a/modules/menu/menu.api.php b/modules/menu/menu.api.php index bf37caae3071a37767ac62be2f1ff64a29cb7189..99fcb8e209dac6c7de9850621257a8f00aca3e6d 100644 --- a/modules/menu/menu.api.php +++ b/modules/menu/menu.api.php @@ -147,6 +147,78 @@ function hook_translated_menu_link_alter(&$item, $map) { } } + /** + * 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 $link + * The $link record saved into the {menu_links} table. + * @return + * None. + * + * @see hook_menu_link_update() + * @see hook_menu_link_delete() + */ +function hook_menu_link_insert($link) { + // 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'] = $link['mlid']; + $record['menu_name'] = $link['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 $link + * The $link record saved into the {menu_links} table. + * @return + * None. + * + * @see hook_menu_link_insert() + * @see hook_menu_link_delete() + */ +function hook_menu_link_update($link) { + // 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' => $link['mlid']))); + if ($menu_name != $link['menu_name']) { + db_update('menu_example') + ->fields(array('menu_name' => $link['menu_name'])) + ->condition('mlid', $link['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 $link + * The $link record saved into the {menu_links} table. + * @return + * None. + * + * @see hook_menu_link_insert() + * @see hook_menu_link_update() + */ +function hook_menu_link_delete($link) { + // Delete the record from our table. + db_delete('menu_example') + ->condition('mlid', $link['mlid']) + ->execute(); +} + /** * @} End of "addtogroup hooks". */ diff --git a/modules/simpletest/tests/menu.test b/modules/simpletest/tests/menu.test index 889d877d3b219fd973c6710c097f7142e733e973..26443f74e08e588a3530608b965eade6cd0ad099 100644 --- a/modules/simpletest/tests/menu.test +++ b/modules/simpletest/tests/menu.test @@ -132,6 +132,21 @@ class MenuIncTestCase extends DrupalWebTestCase { $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_link_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_link_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_link_delete() fired correctly')); + } + } /** diff --git a/modules/simpletest/tests/menu_test.module b/modules/simpletest/tests/menu_test.module index 0428fd76352c4622446a9ec3d35dc16f96eb74e1..15ecea71a1d11cac2a43473f4a365eaf8812e66c 100644 --- a/modules/simpletest/tests/menu_test.module +++ b/modules/simpletest/tests/menu_test.module @@ -73,3 +73,49 @@ function menu_test_menu_name($new_name = '') { } return $name; } + +/** + * Implement hook_menu_link_insert(). + * + * @return + * A random string. + */ +function menu_test_menu_link_insert($item) { + menu_test_static_variable('insert'); +} + +/** + * Implement hook_menu_link_update(). + * + * @return + * A random string. + */ +function menu_test_menu_link_update($item) { + menu_test_static_variable('update'); +} + +/** + * Implement hook_menu_link_delete(). + * + * @return + * A random string. + */ +function menu_test_menu_link_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; +}