How do I limit access to menu by role in Drupal?
Asked Answered
F

7

5

I'm building a Drupal site, and have added two custom menus to give two different groups of management links (some people will see one menu or the other, some will see both, and anonymous/low-level users will see neither).

The problem is, at the moment, all users can see the menus (but the menu items are not visible).

I'm trying to create a simple permissions module - and have created the administration forms which specify which menus are viewable by which role.

But I can't find a hook which lets me override the visibility of a particular menu - only the items.

So, how do I limit access to menu by role in Drupal now that I have a list of permissions in the database?

--

I have looked at Menu per Role and Menu Access. Unfortunately, these work at the item level and not on the menus directly.

Fasces answered 21/2, 2011 at 3:26 Comment(0)
F
0

I've come up with a solution - instead of using the auto-generated menu blocks for display, I've created a single block and put the following code in my module:

function amh_menu_block($op = 'list', $delta = 0, $edit = array())
{
    if ($op == 'list') {
        $blocks[0] = array(
            'info' => t('AMH Menu block'),
            'weight' => 0,
            'status' => 1,
            'region' => 'left',
        );

        return $blocks;
    } elseif ($op == 'view') {
        switch($delta) {
            case 0:
                $block = array(
                    'subject' => '',
                    'content' => _amh_menu_display(),
                );

                break;
        }

        return $block;
    }
}

function _amh_menu_display()
{
    global $user;

    $content = '';

    if ($user->uid != 0) {
        $result = db_query('SELECT * FROM {amh_menu_permission} p LEFT JOIN {menu_custom} m ON p.menu_name = m.menu_name LEFT JOIN {users_roles} u ON p.rid = u.rid WHERE u.uid = %d OR p.rid = 2', $user->uid);
    } else {
        $result = db_query('SELECT * FROM {amh_menu_permission} p LEFT JOIN {menu_custom} m ON p.menu_name = m.menu_name WHERE p.rid = 1');
    }
    $menus = array();
    while ($m = db_fetch_object($result)) {
        $menu = menu_tree($m->menu_name);

        if ($menu) {
            $content .= "\r\n<h2>" . $m->title . "<h2>\r\n";
            $content .= theme_menu_tree($menu);
        }
    }

    return $content;
}

This seems to work fine.

Fasces answered 21/2, 2011 at 5:32 Comment(0)
R
6

Each menu is in a block, and blocks can be set to be visible for given user group (access level). On drupal admin site: Structure/Blocks

Refit answered 1/2, 2012 at 10:27 Comment(1)
Perfect. This helped me out a ton. Additionally what I did was create a similar menu for the other roles ("anonymous user", "authenticated user", and "administrator") so each role would have a menu.Magnus
S
2

Menu Per Role module?

http://drupal.org/project/menu_per_role

Stanwood answered 21/2, 2011 at 3:57 Comment(1)
I'd already looked at that - but despite the name of the module, it actually only works on items and not menus.Fasces
C
1

As long you use a block as a menu you can use the access by role for block setting, provided by core.

Cornwell answered 28/2, 2011 at 12:18 Comment(0)
M
0

For menu listing this function work: menu_get_names();
But it hasn't any permission checks or hooks.
Where did you want to restrict menu list? if at node editing you can alter menu there via hook_form_alter.

Marcelenemarcelia answered 21/2, 2011 at 4:54 Comment(0)
H
0

It's not the most elegant solution, but you can do your access check in the theme.

Heliotype answered 21/2, 2011 at 5:20 Comment(0)
F
0

I've come up with a solution - instead of using the auto-generated menu blocks for display, I've created a single block and put the following code in my module:

function amh_menu_block($op = 'list', $delta = 0, $edit = array())
{
    if ($op == 'list') {
        $blocks[0] = array(
            'info' => t('AMH Menu block'),
            'weight' => 0,
            'status' => 1,
            'region' => 'left',
        );

        return $blocks;
    } elseif ($op == 'view') {
        switch($delta) {
            case 0:
                $block = array(
                    'subject' => '',
                    'content' => _amh_menu_display(),
                );

                break;
        }

        return $block;
    }
}

function _amh_menu_display()
{
    global $user;

    $content = '';

    if ($user->uid != 0) {
        $result = db_query('SELECT * FROM {amh_menu_permission} p LEFT JOIN {menu_custom} m ON p.menu_name = m.menu_name LEFT JOIN {users_roles} u ON p.rid = u.rid WHERE u.uid = %d OR p.rid = 2', $user->uid);
    } else {
        $result = db_query('SELECT * FROM {amh_menu_permission} p LEFT JOIN {menu_custom} m ON p.menu_name = m.menu_name WHERE p.rid = 1');
    }
    $menus = array();
    while ($m = db_fetch_object($result)) {
        $menu = menu_tree($m->menu_name);

        if ($menu) {
            $content .= "\r\n<h2>" . $m->title . "<h2>\r\n";
            $content .= theme_menu_tree($menu);
        }
    }

    return $content;
}

This seems to work fine.

Fasces answered 21/2, 2011 at 5:32 Comment(0)
W
0

The Menu Admin Per Menu module will allow you to restrict edit access to each menu by role. https://www.drupal.org/project/menu_admin_per_menu

Wolfy answered 31/8, 2020 at 18:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.