Filtrar wp_nav_menu ()

9

Tento dividir minha navegação em três barras de navegação únicas (nível 1, nível 2 e nível3 +). Três porque estão separados no site e devem aparecer apenas dependendo da página atual.

-0-------1--------2-------3+- level/depth
Home
 |
 |\___ Lobby
 |
 |\___ Projects
 |       |\___ Project A
 |       |       |\___ Review
 |       |       |\___ Comments
 |       |       \____ Download
 |       \____ Project B
 |               |\___ Review
 |               |\___ Comments
 |               \____ Download
 |\___ Blog
 |
 \____ About
         |\___ Legal
         \____ Contact

A primeira barra de navegação que contém o nível 1 está sempre visível. A segunda barra de navegação (nível 2) somente quando estou atualmente na página pai correspondente. O mesmo vale para a terceira barra de navegação (nível 3+, mais porque esta barra de navegação também conterá subpáginas e páginas de subsub ... do nível 3).

Resumindo: quero exibir todos os menus pai em suas barras de navegação e apenas os filhos diretos da página atual.

O que eu tentei:

function my_nav_menu( $args = array() )
{
    $echo = isset( $args['echo'] ) ? (bool)( $args['echo'] ) : true;
    $args['echo'] = false;

    add_filter( 'wp_get_nav_menu_items' , 'my_nav_menu_filter' , 666 , 3 );

    $menu = wp_nav_menu( $args );

    remove_filter( 'wp_nav_menu_objects' , 'my_nav_menu_filter' , 666 );

    if( $echo )
        echo $menu;
    else
        return $menu;
}

function my_nav_menu_filter( $items , $menu , $args )
{
    //var_dump( $args );

    $navLevel = isset( $args['navlevel'] ) ? (int)( $args['navlevel'] ) : 0;

    //echo 'navlevel = ' . $args['navlevel'] . ' | ' . $navLevel;

    if( $navLevel == 1 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
                unset( $items[$key] );
        }
    }
    else if( $navLevel == 2 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
            {
                $page = get_page( $item->menu_item_parent );

                if( $page->menu_item_parent == 0 )
                    continue;
            }

            unset( $items[$key] );
        }
    }
    else if( $navLevel == 3 )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
            {
                $page = get_page( $item->menu_item_parent );

                if( $page->menu_item_parent != 0 )
                    continue;
            }

            unset( $items[$key] );
        }
    }
    else
    {
        //var_dump( $items );
    }

    return $items;
}

Chamando isso no meu header.php: <?php my_nav_menu( array( 'echo' => false , 'navlevel' => 1 ) ); ?>

No entanto, $argsé definido com os valores padrão e minha entrada personalizada navlevelnão é mostrada no filtro.

Como posso dividir minha barra de navegação conforme descrito? Como defino minha $argsentrada personalizada ?

absurdo
fonte
2
Bom dia e bem-vindo à WPSE. Devo parabenizá-lo por uma pergunta épica construída pela primeira vez. Perguntas bem construídas e claras sempre recebem muita atenção com boas respostas. 1
Pieter Goosen
3
A resposta a esta envolve uma classe personalizada Walker, talvez isso irá ajudar qualquer answerers potenciais
Tom J Nowell
Obrigado. Eu cavei em php / wp apenas neste fim de semana, então não sou tão familiar. Eu tentei um Walker personalizado, no entanto, o Walker lida apenas com um único item de cada vez, por isso não posso compará-lo ao item atual. E um filtro não aceita meu argumento personalizado. Hmmm ...
nonsensation

Respostas:

3

Eu acho que recebi a resposta:

function my_nav_menu( $args = array() )
{
    $echo = isset( $args['echo'] ) ? (bool)( $args['echo'] ) : true;

    $args['echo'] = false;

    add_filter( 'wp_nav_menu_objects' , 'my_filter_nav_menu' , 100 , 2 );

    $menu = wp_nav_menu( $args );

    remove_filter( 'wp_nav_menu_objects' , 'my_filter_nav_menu' , 100, 2 );

    if( $echo )
        echo $menu;
    else
        return $menu;
}

Isso faz o truque: permita-me alterar os itens de menu e argumentos personalizados ainda estão disponíveis. Eu acidentalmente liguei o filtro em wp_get_nav_menu_itemsvez de wp_nav_menu_objects. Ainda estou tendo problemas com a filtragem, no entanto, esses provavelmente são alguns erros lógicos ..

Edição: vou resolver o meu problema, combinando navbar nível 2 e navbar nível 3+ em um e separando-os com css

aqui está a parte atual do php:

function serthy_filter_nav_menu( $items , $args )
{
    $argArray = (array)( $args );

    if( isset( $argArray['toplevel'] ) )
    {
        foreach( $items as $key => $item )
        {
            if( $item->menu_item_parent != 0 )
                unset( $items[$key] );
        }

        return $items;
    }

    global $post;

    $arr = array();

    foreach( $items as $key => $item )
    {
        $parentIDs = get_post_ancestors( $item->ID );

        foreach( $parentIDs as $i => $parentID )
        {
            if( $parentID == $post->ID )
            {
                array_push( $arr , $item );

                break;
            }
        }
    }

    return $arr;
}
absurdo
fonte
Parece bom para mim à primeira vista. Você tem problemas com esse código? Sidenote: Você pode encurtar a sua primeira declaração:$echo = ! isset( $args['echo'] ) ?: $args['echo'];
kaiser
1

Parece-me que você poderia lidar com isso através do CSS, pois poderia ocultar as opções de menu de nível inferior por padrão e optar por mostrá- las se elas tiverem determinadas classes acima delas.

Em desta página Codex , você pode ver as classes de menu (e em sua própria página). Portanto, para o "segundo nível" que você descreveu, assumindo que o menu do primeiro nível seja o nível 1 - não 0.

ul > li > ul.sub-menu { display: none; }  /* Hide by default */
ul > li.current-menu-parent > ul.sub-menu { display: block; } /* Show menu */

E então algo semelhante para o próximo nível abaixo:

ul > li > ul.sub-menu > li > ul.sub-menu{ display: none; }  /* Hide by default */
ul > li > ul.sub-menu > li.current-menu-parent > ul.sub-menu { display: block; }

Obviamente, substitua "block" por "inline-block" ou o que normalmente estiver definido em seus menus.

Talvez você precise brincar para encontrar a combinação certa de classes, mas tive sorte com esse método antes. O WP solta uma tonelada de classes por lá, e pode usá-las.

Amanda Giles
fonte
Obrigado, vou usar algumas aulas em css para minhas barras de navegação! :)
nonsensation
Se você acabou usando esta solução, poderia marcar minha resposta como aceita? Obrigado.
Amanda Giles