uid == 1 || empty($mlid)) { // Admins do not lose access whatever this module would otherwise say // Also, if the menu link identifier is not set, ignore the request return; } $rids = _menu_per_role_get_roles($mlid); // NULL means that you can try some more and FALSE you're definitively out return !empty($rids) && count(array_intersect($rids, array_keys($user->roles))) == 0 ? FALSE : NULL; } /* * Implementation of hook_form_alter(). */ function menu_per_role_form_alter(&$form, $form_state, $form_id) { if ($form_id == 'menu_edit_item') { $default_value = $form['menu']['mlid']['#value'] ? _menu_per_role_get_roles($form['menu']['mlid']['#value']) : array(); $form['menu_per_role'] = array( '#type' => 'fieldset', '#title' => t('Restrict access permission'), '#collapsible' => TRUE, '#collapsed' => count($default_value) == 0, '#weight' => 5, '#description' => t('Last check: check to know whether the user has proper permission to see the defined item.'), ); $form['menu_per_role']['roles'] = array( '#type' => 'checkboxes', '#title' => t('Restrict access to only these roles'), '#options' => user_roles(), '#default_value' => $default_value, '#description' => t('Check no role to leave the access permission to the default.'), ); $form['submit']['#weight'] = 10; $form['#submit'][] = '_menu_per_role_form_submit'; } } /* * Internal function to save the data in our table. */ function _menu_per_role_form_submit($form, &$form_state) { if ($form_state['submitted']) { $mlid = $form_state['values']['menu']['mlid']; if ($mlid) { $rids = array(); foreach ($form_state['values']['roles'] as $rid => $checked) { if ($checked) { $rids[] = $rid; } } $rids_str = implode(',', $rids); db_query("UPDATE {menu_per_role} SET rids = '%s' WHERE mlid = %d", $rids_str, $mlid); if (db_affected_rows() == 0) { // if nothing was affected, the row did not exist yet db_query("INSERT INTO {menu_per_role} (mlid, rids) VALUES (%d, '%s')", $mlid, $rids_str); } menu_cache_clear_all(); } else { drupal_set_message(t('The menu link identifier was not defined on Submit in Menu per Role. You are most certainly adding a new menu item. For this feature to work when adding a menu item, you must apply the patch defined in node #326210. That patch is included in this module for that purpose.'), 'error'); } } } /* * When the menu item is being submitted, the core also calls the * hook_menu_link_alter(&$item, $menu); * * By catching that function, we can set the special alter option * that will let our module receive a call whenever the menu is * ready for display but was not yet displayed. At that time we * can mark the access as FALSE. */ function menu_per_role_menu_link_alter(&$item, $menu) { // TODO: The following marks ALL menu items as alterable. // Any time a menu item is saved, it is marked as // such. I have no clue, at this time, of a way to // avoid such nonsense. Hints welcome! $item['options']['alter'] = TRUE; } /* * Before a menu item gets displayed, the core calls the hook: * hook_translated_menu_link_alter(&$item, $map); * (but only if $item['options']['alter'] is TRUE) * * This function is used to alter the access right based on * the role definition of the item. */ function menu_per_role_translated_menu_link_alter(&$item, $map) { // avoid checking the role if the item access is already false if ($item['access'] && _menu_per_role_access($item['mlid']) === FALSE) { $item['access'] = FALSE; } } /* * Gets all roles with access to the specified menu item * No roles mean that access should either be inherited from the parent menu item * or the user does not have access. */ function _menu_per_role_get_roles($mlid) { $result = db_query("SELECT rids FROM {menu_per_role} WHERE mlid = %d", $mlid); if ($result && ($row = db_fetch_object($result)) && $row->rids) { return explode(',', $row->rids); } // not defined, everyone has the right to use it return array(); }