У меня есть одно "ответвление" дерева навигации моего основного сайта, которое должно только быть доступно для зарегистрированного ряда, зарегистрированные пользователи. Я понимаю, как запросить роль и возможности пользователя. Этот вопрос конкретно о том, что является лучшим способом усилить сборку - в военно-морском меню, но просто скрыть объект условно.
Я должен перегрузить встроенную навигацию по умолчанию и записать пользовательский запрос и создать структуру навигации вручную? Я хотел бы избежать этого, если это возможно.
Мне не нужны полные примеры кода, просто Ваши идеи и общие рамки / подход.
Цените совет!
T
Используйте своего собственного Уокера и проверьте возможность перед созданием объекта.
Ответ 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' ));
}
do_action()
в class Walker_Nav_Menu_Edit
– никакой API, чтобы сделать это. Похож на контроль.
– fuxia♦
07.04.2011, 19:53
Проблема переопределить 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;
}
Я попробовал силы в использовании поля описания для использования, относительно которого роли могут получить доступ, какие пункты меню, и основывал мои модификации на коде, который я получил отсюда - Сутенер мое Меню 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');
?>
Это еще не самая чистая версия, но это работает. Я надеюсь, что кто-то еще может сделать хорошее использование из него также.
Я собираюсь отправить свое решение для других, которые могут случайно встретить этот поток. Я не на 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);
}
}
}
Кто-то сделал блестящий плагин, чтобы сделать это без кодирования. Даже имеет флажки в интерфейсе редактора меню для выбора утвержденных ролей на пункт меню.