DRUPAL Menu System


Published on

How to make Drupal behavior flexible according to requirements using Access Control, Menu Customization & Callback Mapping.

Published in: Technology, Business
No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

DRUPAL Menu System

  1. 1. Drupal Menu System <ul><ul><ul><li>By: Anirudha Prabhune </li></ul></ul></ul><ul><ul><ul><li>Mail: [email_address] </li></ul></ul></ul>
  2. 2. Menu System <ul><li>The Menu System has three primary responsibilities: </li></ul><ul><li>callback mapping </li></ul><ul><li>access control </li></ul><ul><li>menu customization </li></ul>
  3. 3. Callback Mapping <ul><li>When a request is made to Drupal by a browser, a URL is given to Drupal. </li></ul><ul><li>From this information, Drupal must figure out what code to run and how to handle the request. This is commonly known as dispatching . </li></ul>
  4. 4. Mapping URLs to Functions <ul><li>The general approach taken is as follows: Drupal asks all its modules to provide an array of menu items —that is, a path and some information about that path. One of the pieces of information a module must provide is a callback . </li></ul><ul><li>A callback in this context is simply the name of a PHP function that will be run when the browser requests a certain path. </li></ul>
  5. 5. Mapping URLs to Functions <ul><li>Drupal goes through the following steps when a request comes in: </li></ul><ul><li>1. If the path is an alias to a real path, Drupal finds the real path and uses it instead. </li></ul><ul><li>2. Executes hook_menu() so that all modules can provide their callbacks. </li></ul><ul><li>3. Creates a map from paths (such as node/add) to callbacks (PHP functions such as node_page()). </li></ul><ul><li>Cont.. </li></ul>
  6. 6. Mapping URLs to Functions <ul><li>4. If menu.module is enabled, applies any changes or additions the site administrator has made to the map (such as overriding a menu item’s title). </li></ul><ul><li>5. Uses the map to look up the callback function for the requested URL, and calls it. If any callback arguments were specified, Drupal sends those along. </li></ul><ul><li>6. Returns the function’s result or an “Access denied” message if the user may not access the URL, or a 404 response if the path did not map to any function. </li></ul>
  7. 7. Process Representation Menu Array
  8. 8. A Sample Module <ul><li>A module named new_menu.module that places a menu item in Drupal’s navigation menu is coded here. </li></ul><ul><li>The Drupal path new_menu is mapped to the PHP function new_menu_hello(). </li></ul>
  9. 9. A Demo Menu <ul><li>function new_menu_menu($may_cache) </li></ul><ul><li>{ </li></ul><ul><li>$items = array(); </li></ul><ul><li>if ($may_cache) </li></ul><ul><li> { </li></ul><ul><li>$items[] = array( </li></ul><ul><li>'title' => t('My Menu'), </li></ul><ul><li>'path' => 'admin/settings/new_menu', </li></ul><ul><li>'callback' => 'new_menu_hello', </li></ul><ul><li>'callback arguments' => array(t('Menu!'), t('Nested Menu!')), </li></ul><ul><li>'access' => TRUE </li></ul><ul><li>); </li></ul>
  10. 10. A Demo Menu <ul><li>$items[] = array( </li></ul><ul><li>'title' => t('Done'), </li></ul><ul><li>'path' => 'admin/settings/new_menu/MyMenu', </li></ul><ul><li>'callback' => 'new_menu_hello', </li></ul><ul><li>'callback arguments' => array(t('Menu!'), t('Nested Menu!')), </li></ul><ul><li>'access' => TRUE </li></ul><ul><li>); </li></ul><ul><li>} </li></ul><ul><li>return $items; </li></ul><ul><li>} </li></ul>
  11. 11. A Demo Menu <ul><li>function new_menu_hello($first,$second,$name = NULL) </li></ul><ul><li>{ </li></ul><ul><li>drupal_set_message(t('First comes %first', array('%first' => $first))); </li></ul><ul><li>drupal_set_message(t('Second comes %second', array('%second' => $second))); </li></ul><ul><li>if (!isset($name)) </li></ul><ul><li>{ </li></ul><ul><li>$name = t('good looking!'); </li></ul><ul><li>} </li></ul><ul><li>return t('Hello @name!', array('@name' => $name)); </li></ul><ul><li>} </li></ul>
  12. 12. Visual Demo Nested Menu
  13. 13. Access Control <ul><li>Previously we’ve simply set the access key of the menu item to TRUE , meaning that anyone can access our menu. Usually menu access is controlled by defining permissions inside the module using hook_perm() and testing those permissions using user_access(). </li></ul><ul><li>Let’s define a permission called Door Opened!! ; if a user does not have a role that has been granted this permission , the user will receive an “Access denied” message if he or she tries to access that particular menu. </li></ul>
  14. 14. Access Control <ul><li>function new_menu_perm() </li></ul><ul><li>{ </li></ul><ul><li>return array('Door Opened!!'); </li></ul><ul><li>} </li></ul><ul><li>Replace </li></ul><ul><li>‘ access’ => TRUE WITH </li></ul><ul><li>‘ access’ => user_access(‘Door Opened!!’) </li></ul><ul><li>In this way, the menu system serves as a gatekeeper determining which paths may be accessed and which will be denied based on the user’s role. </li></ul><ul><li>Note: Do not forget to apply the Access Control from Administer Panel Manually . </li></ul>
  15. 15. Access Control <ul><li>When determining access to a menu item, Drupal will look at the access key of the menu item’s full path and use that. If the access key is TRUE, access will be granted even if the parent’s access key is FALSE. If there is no access key assigned to a menu item, its parent’s access key will be used. If the parent does not have an access key, Drupal will recurse all the way up the tree until it finds an access key (the access key for the root of the tree is TRUE). Local tasks are common nested menu items. </li></ul>
  16. 16. Access Control <ul><li>Access Settings and Resulting User Access Table </li></ul><ul><li>Parent Child User Access </li></ul><ul><li>FALSE FALSE Denied </li></ul><ul><li>TRUE FALSE Denied </li></ul><ul><li>FALSE TRUE Allowed </li></ul><ul><li>TRUE TRUE Allowed </li></ul><ul><li>FALSE Undefined Denied </li></ul><ul><li>TRUE Undefined Allowed </li></ul>
  17. 17. Kinds of Menu <ul><li>When you are adding a menu item in the menu hook, one of the possible keys you can use is the type. If you do not define a type, the default type MENU_NORMAL_ITEM will be used. Drupal will treat your menu item differently according to the type you assign. Each menu item type is composed of a series of flags, or attributes. </li></ul><ul><li>The Following Table lists the menu item type FLAGS : </li></ul>
  18. 18. Kinds of Menu <ul><li>Binary Hexadecimal Decimal Constant </li></ul><ul><li>000000000001 0x0001 1 MENU_IS_ROOT </li></ul><ul><li>000000000010 0x0002 2 MENU_VISIBLE_IN_TREE </li></ul><ul><li>000000000100 0x0004 4 MENU_VISIBLE_IN_BREADCRUMB </li></ul><ul><li>000000001000 0x0008 8 MENU_VISIBLE_IF_HAS_CHILDREN </li></ul><ul><li>000000010000 0x0010 16 MENU_MODIFIABLE_BY_ADMIN </li></ul><ul><li>000000100000 0x0020 32 MENU_MODIFIED_BY_ADMIN </li></ul><ul><li>000001000000 0x0040 64 MENU_CREATED_BY_ADMIN </li></ul><ul><li>000010000000 0x0080 128 MENU_IS_LOCAL_TASK </li></ul><ul><li>000100000000 0x0100 256 MENU_EXPANDED </li></ul><ul><li>001000000000 0x0200 512 MENU_LINKS_TO_PARENT </li></ul>
  19. 19. Kinds of Menu <ul><li>For example, the constant MENU_NORMAL_ITEM has the flags MENU_VISIBLE_IN_TREE, MENU_VISIBLE_IN_BREADCRUMB, and MENU_MODIFIABLE_BY_ADMIN, as shown in Table . See how the separate flags can be expressed in a single constant? </li></ul><ul><li> Binary Constant </li></ul><ul><li>000000000010 MENU_VISIBLE_IN_TREE </li></ul><ul><li>000000000100 MENU_VISIBLE_IN_BREADCRUMB </li></ul><ul><li>000000010000 MENU_MODIFIABLE_BY_ADMIN </li></ul><ul><li>000000010110 MENU_NORMAL_ITEM </li></ul>
  20. 20. Common Tasks <ul><li>Assigning Callbacks Without Adding a Link to the Menu </li></ul><ul><li>Often we want to map a URL to a function without creating a visible menu item. We can do this by assigning the MENU_CALLBACK type to your menu item, as in this example from node.module : </li></ul><ul><li>$items[] = array( </li></ul><ul><li>‘ path' => 'rss.xml', </li></ul><ul><li>'title' => t('RSS feed'), </li></ul><ul><li>'callback' => 'node_feed', </li></ul><ul><li>'access' => user_access('access content'), </li></ul><ul><li>'type' => MENU_CALLBACK </li></ul><ul><li>); </li></ul>
  21. 21. Common Tasks <ul><li>Programmatically Modifying Existing Menus: </li></ul><ul><li>When we implement the menu hook in our module, there’s nothing to prevent us from adding entries to other modules’ paths, or even from overriding them. Typically this is done using the handy web interface provided by menu.module, which ships as part of Drupal, but we have reasons to do this programmatically. </li></ul>
  22. 22. Common Tasks <ul><li>Wrapping Calls to Menu Items: </li></ul><ul><li>For example, devel.module has a menu item that clears Drupal’s cache tables. Let’s wrap that function so our function gets called first. First, we override devel.module’s menu item by specifying one of our own with the same path inside our menu hook </li></ul>
  23. 23. Common Tasks <ul><li>function mymodule_menu($may_cache) { </li></ul><ul><li>$items = array(); </li></ul><ul><li>if (!$may_cache && module_exist('devel')) { // Make sure devel.module is enabled. </li></ul><ul><li>$items[] = array( </li></ul><ul><li>'path' => 'devel/cache/clear', // Same path that devel.module uses. </li></ul><ul><li>'title' => t('Wrap cache clear'), </li></ul><ul><li>'callback' => 'mymodule_clear_cache', </li></ul><ul><li>'type' => MENU_CALLBACK, </li></ul><ul><li>'access' => user_access('access devel information') // Same as devel.module. </li></ul><ul><li>); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>function mymodule_clear_cache() { </li></ul><ul><li>drupal_set_message('We got called first!'); </li></ul><ul><li>// Wrap the devel function normally called. </li></ul><ul><li>devel_cache_clear(); </li></ul><ul><li>} </li></ul>
  24. 24. Common Tasks <ul><li>Now when we go to the menu ../?q=devel/cache/clear , our module will be called first, and it will call the function that would have originally been called. Here’s the result: </li></ul><ul><li>We got called first! </li></ul><ul><li>Cache cleared. </li></ul><ul><li>Note : This is a useful technique for when you want to modify Drupal’s default behavior without modifying any underlying code. </li></ul>
  25. 25. Common Tasks <ul><li>Deleting Existing Menus: </li></ul><ul><li>Using the same approach presented in the section “Wrapping Calls to Menu Items,” we can delete existing menu items by overriding their paths. Suppose you want to remove the “create content” menu item and the ability to add content, for some reason: </li></ul><ul><li>$items[] = array( </li></ul><ul><li>'path' => 'node/add', </li></ul><ul><li>'title' => t('This should not show up'), </li></ul><ul><li>'callback' => 'drupal_not_found', </li></ul><ul><li>‘ type' => MENU_CALLBACK </li></ul><ul><li>); </li></ul>
  26. 26. Common Tasks <ul><li>Adding to Existing Menus: </li></ul><ul><li>We can add to existing menus by inserting our menu item with a clever path. For example, suppose we want to add a tab to the user administration interface to delete all users. By examining the menu hook in user.module, we determine that admin/user is the path we want to use as our base path. Here’s the menu item we return from eradicateusers.module: </li></ul>
  27. 27. Common Tasks <ul><li>$items[] = array( </li></ul><ul><li>'path' => 'admin/user/eradicate', </li></ul><ul><li>'title' => t('Eradicate all users'), </li></ul><ul><li>'callback' => 'mymodule_eradicate_users', </li></ul><ul><li>'type' => MENU_LOCAL_TASK, </li></ul><ul><li>'access' => user_access('eradicate users') </li></ul><ul><li>); </li></ul><ul><li>This adds the menu item as a local task. If we want the menu item to show up in the administrative menu block, we have to make the type a MENU_NORMAL_ITEM instead of a MENU_LOCAL_TASK. And if we want it to show up in both places, use the following: </li></ul><ul><li>'type' => MENU_NORMAL_ITEM | MENU_LOCAL_TASK </li></ul><ul><li>and the menu item will have the attributes of both menu item types. </li></ul>
  28. 28. <ul><li>THANK YOU </li></ul>