Пункт меню экранной навигации условно на основе пользовательских возможностей

У меня есть одно "ответвление" дерева навигации моего основного сайта, которое должно только быть доступно для зарегистрированного ряда, зарегистрированные пользователи. Я понимаю, как запросить роль и возможности пользователя. Этот вопрос конкретно о том, что является лучшим способом усилить сборку - в военно-морском меню, но просто скрыть объект условно.

Я должен перегрузить встроенную навигацию по умолчанию и записать пользовательский запрос и создать структуру навигации вручную? Я хотел бы избежать этого, если это возможно.

Мне не нужны полные примеры кода, просто Ваши идеи и общие рамки / подход.

Цените совет!

T

5
07.04.2011, 17:21
6 ответов

Используйте своего собственного Уокера и проверьте возможность перед созданием объекта.

4
19.02.2020, 22:06
  • 1
    Абсолютно блестящий. Спасибо за это - хотя я удивлен, что это вполне столь же сложно как все это. Как Вы сказал, возможно контроль? –  Tom Auger 21.04.2011, 22:43
  • 2
    , Таким образом, Уокер хорош для проверки, что пункт меню, который отмечается, как "защищено", не появляется. Но как Вы создаете пункт меню, который отмечается столь же "защищенный", или, еще лучше, как принадлежащий определенной роли или возможности? Кажется, что мы расширяем пункты меню и добавляем еще некоторые пользовательские конфигурируемые параметры к форме пункта меню...? –  Tom Auger 17.05.2011, 18:54
  • 3
    @TomAuger Добавляет соответствующие метаданные к связанному объекту сообщения, например, пользовательская таксономия или сообщение meta поле. Проверьте значение поля в Уокера. –  fuxia♦ 17.05.2011, 18:56
  • 4
    Спасибо за разъяснение. Абсолютно пользовательская таксономия или пользовательское поле были бы надлежащим способом пойти. Другая опция, которую я придумал, основана на шаблоне. Мне не нравится мое решение так же, потому что Вы не должны связывать шаблон со встроенной функциональностью как этот, но существует логическое соединение между шаблоном (который должен проверить, есть ли у пользователя доступ для наблюдения содержания), и меню. Я собираюсь отправить свой код в ответе, ниже, для других пользователей с тем же вопросом. –  Tom Auger 20.05.2011, 15:42

Ответ toscho отправленный корректен, но для нескольких человек, которые знают то, что они делают и как сделать это.:) Я добавляю это для остальной части мира как простое решение для меньшего количества опытных пользователей. Идея состояла бы в том, чтобы иметь различные меню и просто отображение их на основе пользовательской роли.

Поэтому скажите, что у Вас есть 3 меню, названные редактором, автором и значением по умолчанию:

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' ));
}
3
19.02.2020, 22:06
  • 1
    Теперь необходимо управлять одним меню для каждой роли. Я добавил бы флажок к пунктам меню в редакторе. К сожалению, существует нет do_action() в class Walker_Nav_Menu_Edit – никакой API, чтобы сделать это. Похож на контроль. –  fuxia♦ 07.04.2011, 19:53
  • 2
    , который я согласовываю и я сам, добавил бы флажок или простое поле ввода для содержания требуемого ролевого имени, но снова я отправил этот ответ как альтернативу Вашему. Существует опция использовать поле описания для каждого объекта и на основе которого можно проверить роль, но затем Вы теряете способность к описанию. это - новый API, дайте ему некоторое время и открытый и много trac билетов, как Вы можете для получения его идущий :) –  Bainternet 07.04.2011, 20:21
  • 3
    Спасибо за это большее количество простого подхода. Я лично дрожу при необходимости определить мои меню через код - мне это полностью подрывает одну из основных характеристик wp_admin, но возможно нет никакой более легкой альтернативы. –  Tom Auger 21.04.2011, 22:45

Проблема переопределить start_el и end_el состоит в том, что выполнение поэтому только управляет дисплеем рассматриваемого пункта меню - это не влияет на дисплей детей. Я думаю, что необходимо переопределить display_element для сокрытия детей также.

Кроме того, возможно использовать поле описания пункта меню для содержания информации для каждого пункта меню о том, отобразить ли его или нет.

Этот код взгляды в описании каждого пункта меню для запятой разграничил список возможностей такой как [возможность: this_one, next_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;

}
2
19.02.2020, 22:06
  • 1
    я добавил этот ответ даже при том, что это некоторое время начиная с этого вопроса, был активен, потому что я думал, что это могло бы быть полезно для других. –  lpryor 24.08.2011, 00:46
  • 2
    +1 спасибо за то, что заняли время для добавления решения! Это всегда ценится другими, которые натыкаются на вопрос в поиске SE или Google.Удачи! –  Tom Auger 24.08.2011, 15:25

Я попробовал силы в использовании поля описания для использования, относительно которого роли могут получить доступ, какие пункты меню, и основывал мои модификации на коде, который я получил отсюда - Сутенер мое Меню WP

Моя измененная версия:

<?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');

?>

Это еще не самая чистая версия, но это работает. Я надеюсь, что кто-то еще может сделать хорошее использование из него также.

1
19.02.2020, 22:06

Я собираюсь отправить свое решение для других, которые могут случайно встретить этот поток. Я не на 100% доволен им, потому что Вы не должны связывать шаблон с функциональностью меню (подход Toscho использования метаданных, или пользовательская таксономия, вероятно, более корректна). Однако это - быстрое и грязное. Я попытался смягчить плотное соединение путем обеспечения некоторых констант около вершины functions.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, но он проверит, чтобы видеть ли current_user_can (ZG_PROTECTED_PAGE_CAPABILITY) прежде, чем отобразить любое содержание из соображений безопасности.

Затем, я реализую пользовательского Уокера согласно предложению Toscho. Уокер в этом случае чрезвычайно прост - мы переопределяем общественность Walker_Nav_Menu start_el и end_el методы, просто прервав их достаточно долго для задавания вопроса: у нас есть доступ для наблюдения пункта меню?

Правило просто: если страница не является "частной" страницей (который в этом случае определяется той страницей с помощью конкретного шаблона страницы), это видимо. Если это - "частная" страница, и пользователь аутентифицируется в роль, которая имеет пользовательскую возможность, которую мы ищем, то это видимо. Иначе это не видимо.

Если у нас действительно есть доступ, то мы просто должны использовать встроенные методы Walker_Nav_Menu без модификации, таким образом, мы называем родителя:: метод того же имени.

/* 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);
            }
        }
    }
0
19.02.2020, 22:06

Кто-то сделал блестящий плагин, чтобы сделать это без кодирования. Даже имеет флажки в интерфейсе редактора меню для выбора утвержденных ролей на пункт меню.

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

4
19.02.2020, 22:06

Теги

Похожие вопросы