Exclure dynamiquement des éléments de menu de wp_nav_menu

17

J'ai essayé de chercher des informations sur la façon d'exclure / supprimer des éléments de menu nav des menus personnalisés, et le seul fil que j'ai trouvé n'a pas de réponses qui m'ont été utiles.

1. Origines:

J'ai mis en place un menu Dock en utilisant les menus personnalisés WP (wp_nav_menu) et jqDock sur mon site. Étant donné que jqDock a besoin d'images continues ou de liens d'image pour fonctionner sa magie, j'utilise un marcheur personnalisé de sorte que la sortie HTML du menu de navigation ressemble à ceci:

<div id="menu-first" class="nav">
<a><img src="http://path/to/image-1.png"/></a>
<a><img src="http://path/to/image-2.png"/></a>
<a><img src="http://path/to/image-3.png"/></a>
etc...
</div>

Le code de mon déambulateur personnalisé est:

class custom_nav_walker extends Walker_Nav_Menu 
{
    var $tree_type = array( 'post_type', 'taxonomy', 'custom' );
    var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );

    function start_lvl(&$output, $depth) {
        $indent = str_repeat("\t", $depth);
        $output .= "\n$indent<ul class=\"sub-menu\">\n";
    }

    function end_lvl(&$output, $depth) {
        $indent = str_repeat("\t", $depth);
        $output .= "$indent</ul>\n";
    }

    function start_el(&$output, $item, $depth, $args) {
        global $wp_query;
        $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

        $class_names = $value = '';

        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $classes[] = 'menu-item-' . $item->ID;

        $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
        $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 . $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        ) .'"' : '';

        $description  = ! empty( $item->description ) ? esc_attr( strtolower( $item->description )) : '';
        $item_title   = ! empty( $item->attr_title )  ? esc_attr( $item->attr_title ) : '';

        if ( strpos($description, ';') !== false ) {
        $description_array = explode (';', $description);
            $image_name = $description_array[0];
            $image_alt = $description_array[1];
        } else {
            $image_name = $description;
            $image_alt = $item_title;
        }

        $item_output = $args->before;
        $item_output .= '<a'. $attributes .'>';
        $item_output .= $args->link_before .'<img src="'.get_bloginfo('template_url').'/images/skin1/'.$image_name.'" alt="'.$image_alt.'" title="'.$item_title.'" />'.$args->link_after;
        $item_output .= '</a>';
        $item_output .= $args->after;

        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }

    function end_el(&$output, $item, $depth) {
        $output .= "";
    }

}

Le script jqDock intercepte ensuite l'ID de menu ('menu-first') et remplace la sortie wp_nav_menu par celle du menu Dock. La sortie HTML du menu Dock change en fonction des options spécifiées lors du chargement de jqDock.

2. La question:

Je souhaite ne pas afficher (c'est-à-dire exclure) certains éléments de menu en fonction de l'emplacement de l'utilisateur sur le site. Par exemple, je voudrais afficher uniquement l'élément d'accueil lorsque l'utilisateur n'est pas dans l'accueil et l'élément de publication aléatoire uniquement lorsqu'il l'est.

3. Solutions rejetées:

une. Menus multiples: L' enregistrement et la création de plusieurs menus, puis leur appel conditionnel pourraient fonctionner; cependant, je ne pense pas que ce soit une solution idéale ni propre du tout pour de nombreuses raisons. De plus, plusieurs menus ne sont pas faciles à maintenir ou à mettre à jour.

b. Recherche et remplacement d' expressions régulières : cela peut m'obliger à modifier le paramètre de l' aiguille chaque fois que je modifie les options de jqDock car la sortie HTML est modifiée.

c. Propriété d'affichage CSS: masquer les éléments via la propriété d'affichage CSS fonctionne, mais comme elle doit être appliquée à la sortie du menu jqDock, elle affecte le rendu visuel du menu.

4. Solutions ayant échoué:

une. Filtrer vers wp_nav_menu_items : j'ai essayé d'attraper la variable ($ items) (chaîne) et de lui affecter des valeurs différentes via des balises conditionnelles avec le code suivant:

function userf_dynamic_nav_menu ($items) {
    $items_array_home = explode('<a', $items);
    $items_array_nothome = $items_array_home;

    unset($items_array_home[1]);
    unset($items_array_nothome[2]);

    $items_home = implode('<a', $items_array_home);
    $items_nothome = implode('<a', $items_array_nothome);

    if ( is_home() ) {
        $items = $items_home;
    } else {
        $items = $items_nothome;
    }
    return $items;
}
add_filter('wp_nav_menu_first_items', 'userf_dynamic_nav_menu');

Cela ne fonctionne que partiellement, car les éléments de menu changent, mais les balises conditionnelles sont ignorées. Je suppose que cela a du sens en raison du moment où le filtre est appliqué.

b. Fonction de menu de navigation personnalisée : J'ai essayé de créer ma propre fonction de menu de navigation personnalisée pour pouvoir ajouter un argument d'exclusion au tableau $ defaults et utiliser ce code légèrement modifié wp_list_pagespour remplir l'argument supplémentaire:

$exclude_array = ( $args->exclude ) ? explode(',', $args->exclude) : array();
$args->exclude = implode( ',', apply_filters('wp_nav_menu_excludes', $exclude_array) );

Des idées?

Marventus
la source
Pouvez-vous nous montrer votre classe enfant de marcheur personnalisée?
soulseekah
Salut Souleseekah, je viens de l'ajouter à mon message d'origine. Merci!
Marventus
J'ai aussi pensé à passer un excludeargument, mais, contrairement à de wp_list_pagesnombreuses autres fonctions WP, wp_nav_menun'en inclut pas. Donc, même si j'en spécifie un lors de l'appel du menu ou dans le déambulateur, il ne serait pas récupéré à l'intérieur wp_nav_menu, n'est-ce pas?
Marventus
Désolé, je ne pensais pas bien quand j'ai écrit ça, supprimé immédiatement.
soulseekah
Ne vous en faites pas!
Marventus

Réponses:

26

Méthode 1

Vous pouvez ajouter un constructeur à votre Walker personnalisé pour stocker des arguments d'exclusion supplémentaires, comme:

class custom_nav_walker extends Walker_Nav_Menu {
    function __construct( $exclude = null ) {
        $this->exclude = $exclude;
    }

    function skip( $item ) {
        return in_array($item->ID, (array)$this->exclude);
        // or
        return in_array($item->title, (array)$this->exclude);
        // etc.
    }

    // ...inside start_el, end_el
    if ( $this->skip( $item ) ) return;
}

Ou déposez le constructeur et définissez sa $excludepropriété avant de le passer en tant que marcheur pour l' wp_nav_menu()aimer ainsi:

$my_custom_nav_walker = new custom_nav_walker;
$my_custom_nav_walker->exclude = array( ... );

Selon ce que vous excluez, fournissez le bon formulaire à exclure.

Méthode 2

C'est ainsi que vous vous y prendrez en vous connectant au wp_get_nav_menu_itemsfiltre.

function wpse31748_exclude_menu_items( $items, $menu, $args ) {
    // Iterate over the items to search and destroy
    foreach ( $items as $key => $item ) {
        if ( $item->object_id == 168 ) unset( $items[$key] );
    }

    return $items;
}

add_filter( 'wp_get_nav_menu_items', 'wpse31748_exclude_menu_items', null, 3 );

Remarque: object_idest l'objet vers lequel le menu pointe, tandis que IDl'ID du menu est différent.

Dis moi ce que tu penses.

soulseekah
la source
Merci! Ça pourrait marcher. Je vais essayer et je vous le ferai savoir.
Marventus
J'ai essayé l'approche du constructeur et, peu importe ce que j'essaie, j'obtiens toujours une erreur "Mauvais type de données pour le deuxième argument" pour la in_arrayfonction. Est-ce que je fais quelque chose de mal?
Marventus
La $excludepropriété doit être un tableau. Assurez-vous donc que vous passez un tableau dans le constructeur, ou regardez le code mis à jour dans ma réponse. Plus précisément le transtypage pour $this->exclude, juste au cas où un tableau ne serait pas transmis.
soulseekah
Désolé à ce sujet: j'avais une faute de frappe dans ma fonction. Je viens d'essayer $exclude = array ('4', '7');et d'utiliser les slugs aussi, mais cela n'a aucun effet sur la sortie du déambulateur. Je vais essayer la deuxième approche et je vous le ferai savoir.
Marventus
Non, ça n'a pas marché non plus. Je pense que je suis mort de cervelle d'essayer de comprendre cela, donc cela pourrait affecter mes ... "performances", :-)
Marventus
0

est-ce que cela aide

$exclude_array = ( $args->exclude ) ? explode(',', $args->exclude) : array();
$args->exclude = implode( ',', apply_filters('wp_nav_menu_excludes', $exclude_array) );

par exemple

< ?php wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary', 'exclude' => '66' ) ); ?>
saq
la source
Salut Saq, j'ai oublié de mentionner que l'une des solutions qui n'a pas fonctionné était de créer une fonction nav_menu personnalisée et d'ajouter ce code comme argument supplémentaire aux valeurs par défaut de la fonction. Malheureusement, cela n'a pas fonctionné. Je n'ai pas essayé de l'inclure dans le déambulateur, mais je ne pense pas que cela fonctionnerait non plus pour la même raison que j'ai mentionnée ci-dessus, principalement que le wp_nav_menun'a pas d'argument "exclure", mais je peux me tromper.
Marventus
J'ai mis à jour mon message d'origine pour l'inclure pour plus de clarté.
Marventus
que faire si vous n'utilisez pas un déambulateur personnalisé, au lieu de cela, vous utilisez un nav_menu normal et extrayez les éléments avec wp_get_nav_menu_items () avec votre image personnalisée
saq
Ce serait une bonne solution de contournement en général, mais dans ce cas particulier, wp_get_nav_menu_itemsne récupérera pas les images car les balises img ne sont pas stockées dans le menu personnalisé réel (seuls leurs noms de fichiers sont dans le champ de description, par exemple, "image1.png" ). Le marcheur personnalisé est ce qui me permet d'insérer les balises img dans la sortie du menu.
Marventus