根据用户功能有条件地显示导航菜单项

时间:2011-04-07 作者:Tom Auger

我的主站点导航树有一个“分支”,只有一组注册的、登录的用户才能访问。我了解如何查询用户的角色和功能。这个问题特别是关于利用内置导航菜单的最佳方式是什么,而只是有条件地隐藏项目。

我是否需要重载内置默认导航并编写自定义查询并手动构建导航结构?如果可能的话,我很想避免这种情况。

我不需要完整的代码示例,只需要您的想法和一般框架/方法。

感谢您的建议!

T

6 个回复
最合适的回答,由SO网友:fuxia 整理而成

使用您的own walker 并在创建项目之前检查功能。

SO网友:somatic

有人制作了一个出色的插件来实现这一点,无需编码。甚至在菜单编辑器界面中也有复选框,用于选择每个菜单项的批准角色。

http://wordpress.org/extend/plugins/nav-menu-roles/

SO网友:Bainternet

toscho发布的答案is correct 但对于少数知道自己在做什么以及如何做的人来说:我正在为世界其他地区添加此功能,作为针对较不高级用户的更简单解决方案。想法是有不同的菜单,并根据用户角色显示它们。

假设您有3个菜单,分别名为editor、author和default:

if (current_user_can(\'Editor\')){
    //menu for editor role
    wp_nav_menu( array(\'menu\' => \'editor\' ));

}elseif(current_user_can(\'Author\')){
    //menu for author role
    wp_nav_menu( array(\'menu\' => \'author\' ));

}else{
    //default menu
    wp_nav_menu( array(\'menu\' => \'default\' ));
}

SO网友:lpryor

覆盖start\\u el和end\\u el的问题在于,这样做只会控制相关菜单项的显示,而不会影响子菜单项的显示。我认为您需要重写display\\u元素来隐藏子元素。

此外,还可以使用菜单项的描述字段保存每个菜单项是否显示的信息。

此代码在每个菜单项的描述中查找以逗号分隔的功能列表,例如[功能:This\\u one,next\\u one],如果当前用户没有任何功能,则不会显示该项(或其任何子项)。如果您确实想将描述用于其预期目的,那么从描述中删除字符串是相当容易的。

/*
 * hide or display menus based on user capabilities
 *
 * Use the description field of the custom menu item. If it contains a string like [capability: xx, xx] 
 * display the menu item only if the user has at least one of the capabilities.
 * If a menu item is not displayed, nor are any of its sub items.
 */
/* Custom Walker */
class NASS_Nav_Walker extends Walker_Nav_Menu {

        // override parent method
        function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
            // we know the $element is a menu item  
            // we want to check its description field to see if it\'s OK to display it
            // in which case we just retreat to the parent method
            $desc = $element->description;
            if ( should_display_menu_item($desc) ) {
                parent::display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output );
            } else {
                return;
            }
        }    
}
/* should we display the menu item, if this is its description? */
function should_display_menu_item( $desc ) {
    // first see if the description contains a capability specification of the form
    // [capability: comma, delimited, list]
    // we assume all capability names consist only of lower case with underbars
    $prefix = "\\[capability:";
    $postfix = "\\]";
    $pattern = \'@\' . $prefix . \'([a-z_, ]+)\' . $postfix . \'@\';
    $answer = true;
    if ( preg_match($pattern, $desc, $matches) ) { // if we\'ve got a match
        $found = $matches[1];   // the parenthesized bit of the regex
        $caps = array_map(\'trim\', explode(",", $found));
        if ( count ($caps) > 0 ) { // there is at least one
            $answer = false;
            // now see if the user has any of them
            foreach ($caps as $cap) {
                if ( current_user_can ($cap) ) $answer = true;
            }
        }
    }
    return $answer;

}

SO网友:tejas

我曾尝试使用描述字段来确定哪些角色可以访问哪些菜单项,并根据我从这里得到的代码进行修改-Pimp my WP Menu

我的修改版本:

<?php

/***
* Menu WALKER - for restricting the menu items visibility
* Code modified by - Trupti Bhatt (http://3sided.co.in)
* using original code posted here - http://www.tisseur-de-toile.fr/wordpress-tricks/pimp-my-wordpress-menu-part-2-access-granted-to-authorized-personnel-only.html
***/
class description_walker extends Walker_Nav_Menu
{
        /*
                 *      Custom var to store current role
                 */
                private $current_user_role = "";

                /*
                 *      Get te current user role
                 */
                private function getCurrentUserRole()
                {
                                global $current_user;
                                if ( is_user_logged_in() )
                                {
                                        if ( $this->current_user_role == "" )
                                        {
                                                $this->current_user_role = $current_user->roles[0];
                                        }

                                        return $this->current_user_role;
                                }
                                else
                                {
                                        $this->current_user_role=\'visitor\';
                                        return $this->current_user_role;
                                }
                }

                /*
                 *      Check if the user is an administrator
                 */
                private function isAdmin()
                {
                                $current_role = $this->getCurrentUserRole();

                if ( $current_role == "administrator" )
                                {
                                                return true;
                                }
                                else
                                {
                                                return false;
                                }
                }

                /*
                 *      Get all restrictions
                 */
                private function getAllRestrictions()
                {
                        global $menu_restricted_access_array;


                                $all_restrictions_array = array();

                                foreach ( $menu_restricted_access_array as $one_restriction )
                                {
                                        $all_restrictions_array = array_merge($all_restrictions_array, $one_restriction);
                                }
                                $all_restrictions_array = array_unique($all_restrictions_array);

                                return $all_restrictions_array;
                }

                /*
                 *      Check the access
                 */
                private function isAccessGranted( $id_menu_item )
                {
                                global $menu_restricted_access_array;

                if ( $this->isAdmin() )
                                {
                                                return true;
                                }
                else if ( isset($menu_restricted_access_array[$this->current_user_role]) )
                {
                    $restricted_access = $menu_restricted_access_array[$this->current_user_role];

                    if ( in_array($id_menu_item, $restricted_access) )
                                        {
                        return true;
                                        }
                                        else
                                        {
                        return false;
                                        }
                }
                else {
                        return true;
                                        }

                }

     /*
                 *      Element render
                 */
                function start_el(&$output, $item, $depth, $args)
        {

            global $wp_query, $menu_restricted_access_array;
            global $g_role,$g_pageid;
            $indent = ( $depth ) ? str_repeat( "\\t", $depth ) : \'\';
                        $g_role=strtolower((trim($item->description)));

                        $str = explode(\',\',$g_role);
                        for( $i=0; $i< count($str); $i++)
                                {                      

                                        if (strtolower(trim($str[$i]))==$this->current_user_role)
                                        {                      
                                                $restriction =$item->object_id;        
                                                $menu_restricted_access_array[$this->current_user_role] =array( $restriction);
                                        }


                                }


            $class_names = $value = \'\';

            $classes = empty( $item->classes ) ? array() : (array) $item->classes;
            $classes[] = \'menu-item-\' . $item->ID;


            /*
             *  First test, add custom class to each menu item
             */
                $classes[] = \'my-custom-menu-class\';

            /*
             *  Detect the menu item matching the unpublished page
             *  Detect the menu item matching the unpublished page
             */
                // -> FLag to display the output
                $item_to_display = true;
                $is_item_published = true;

                // -> Gather data of linked object
                $item_data = get_post($item->object_id);

                // --> If it\'s a page, act on the flag

                if ( !empty($item_data) && ($item->object == "page") )
                {
                    $is_item_published = ( $item_data->post_status == "publish" ) ? true : false;
                    $item_output = "";
                }

            /*
             *  Detect and display by user Role
             **/
                if ( _USE_RESTRICTED_ACCESS )
                {
                    $restrictions_array = $this->getAllRestrictions();
                    $this->isAccessGranted($item->object_id);

                }
                else
                {
                    $item_to_display = $is_item_published;
                }

            $class_names = join( \' \', apply_filters( \'nav_menu_css_class\', array_filter( $classes ), $item ) );
            $class_names = \' class="\' . esc_attr( $class_names ) . \'"\';



            $id = apply_filters( \'nav_menu_item_id\', \'menu-item-\'. $item->ID, $item, $args );
            $id = strlen( $id ) ? \' id="\' . esc_attr( $id ) . \'"\' : \'\';

            $output .= $indent . \'<li id="menu-item-\'. $item->ID . \'"\' . $value . $class_names .\'>\';

            $attributes  = ! empty( $item->attr_title ) ? \' title="\'  . esc_attr( $item->attr_title ) .\'"\' : \'\';
            $attributes .= ! empty( $item->target )     ? \' target="\' . esc_attr( $item->target     ) .\'"\' : \'\';
            $attributes .= ! empty( $item->xfn )        ? \' rel="\'    . esc_attr( $item->xfn        ) .\'"\' : \'\';
            $attributes .= ! empty( $item->url )        ? \' href="\'   . esc_attr( $item->url        ) .\'"\' : \'\';



                        if($depth != 0)
                        {
                    $description = $append = $prepend = "";
                        }

            // --> If the flag is true, when display the output

            if ( $item_to_display )
            {
                $item_output = $args->before;
                $item_output .= \'<a\'. $attributes .\'>\';
                $item_output .= $args->link_before .apply_filters( \'the_title\', $item->title, $item->ID ).$append; // this is where the strong tags are prepend and append to the description

                                $item_output .= \'</a>\';
                $item_output .= $args->after;
            }

            $output .= apply_filters( \'walker_nav_menu_start_el\', $item_output, $item, $depth, $args );
        }
}
/*
 *      Restrictions configuration
* 2 is page id of Homepage
 **/
define("_USE_RESTRICTED_ACCESS", true);
$menu_restricted_access_array[\'subscriber\'] = array(\'2\');

?>
它还不是最干净的版本,但它可以工作。我希望其他人也能好好利用它。

SO网友:Tom Auger

我将把我的解决方案发布给可能发生在这个帖子上的其他人。我对它不是百分之百满意,因为您不应该将模板与菜单功能结合在一起(Toscho使用元数据或自定义分类法的方法可能更正确)。然而,这是一个快速和肮脏的。我试图通过在函数顶部附近提供一些常量来缓解紧耦合。php帮助未来的开发人员维护代码:

// define the custom password-protected template that is used to determine whether this item is protected or not in the menus
define (\'ZG_PROTECTED_PAGE_TEMPLATE\', \'page-membersonly.php\');
// define the custom capability name for protected pages
define (\'ZG_PROTECTED_PAGE_CAPABILITY\', \'view_member_pages\');
因此,受保护的页面模板只是single的一个变体。php,但出于安全原因,它会在显示任何内容之前检查当前的\\u user\\u是否可以(ZG\\u PROTECTED\\u PAGE\\u功能)。

接下来,根据Toscho的建议,我实现了一个自定义walker。本例中的walker非常简单-我们覆盖walker\\u Nav\\u菜单的公共start\\u el和end\\u el方法,只是拦截它们足够长的时间来问这个问题:我们有权查看菜单项吗?

规则很简单:如果页面不是“私有”页面(在本例中是由该页面使用特定页面模板确定的),那么它是可见的。如果它是一个“私有”页面,并且用户被验证为具有我们正在寻找的自定义功能的角色,那么它是可见的。否则,它将不可见。

如果我们确实有访问权限,那么我们只需使用Walker\\u Nav\\u菜单的内置方法,而无需修改,因此我们调用同名的父::方法。

/* Custom Walker to prevent password-protected pages from appearing in the list */
    class HALCO_Nav_Walker extends Walker_Nav_Menu {

        protected $is_private = false;
        protected $page_is_visible = false;

        // override parent method
        function start_el(&$output, $item, $depth, $args) {
            // does this menu item refer to a page that is using our protected template?
            $is_private = get_post_meta($item->object_id, \'_wp_page_template\', true) == ZG_PROTECTED_PAGE_TEMPLATE;
            $page_is_visible = !$is_private || ($is_private && current_user_can(ZG_PROTECTED_PAGE_CAPABILITY));

            if ($page_is_visible){
                parent::start_el(&$output, $item, $depth, $args);
            }
        }

        // override parent method
        function end_el(&$output, $item, $depth) {
            if ($page_is_visible){
                parent::end_el(&$output, $item, $depth);
            }
        }
    }

结束

相关推荐

Thesis -style Navigation

我正在研究一个主题,我希望用户能够像论文一样选择要在主题选项页面中显示的页面。我已经在谷歌上搜索了几个小时的逆向工程论文,但还没有找到一个很好的解决方案。我想知道是否有人做过这件事或看过教程。