Пользовательская иерархия типов записей Wordpress и подсветка меню (current_page_parent) - PullRequest
8 голосов
/ 17 июля 2010

Я создал пользовательский тип сообщения «портфолио» и страницу с шаблоном, который извлекает все сообщения, соответствующие этому пользовательскому типу.

Проблема в том, что когда я углубляюсь в реальный пост, пост, кажется, находится под «блогом» в выделении главного меню (отображает current_page_parent как класс)

URL-адрес ссылки правильный: www.site.com/portfolio/post-slug

Но в меню говорится, что родитель - это "блог".

Это, очевидно, иерархическая проблема, но я не знаю, что делать, чтобы ее исправить.

Ответы [ 5 ]

12 голосов
/ 17 июля 2010

Похоже, это проблема с основным кодом Wordpress;код, который генерирует классы меню, добавляет current_page_parent к вашей странице блога везде, кроме случаев, когда вы просматриваете шаблоны статических страниц.

(Это обсуждалось попутно на http://core.trac.wordpress.org/ticket/13543).

Однако вы можете обойти этос помощью некоторого пользовательского кода с использованием фильтра page_css_class. Например, добавьте что-то вроде этого в файл functions.php (не проверенный на 100%):

function my_page_css_class($css_class, $page) {
    if (get_post_type()=='portfolio' || is_page(57)) {
        if ($page->ID == get_option('page_for_posts')) {
            foreach ($css_class as $k=>$v) {
                if ($v=='current_page_parent') unset($css_class[$k]);
            }
        }
        if ($page->ID==57) {
            $css_class[]='current_page_parent';
        }
    }
    return $css_class;
}
add_filter('page_css_class','my_page_css_class',10,2);

Конечно, заменив 57 идентификатором страницы ваших портфелей.Это удаляет current_page_parent при печати страницы блога и добавляет current_page_parent на страницу ваших портфелей при просмотре отдельного портфолио или самой странице портфолио.

6 голосов
/ 11 сентября 2013

Вот моя оптимизированная / расширенная версия ранее предложенных решений, которая в значительной степени полностью автоматизирована. Больше никаких дополнительных атрибутов CSS или меню не требуется.

Эта версия динамически получает список пользовательских типов сообщений, и если текущий тип сообщений является пользовательским типом сообщений, то он удаляет класс 'current_page_parent' из всех пунктов меню.

Кроме того, он проверяет каждый элемент меню, чтобы определить, предназначен ли он для страницы с шаблоном страницы, таким как "page- {custom_post_type_slug} .php", и если это так, он добавит класс 'current_page_parent'.

Приоритет фильтра - 1, так как некоторые темы заменяют current_page_parent / etc. классы с таким классом, как «активный» (например, это делает «корни»), поэтому этот фильтр должен сначала выполняться.

Наконец, он использует 3 статические переменные, поскольку эта функция вызывается неоднократно, и они (очевидно) остаются неизменными во всех вызовах.

function theme_current_type_nav_class($css_class, $item) {
    static $custom_post_types, $post_type, $filter_func;

    if (empty($custom_post_types))
        $custom_post_types = get_post_types(array('_builtin' => false));

    if (empty($post_type))
        $post_type = get_post_type();

    if ('page' == $item->object && in_array($post_type, $custom_post_types)) {
        if (empty($filter_func))
            $filter_func = create_function('$el', 'return ($el != "current_page_parent");');

        $css_class = array_filter($css_class, $filter_func);

        $template = get_page_template_slug($item->object_id);
        if (!empty($template) && preg_match("/^page(-[^-]+)*-$post_type/", $template) === 1)
            array_push($css_class, 'current_page_parent');

    }

    return $css_class;
}
add_filter('nav_menu_css_class', 'theme_current_type_nav_class', 1, 2);

PS. Просто чтобы указать на один недостаток во всех не-CSS решениях, которые я видел до сих пор, включая мое собственное: Что-то, что не принимается во внимание, выделяет пункт меню родителя / предка элемента, ссылающегося на страницу, которая отображает сообщения текущего пользовательского типа сообщения. Рассмотрим пользовательский тип записи "product" и меню вроде:

Home  Company  News  Contact
      |
      \--About Us
      \--Products

«Продукты» - это страница с шаблоном «page-product.php», которая показывает обзор постов типа «продукт». Это выделено благодаря опубликованному решению. Однако «Компания» как ее родитель / предок также должна быть выделена, но это не так. Что-то иметь в виду.

3 голосов
/ 15 февраля 2013

Билет WP: http://core.trac.wordpress.org/ticket/16382

function fix_blog_menu_css_class( $classes, $item ) {
    if ( is_tax( 'my-cat-tax' ) || is_singular( 'my-post-type' ) || is_post_type_archive( 'my-post-type' ) ) {
        if ( $item->object_id == get_option('page_for_posts') ) {
            $key = array_search( 'current_page_parent', $classes );
            if ( false !== $key )
                unset( $classes[ $key ] );
        }
    }

    return $classes;
}
add_filter( 'nav_menu_css_class', 'fix_blog_menu_css_class', 10, 2 );
0 голосов
/ 24 марта 2013

Вот решение, которое сработало для меня, без необходимости определять мой собственный тип записи или идентификатор меню или идентификатор страницы в коде:

http://dtbaker.net/web-development/how-to-stop-wordpress-automatically-highlighting-the-blog-page-in-the-menu/

function dtbaker_wp_nav_menu_objects($sorted_menu_items, $args){
    // this is the code from nav-menu-template.php that we want to stop running
    // so we try our best to "reverse" this code wp code in this filter.
    /* if ( ! empty( $home_page_id ) && 'post_type' == $menu_item->type && empty( $wp_query->is_page ) && $home_page_id == $menu_item->object_id )
            $classes[] = 'current_page_parent'; */

    // check if the current page is really a blog post.
    //print_r($wp_query);exit;
    global $wp_query;
    if(!empty($wp_query->queried_object_id)){
        $current_page = get_post($wp_query->queried_object_id);
        if($current_page && $current_page->post_type=='post'){
            //yes!
        }else{
            $current_page = false;
        }
    }else{
        $current_page = false;
    }


    $home_page_id = (int) get_option( 'page_for_posts' );
    foreach($sorted_menu_items as $id => $menu_item){
        if ( ! empty( $home_page_id ) && 'post_type' == $menu_item->type && empty( $wp_query->is_page ) && $home_page_id == $menu_item->object_id ){
            if(!$current_page){
                foreach($sorted_menu_items[$id]->classes as $classid=>$classname){
                    if($classname=='current_page_parent'){
                        unset($sorted_menu_items[$id]->classes[$classid]);
                    }
                }
            }
        }
    }
    return $sorted_menu_items;
}
add_filter('wp_nav_menu_objects','dtbaker_wp_nav_menu_objects',10,2);
0 голосов
/ 10 декабря 2010

Я еще немного огляделся по этому поводу и нашел другой способ сделать это.

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2);
function current_type_nav_class($css_class, $item) {
$post_type = get_query_var('post_type');

if (get_post_type()=='portfolio') {
    $current_value = "current_page_parent"; 
    $css_class = array_filter($css_class, function ($element) use ($current_value) { return ($element != $current_value); } );
}

if ($item->attr_title != '' && $item->attr_title == $post_type) {       
    array_push($css_class, 'current_page_parent');
};
return $css_class;

}

Я получил некоторую справку из этого поста, а затем изменил его, чтобы также удалитьКласс current_page_parent со страницы блога.https://wordpress.stackexchange.com/questions/3014/highlighting-wp-nav-menu-ancestor-class-w-o-children-in-nav-structure/3034#3034

Сердечно Ваю

...