Drupal  Menu System By: Anirudha Prabhune Mail: [email_address]
Menu  System The Menu System has three primary responsibilities:  callback mapping   access control menu customization
Callback  Mapping When a request is made to Drupal by a browser, a URL is given to Drupal.  From this information, Drupal must figure out what code to run and how to handle the request. This is commonly known as  dispatching .
Mapping URLs  to Functions 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 . A  callback   in this context is simply the name of a PHP function that will be run when the browser requests a certain path.
Mapping URLs  to Functions Drupal goes through the following steps when a request comes in: 1. If the path is an alias to a real path, Drupal finds the real path and uses it instead.  2. Executes hook_menu() so that all modules can provide their callbacks. 3. Creates a map from paths (such as node/add) to callbacks (PHP functions such as node_page()). Cont..
Mapping URLs  to Functions 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). 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. 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.
Process  Representation Menu   Array
A Sample   Module A module named new_menu.module that places a menu item in Drupal’s navigation menu is coded here. The Drupal path new_menu is mapped to the PHP function new_menu_hello().
A Demo  Menu function new_menu_menu($may_cache)  { $items = array(); if ($may_cache)   { $items[] = array( 'title' => t('My Menu'), 'path' => 'admin/settings/new_menu', 'callback' => 'new_menu_hello', 'callback arguments' => array(t('Menu!'), t('Nested Menu!')), 'access' => TRUE );
A Demo  Menu $items[] = array( 'title' => t('Done'), 'path' => 'admin/settings/new_menu/MyMenu', 'callback' => 'new_menu_hello', 'callback arguments' => array(t('Menu!'), t('Nested Menu!')), 'access' => TRUE ); } return $items; }
A Demo  Menu function new_menu_hello($first,$second,$name = NULL) { drupal_set_message(t('First comes %first', array('%first' => $first))); drupal_set_message(t('Second comes %second', array('%second' =>  $second))); if (!isset($name))  { $name = t('good looking!'); } return t('Hello @name!', array('@name' => $name)); }
Visual  Demo Nested Menu
Access   Control 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().  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.
Access   Control function new_menu_perm()  { return array('Door Opened!!'); } Replace  ‘ access’ => TRUE   WITH ‘ access’ => user_access(‘Door Opened!!’) 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. Note: Do not forget to apply the Access Control from Administer Panel  Manually .
Access   Control 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.
Access   Control Access Settings and Resulting User Access Table Parent  Child  User Access FALSE  FALSE Denied TRUE  FALSE  Denied FALSE  TRUE  Allowed TRUE  TRUE  Allowed FALSE  Undefined  Denied TRUE  Undefined  Allowed
Kinds of  Menu 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. The Following Table lists the menu item type FLAGS :
Kinds of  Menu Binary  Hexadecimal    Decimal     Constant 000000000001   0x0001  1  MENU_IS_ROOT 000000000010    0x0002    2   MENU_VISIBLE_IN_TREE 000000000100   0x0004  4  MENU_VISIBLE_IN_BREADCRUMB 000000001000    0x0008 8  MENU_VISIBLE_IF_HAS_CHILDREN 000000010000    0x0010  16  MENU_MODIFIABLE_BY_ADMIN 000000100000   0x0020  32  MENU_MODIFIED_BY_ADMIN 000001000000    0x0040  64  MENU_CREATED_BY_ADMIN 000010000000    0x0080  128  MENU_IS_LOCAL_TASK 000100000000    0x0100  256  MENU_EXPANDED 001000000000   0x0200  512  MENU_LINKS_TO_PARENT
Kinds of  Menu 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?   Binary    Constant 000000000010  MENU_VISIBLE_IN_TREE 000000000100  MENU_VISIBLE_IN_BREADCRUMB 000000010000  MENU_MODIFIABLE_BY_ADMIN 000000010110  MENU_NORMAL_ITEM
Common   Tasks Assigning Callbacks Without Adding a Link to the Menu 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 : $items[] = array( ‘ path' => 'rss.xml', 'title' => t('RSS feed'), 'callback' => 'node_feed', 'access' => user_access('access content'), 'type' => MENU_CALLBACK );
Common   Tasks Programmatically Modifying Existing Menus: 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.
Common   Tasks Wrapping Calls to Menu Items: 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
Common   Tasks function mymodule_menu($may_cache) { $items = array(); if (!$may_cache && module_exist('devel')) { // Make sure devel.module is enabled. $items[] = array( 'path' => 'devel/cache/clear', // Same path that devel.module uses. 'title' => t('Wrap cache clear'), 'callback' => 'mymodule_clear_cache', 'type' => MENU_CALLBACK, 'access' => user_access('access devel information') // Same as devel.module. ); } } function mymodule_clear_cache() { drupal_set_message('We got called first!'); // Wrap the devel function normally called. devel_cache_clear(); }
Common   Tasks 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: We got called first! Cache cleared. Note :  This is a useful technique for when you want to modify Drupal’s default behavior without modifying any underlying code.
Common   Tasks Deleting Existing Menus: 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: $items[] = array( 'path' => 'node/add', 'title' => t('This should not show up'), 'callback' => 'drupal_not_found', ‘ type' => MENU_CALLBACK );
Common   Tasks Adding to Existing Menus: 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:
Common   Tasks $items[] = array( 'path' => 'admin/user/eradicate', 'title' => t('Eradicate all users'), 'callback' => 'mymodule_eradicate_users', 'type' => MENU_LOCAL_TASK, 'access' => user_access('eradicate users') ); 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: 'type' => MENU_NORMAL_ITEM | MENU_LOCAL_TASK and the menu item will have the attributes of both menu item types.
THANK   YOU

Drupal Menu System

  • 1.
    Drupal MenuSystem By: Anirudha Prabhune Mail: [email_address]
  • 2.
    Menu SystemThe Menu System has three primary responsibilities: callback mapping access control menu customization
  • 3.
    Callback MappingWhen a request is made to Drupal by a browser, a URL is given to Drupal. From this information, Drupal must figure out what code to run and how to handle the request. This is commonly known as dispatching .
  • 4.
    Mapping URLs to Functions 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 . A callback in this context is simply the name of a PHP function that will be run when the browser requests a certain path.
  • 5.
    Mapping URLs to Functions Drupal goes through the following steps when a request comes in: 1. If the path is an alias to a real path, Drupal finds the real path and uses it instead. 2. Executes hook_menu() so that all modules can provide their callbacks. 3. Creates a map from paths (such as node/add) to callbacks (PHP functions such as node_page()). Cont..
  • 6.
    Mapping URLs to Functions 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). 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. 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.
  • 7.
  • 8.
    A Sample Module A module named new_menu.module that places a menu item in Drupal’s navigation menu is coded here. The Drupal path new_menu is mapped to the PHP function new_menu_hello().
  • 9.
    A Demo Menu function new_menu_menu($may_cache) { $items = array(); if ($may_cache) { $items[] = array( 'title' => t('My Menu'), 'path' => 'admin/settings/new_menu', 'callback' => 'new_menu_hello', 'callback arguments' => array(t('Menu!'), t('Nested Menu!')), 'access' => TRUE );
  • 10.
    A Demo Menu $items[] = array( 'title' => t('Done'), 'path' => 'admin/settings/new_menu/MyMenu', 'callback' => 'new_menu_hello', 'callback arguments' => array(t('Menu!'), t('Nested Menu!')), 'access' => TRUE ); } return $items; }
  • 11.
    A Demo Menu function new_menu_hello($first,$second,$name = NULL) { drupal_set_message(t('First comes %first', array('%first' => $first))); drupal_set_message(t('Second comes %second', array('%second' => $second))); if (!isset($name)) { $name = t('good looking!'); } return t('Hello @name!', array('@name' => $name)); }
  • 12.
    Visual DemoNested Menu
  • 13.
    Access Control 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(). 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.
  • 14.
    Access Control function new_menu_perm() { return array('Door Opened!!'); } Replace ‘ access’ => TRUE WITH ‘ access’ => user_access(‘Door Opened!!’) 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. Note: Do not forget to apply the Access Control from Administer Panel Manually .
  • 15.
    Access Control 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.
  • 16.
    Access Control Access Settings and Resulting User Access Table Parent Child User Access FALSE FALSE Denied TRUE FALSE Denied FALSE TRUE Allowed TRUE TRUE Allowed FALSE Undefined Denied TRUE Undefined Allowed
  • 17.
    Kinds of Menu 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. The Following Table lists the menu item type FLAGS :
  • 18.
    Kinds of Menu Binary Hexadecimal Decimal Constant 000000000001 0x0001 1 MENU_IS_ROOT 000000000010 0x0002 2 MENU_VISIBLE_IN_TREE 000000000100 0x0004 4 MENU_VISIBLE_IN_BREADCRUMB 000000001000 0x0008 8 MENU_VISIBLE_IF_HAS_CHILDREN 000000010000 0x0010 16 MENU_MODIFIABLE_BY_ADMIN 000000100000 0x0020 32 MENU_MODIFIED_BY_ADMIN 000001000000 0x0040 64 MENU_CREATED_BY_ADMIN 000010000000 0x0080 128 MENU_IS_LOCAL_TASK 000100000000 0x0100 256 MENU_EXPANDED 001000000000 0x0200 512 MENU_LINKS_TO_PARENT
  • 19.
    Kinds of Menu 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? Binary Constant 000000000010 MENU_VISIBLE_IN_TREE 000000000100 MENU_VISIBLE_IN_BREADCRUMB 000000010000 MENU_MODIFIABLE_BY_ADMIN 000000010110 MENU_NORMAL_ITEM
  • 20.
    Common Tasks Assigning Callbacks Without Adding a Link to the Menu 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 : $items[] = array( ‘ path' => 'rss.xml', 'title' => t('RSS feed'), 'callback' => 'node_feed', 'access' => user_access('access content'), 'type' => MENU_CALLBACK );
  • 21.
    Common Tasks Programmatically Modifying Existing Menus: 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.
  • 22.
    Common Tasks Wrapping Calls to Menu Items: 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
  • 23.
    Common Tasks function mymodule_menu($may_cache) { $items = array(); if (!$may_cache && module_exist('devel')) { // Make sure devel.module is enabled. $items[] = array( 'path' => 'devel/cache/clear', // Same path that devel.module uses. 'title' => t('Wrap cache clear'), 'callback' => 'mymodule_clear_cache', 'type' => MENU_CALLBACK, 'access' => user_access('access devel information') // Same as devel.module. ); } } function mymodule_clear_cache() { drupal_set_message('We got called first!'); // Wrap the devel function normally called. devel_cache_clear(); }
  • 24.
    Common Tasks 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: We got called first! Cache cleared. Note : This is a useful technique for when you want to modify Drupal’s default behavior without modifying any underlying code.
  • 25.
    Common Tasks Deleting Existing Menus: 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: $items[] = array( 'path' => 'node/add', 'title' => t('This should not show up'), 'callback' => 'drupal_not_found', ‘ type' => MENU_CALLBACK );
  • 26.
    Common Tasks Adding to Existing Menus: 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:
  • 27.
    Common Tasks $items[] = array( 'path' => 'admin/user/eradicate', 'title' => t('Eradicate all users'), 'callback' => 'mymodule_eradicate_users', 'type' => MENU_LOCAL_TASK, 'access' => user_access('eradicate users') ); 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: 'type' => MENU_NORMAL_ITEM | MENU_LOCAL_TASK and the menu item will have the attributes of both menu item types.
  • 28.
    THANK YOU