menu_item_visibility.module in Menu Item Visibility 7
Same filename and directory in other branches
Alters the menu item form to specify roles who are allowed to view them.
File
menu_item_visibility.moduleView source
<?php
/**
* @file
* Alters the menu item form to specify roles who are allowed to view them.
*/
/**
* Implements hook_menu_link_alter().
*
* In order to have our menu_item_visibility_translated_menu_link_alter()
* function called by _menu_link_translate(), we have to manually set this
* menu link as 'altered'. Unfortunately this alters all menu links and we need
* to figure out a better solution in order to not globally alter all links.
*/
function menu_item_visibility_menu_link_alter(&$item) {
$item['options']['alter'] = TRUE;
// Because menu_link_save() may skip calling hook_menu_link_update(), we need
// to force it to be invoked. See http://drupal.org/node/1013856.
if (!empty($item['mlid'])) {
_menu_item_visibility_menu_link_update($item);
}
}
/**
* Implements hook_translated_menu_link_alter().
*/
function menu_item_visibility_translated_menu_link_alter(&$item, $map) {
global $user;
if (!empty($item['access'])) {
// Menu administrators can see all links within admin paths.
if (user_access('administer menu') && path_is_admin(current_path())) {
return;
}
// @todo Convert this into a proper hook so modules can extend visibility.
$item['visibility'] = menu_item_visibility_load($item['mlid']);
if (!empty($item['visibility']['roles']) && !array_intersect($item['visibility']['roles'], array_keys($user->roles))) {
$item['access'] = FALSE;
}
}
}
/**
* Implements hook_module_implements_alter().
*/
function menu_item_visibility_module_implements_alter(&$implementations, $hook) {
if ($hook == 'translated_menu_link_alter') {
// Move menu_item_visibility_translated_menu_link_alter() to the end of the
// list. This is mainly to deal with menu_token resetting the menu item
// access back to what is returned by menu_get_item().
$group = $implementations['menu_item_visibility'];
unset($implementations['menu_item_visibility']);
$implementations['menu_item_visibility'] = $group;
}
}
/**
* Load all visibility data for a menu link.
*/
function menu_item_visibility_load($mlid, $reset = FALSE) {
// Use the advanced drupal_static() pattern, since this is called very often.
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['visibilities'] =& drupal_static(__FUNCTION__);
}
$visibilities =& $drupal_static_fast['visibilities'];
// If we haven't stored them all in the static build them from the database.
if (!isset($visibilities) || $reset) {
// Select all menu link ids and their role ids.
$result = db_select('menu_links_visibility_role', 'r')
->fields('r', array(
'mlid',
'rid',
))
->execute()
->fetchAll(PDO::FETCH_ASSOC);
$visibilities = array();
foreach ($result as $record) {
$visibilities[$record['mlid']][] = $record['rid'];
}
}
$visibility['roles'] = !empty($visibilities[$mlid]) ? $visibilities[$mlid] : array();
if (!empty($mlid)) {
drupal_alter('menu_item_visibility_load', $visibility, $mlid);
}
return $visibility;
}
/**
* Implements hook_menu_link_insert().
*/
function menu_item_visibility_menu_link_insert($link) {
if (!empty($link['roles']) && ($roles = array_filter($link['roles']))) {
$query = db_insert('menu_links_visibility_role');
$query
->fields(array(
'mlid',
'rid',
));
foreach ($roles as $rid) {
$query
->values(array(
'mlid' => $link['mlid'],
'rid' => $rid,
));
}
$query
->execute();
}
}
/**
* Implements hook_menu_link_update().
*
* Disabled as a hook until http://drupal.org/node/1013856 is fixed.
*/
function _menu_item_visibility_menu_link_update($link) {
// http://drupal.org/node/1369480
// Only delete the roles if the $link object contains actual role information
// otherwise role information will be lost when moving menu items.
if (isset($link['roles'])) {
db_delete('menu_links_visibility_role')
->condition('mlid', $link['mlid'])
->execute();
}
menu_item_visibility_menu_link_insert($link);
}
/**
* Implements hook_menu_link_delete().
*/
function menu_item_visibility_menu_link_delete($link) {
db_delete('menu_links_visibility_role')
->condition('mlid', $link['mlid'])
->execute();
}
/**
* Implements hook_user_role_delete().
*/
function menu_item_visibility_user_role_delete($role) {
db_delete('menu_links_visibility_role')
->condition('rid', $role->rid)
->execute();
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function menu_item_visibility_form_menu_edit_item_alter(&$form, &$form_state) {
// Visibility settings.
$form['visibility_title'] = array(
'#type' => 'item',
'#title' => t('Visibility settings'),
);
$form['visibility'] = array(
'#type' => 'vertical_tabs',
'#attached' => array(
'js' => array(
'vertical-tabs' => drupal_get_path('module', 'menu_item_visibility') . '/menu_item_visibility.js',
),
),
);
$visibility = menu_item_visibility_load($form['mlid']['#value'], TRUE);
// Per-role visibility.
$form['visibility']['role'] = array(
'#type' => 'fieldset',
'#title' => t('Roles'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'visibility',
'#weight' => 10,
);
$form['visibility']['role']['roles'] = array(
'#type' => 'checkboxes',
'#title' => t('Show menu link for specific roles'),
'#default_value' => isset($visibility['roles']) ? $visibility['roles'] : array(),
'#options' => array_map('check_plain', user_roles()),
'#description' => t('Show this menu link only for the selected role(s). If you select no roles, the menu link will be visible to all users.'),
);
}
Functions
Name![]() |
Description |
---|---|
menu_item_visibility_form_menu_edit_item_alter | Implements hook_form_FORM_ID_alter(). |
menu_item_visibility_load | Load all visibility data for a menu link. |
menu_item_visibility_menu_link_alter | Implements hook_menu_link_alter(). |
menu_item_visibility_menu_link_delete | Implements hook_menu_link_delete(). |
menu_item_visibility_menu_link_insert | Implements hook_menu_link_insert(). |
menu_item_visibility_module_implements_alter | Implements hook_module_implements_alter(). |
menu_item_visibility_translated_menu_link_alter | Implements hook_translated_menu_link_alter(). |
menu_item_visibility_user_role_delete | Implements hook_user_role_delete(). |
_menu_item_visibility_menu_link_update | Implements hook_menu_link_update(). |