使用自定义菜单时,从主导航中排除私人页面和草稿页面

时间:2012-10-11 作者:Jeff Cohan

我正在寻找防止“私有”和“草稿”页面(对于未登录的管理员)出现在基于自定义菜单的网站主导航菜单中的方法,而不是手动从WP自定义菜单中删除这些页面,然后在发布时将其拖回。

FWIW,我很惊讶我正在寻找的行为不是默认的。

使用:WP 3.4.2

5 个回复
SO网友:jjaderberg

我有一个类似的问题,这里是我能想到的最好的解决方案。我认为,菜单中显示私有或未发布项目的原因是菜单项目本身就是帖子,并且有自己的post_status. 这意味着,在页面被标记为私有的情况下,该页面的菜单项仍然可以设置为发布并显示。我为wp_nav_menu_objects 钩子可以看到post_status 对于菜单项所代表的对象,如果该对象是私有的,则将其从菜单中删除。在我的情况下,关注的是私有页面,但可以很容易地将其应用于草稿。我还允许在用户登录时显示菜单项,无论其功能如何,而WP在默认情况下限制管理员和编辑对私有页面的访问。这也可以很容易地进行调整。

function jj_filter_private_pages_from_menu ($items, $args) {
    foreach ($items as $ix => $obj) {
        if (!is_user_logged_in () && \'private\' == get_post_status ($obj->object_id)) {
            unset ($items[$ix]);
        }
    }
    return $items;
}
add_filter (\'wp_nav_menu_objects\', \'jj_filter_private_pages_from_menu\', 10, 2); 
在我看来,过滤菜单项比用CSS隐藏菜单项更容易、更合适,你的理解可能会有所不同。

若要将专用页的菜单项限制为管理员和编辑器,您应该能够替换current_user_can (\'read_private_pages\') 对于!is_user_logged_in ().

SO网友:sinds78

我将此用作隐藏草稿页的解决方案。可以使用li隐藏(草稿页)菜单项。草稿类。

add_filter(\'nav_menu_css_class\' , \'nav_menu_add_post_status_class\' , 10 , 2);
function nav_menu_add_post_status_class($classes, $item){
    $post_status = get_post_status($item->object_id);
    $classes[] = $post_status;
    return $classes;
}
FWIW:我也有同感;-)

SO网友:brasofilo

最简单的解决方案是向要隐藏的菜单项添加特定的类。然后通过CSS隐藏它们。

custom nav menu classes
^单击可放大^

默认情况下,CSS类不可见,您必须在Screen Options 上部选项卡。

如果主题没有在<body> 标签,这将执行以下操作:

add_filter( \'body_class\', \'wpse_67929_body_class\' );

function wpse_67929_body_class( $classes ) 
{
    if( !is_user_logged_in() )
        $classes[] = \'not-logged-menu\';

    return $classes;
}
最后,在您的style.css, 添加此规则:

body.not-logged-menu .menu-logged-in {display:none}
<小时>Another option, 使用以下筛选器:

add_filter(\'wp_nav_menu_items\', \'wpse_67929_nav_menu_items\', 10, 2 );

function wpse_67929_nav_menu_items( $nav_menu, $args )
{
    // Manipulate the output
    // $nav_menu contains a single string with the menu Html structure
    // more or less like this: 
    // <li id class><a href>Menu Item</a></li> <ul><li><a>Submenu Item</li></ul> <etc>
    return $nav_menu;
}
“操纵输出”看起来很简单,但却很棘手:

SO网友:Joel MMCC

用CSS隐藏它们是有问题的,因为它们仍然会通过网络发送,并且仍然会向任何查看源代码的人、出于任何原因禁用CSS的人(例如盲用户-CSS只会让他们慢下来,没有真正的好处)以及黑客脚本等暴露可能是敏感信息的信息。

不,我们需要一种方法,允许将菜单项添加到引用页面或帖子的菜单中,但如果这些菜单项所引用的页面或帖子已完全公开发布,则只能通过网络显示或发送这些菜单项。非草稿、非挂起、非私有、非计划(直到计划时间过去),当然也不是垃圾。

这是我在另一个地方找到的一个解决方案,我做了一些修改(添加到theme的functions.php):

function exclude_draft_nav_items( $items, $menu, $args )
{
  global $wpdb;

  //add your custom posttypes to this array
  $allowed_posttypes = array( \'post\', \'page\' );

  $sql = "SELECT ID FROM {$wpdb->prefix}posts WHERE (post_status!=\'publish\') AND ID=%d && post_type=%s";

  foreach ( $items as $k => $item )
  {
    if( in_array($item->object, $allowed_posttypes) )
    {
      $query = $wpdb->prepare( $sql, $item->object_id, $item->object );
      $result = $wpdb->get_var( $query );

      if( $result ) unset($items[$k]);
    }
  }

  return $items;
}

add_filter( \'wp_get_nav_menu_items\', \'exclude_draft_nav_items\', 10, 3 );

SO网友:p_leo

最好对数据库进行一次调用,而不是多次查询,尤其是在菜单有多个项目的情况下。根据其他一些答案,您可以构建一个已批准ID的列表,并使用该列表筛选项目。请注意,数组声明是PHP7。0个+

function exclude_draft_nav_items( $items, $menu, $args ){
    global $wpdb;
    $ids = [];
    $out = [];
    foreach( $items as $k=>$v ){
        $ids[] = $v->object_id;
    }
    $ids = join( \',\', $ids );
    $res = $wpdb->get_results("SELECT ID FROM $wpdb->posts WHERE ID IN ($ids) AND post_status = \'publish\'");
    $ids = [];
    foreach( $res as $v ){
        $ids[ $v->ID ] = true;
    }
    foreach( $items as $v ){
        if( !isset( $ids[$v->object_id] ) ){
            continue;
        }
        $out[] = $v;
    }
    return $out;
}

add_filter( \'wp_get_nav_menu_items\', \'exclude_draft_nav_items\', 10, 3 );

结束

相关推荐

Restrict WordPress to Private

我想建立一个只有2个用户的私有WordPress站点,我只需要一个简单的私有站点功能,访问者在尝试登录时无法看到任何东西,只能重定向到登录页面。RSS也应该被阻止。我发现有一个插件可以做到这一点,但它似乎没有得到维护,还有其他插件可以做同样的事情并得到维护吗?http://wordpress.org/extend/plugins/members-only/