uid == 1 || empty($mlid) || user_access('administer menu_per_role')) {
// Admins do not lose access whatever this module would otherwise say
// Also, if the menu link identifier is not set, ignore the request
return NULL;
}
// check whether this role has visibility access (must be present)
$rids = _menu_per_role_get_roles($mlid, 0);
if (!empty($rids) && count(array_intersect($rids, array_keys($user->roles))) == 0) {
// not permitted by the rids...
return FALSE;
}
// check whether this role has visibility access (must not be present)
$hrids = _menu_per_role_get_roles($mlid, 1);
if (!empty($hrids) && count(array_intersect($hrids, array_keys($user->roles))) > 0) {
// not permitted by the hrids...
return FALSE;
}
// this module is not preventing user from seeing this menu entry
return NULL;
}
/*
* Implementation of hook_form_alter().
*/
function menu_per_role_form_alter(&$form, $form_state, $form_id) {
if (!user_access('administer menu_per_role')) {
return;
}
if ($form_id == 'menu_edit_item') {
$f = &$form;
$form['submit']['#weight'] = 10;
}
if (isset($form['#node']) && $form['#node']->type .'_node_form' == $form_id && isset($form['menu'])) {
$f = &$form['menu'];
}
if (isset($f)) {
$default_value_roles = $form['menu']['mlid']['#value']
? _menu_per_role_get_roles($form['menu']['mlid']['#value'], 0)
: array();
$default_value_hide_from_roles = $form['menu']['mlid']['#value']
? _menu_per_role_get_roles($form['menu']['mlid']['#value'], 1)
: array();
$f['menu_per_role'] = array(
'#type' => 'fieldset',
'#title' => t('Restrict item visibility'),
'#collapsible' => TRUE,
'#collapsed' => (count($default_value_roles) + count($default_value_hide_from_roles)) == 0,
'#weight' => 5,
'#description' => t('Check to know whether the user has proper visibility permissions to see this menu item. Note that both checks are always performed.'),
);
$f['menu_per_role']['menu_per_role_roles'] = array(
'#type' => 'checkboxes',
'#title' => t('Show menu item only to selected roles'),
'#options' => user_roles(),
'#default_value' => $default_value_roles,
'#description' => t('Check no role to leave the access permission to the default. A user who is not part of at least one of the selected roles will not see this menu item.'),
);
$f['menu_per_role']['menu_per_role_hide_from_roles'] = array(
'#type' => 'checkboxes',
'#title' => t('Hide menu item from selected roles'),
'#options' => user_roles(),
'#default_value' => $default_value_hide_from_roles,
'#description' => t('Check no role to leave the access permission to the default. A user who is part of any one of these roles will not see this menu item.'),
);
$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) {
global $db_type;
if ($form_state['submitted']) {
$mlid = $form_state['values']['menu']['mlid'];
if ($mlid) {
// hide but to those roles
$rids = array();
$roles = isset($form_state['values']['menu_per_role_roles']) ?
$form_state['values']['menu_per_role_roles']
: $form_state['values']['menu']['menu_per_role']['menu_per_role_roles'];
foreach ($roles as $rid => $checked) {
if ($checked) {
$rids[] = $rid;
}
}
$rids_str = implode(',', $rids);
// show but to those roles
$hrids = array();
$roles = isset($form_state['values']['menu_per_role_hide_from_roles']) ?
$form_state['values']['menu_per_role_hide_from_roles']
: $form_state['values']['menu']['menu_per_role']['menu_per_role_hide_from_roles'];
foreach ($roles as $rid => $checked) {
if ($checked) {
$hrids[] = $rid;
}
}
$hrids_str = implode(',', $hrids);
// save in our table
//db_lock_table('menu_per_role');
if ($rids_str || $hrids_str) {
db_query("UPDATE {menu_per_role} SET rids = '%s', hrids = '%s' WHERE mlid = %d", $rids_str, $hrids_str, $mlid);
if (db_affected_rows() == 0) {
// if nothing was affected, the row did not exist yet
// (although with MySQL this may fail because db_affected_rows() may only return
// rows that have been changed instead of the # of rows that match the WHERE clause.)
if ($db_type != 'pgsql') {
$insert = !db_result(db_query("SELECT 1 FROM {menu_per_role} WHERE mlid = %d", $mlid));
}
else {
$insert = TRUE;
}
if ($insert) {
db_query("INSERT INTO {menu_per_role} (mlid, rids, hrids) VALUES (%d, '%s', '%s')", $mlid, $rids_str, $hrids_str);
}
}
}
else {
// we don't need to save it when empty, instead, remove that completely
db_query("DELETE FROM {menu_per_role} WHERE mlid = %d", $mlid);
}
//db_unlock_tables();
// reset the menus
menu_cache_clear_all();
}
else if (isset($form_state['values']['menu_per_role_roles'])) {
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 is granted by this module.
*
* $show set to 0 for show to roles, 1 for hide from roles
*/
function _menu_per_role_get_roles($mlid, $show) {
static $menu_per_role;
if (!isset($menu_per_role)) {
// read all the data ONCE, it is likely very small
$menu_per_role = array();
$result = db_query("SELECT * FROM {menu_per_role}");
while ($row = db_fetch_object($result)) {
if ($row->rids || $row->hrids) {
$menu_per_role[$row->mlid][0] = explode(',', $row->rids);
$menu_per_role[$row->mlid][1] = explode(',', $row->hrids);
}
}
}
if (isset($menu_per_role[$mlid])) {
return $menu_per_role[$mlid][$show];
}
// not defined, everyone has the right to use it
return array();
}
// vim: ts=2 sw=2 et syntax=php