Filtre wp_nav_menu ()

9

J'essaie de diviser ma navigation en 3 barres de navigation uniques (niveau 1, niveau 2 et niveau3 +). Trois car ils sont séparés sur le site et ils ne devraient apparaître qu'en fonction de la page en cours.

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

La première barre de navigation contenant le niveau 1 est toujours visible. La deuxième barre de navigation (niveau 2) uniquement lorsque je suis actuellement sur la page parent correspondante. Il en va de même pour la troisième barre de navigation (niveau 3+, plus car cette barre de navigation contiendra également des sous-pages et des sous-pages ... de niveau 3).

En bref: je veux afficher tous les menus parents dans leurs barres de navigation et uniquement les enfants directs de la page en cours.

Ce que j'ai essayé:

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;
}

Appelant cela dans mon header.php: <?php my_nav_menu( array( 'echo' => false , 'navlevel' => 1 ) ); ?>

Cependant, il $argsest défini sur les valeurs par défaut et mon entrée personnalisée navleveln'est pas affichée dans le filtre.

Comment puis-je diviser ma barre de navigation comme décrit? Comment définir mon $argsentrée personnalisée ?

non-compensation
la source
2
Bonjour et bienvenue au WPSE. Je dois vous féliciter pour une question épique construite pour un premier temporisateur. Des questions bien construites et claires reçoivent toujours beaucoup d'attention avec de bonnes réponses. +1
Pieter Goosen
3
La réponse à cela implique une classe de Walker personnalisée, peut-être que cela aidera tous les répondeurs potentiels
Tom J Nowell
Je vous remercie. J'ai creusé dans php / wp seulement ce week-end, donc je ne suis pas familier. J'ai essayé un Walker personnalisé, mais le Walker ne gère qu'un seul élément à la fois, donc je ne peux pas le comparer à l'élément actuel. Et un filtre n'accepte pas mon argument personnalisé. Hmmm ...
non

Réponses:

3

Je pense avoir obtenu la réponse:

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;
}

Cela fait l'affaire: me permet de modifier les menus et les arguments personnalisés sont toujours disponibles. J'ai accidentellement accroché le filtre à la wp_get_nav_menu_itemsplace de wp_nav_menu_objects. J'ai toujours des problèmes avec le filtrage, mais ce sont probablement des bugs logiques ..

EDIT: je vais résoudre mon problème en combinant le niveau 2 de la barre de navigation et le niveau 3+ de la barre de navigation en un et en les séparant avec CSS

voici la partie php actuelle:

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;
}
non-compensation
la source
Ça me semble bien au premier coup d'œil. Avez-vous des problèmes avec ce code? Sidenote: Vous pouvez raccourcir votre première déclaration:$echo = ! isset( $args['echo'] ) ?: $args['echo'];
kaiser
1

Il me semble que vous pouvez gérer cela via CSS en ce sens que vous pouvez masquer les options de menu de niveau inférieur par défaut, puis choisir de les afficher si elles ont certaines classes au-dessus.

Sur cette page du Codex , vous pouvez voir les classes de menu (et sur votre page elle-même). Donc, pour le "deuxième niveau" que vous avez décrit, en supposant que le menu du premier niveau est le niveau 1 - pas 0.

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

Et puis quelque chose de similaire pour le niveau suivant:

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; }

Remplacez évidemment "block" par "inline-block" ou tout ce que vos menus sont normalement définis.

Vous devrez peut-être jouer pour trouver la bonne combinaison de classes, mais j'ai déjà eu de la chance avec cette méthode auparavant. WP y dépose une tonne de cours, autant les utiliser.

Amanda Giles
la source
Merci, je vais utiliser des cours en CSS pour mes barres de navigation! :)
non
Si vous avez fini par utiliser cette solution, pourriez-vous s'il vous plaît marquer ma réponse comme acceptée? Je vous remercie.
Amanda Giles