web-dev-qa-db-fra.com

Exclure dynamiquement les éléments de menu de wp_nav_menu

J'ai essayé de rechercher des informations sur la manière d'exclure/de supprimer les éléments de menu de navigation des menus personnalisés, et le seul thread que j'ai trouvé ne contenait aucune réponse qui me soit utile.

1. Contexte:

J'ai mis en place un menu Dock en utilisant WP menus personnalisés (wp_nav_menu) et jqDock sur mon site. Puisque jqDock a besoin d’images continues ou de liens d’images pour fonctionner comme par magie, j’utilise un lecteur personnalisé pour 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 marcheur 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 récupère ensuite l'ID de menu ('menu-first') et remplace la sortie wp_nav_menu par la sortie 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 l'élément d'accueil uniquement lorsque l'utilisateur ne se trouve pas dans l'accueil, et l'élément de publication aléatoire uniquement lorsqu'il l'est.

3. Solutions rejetées:

(a. Plusieurs menus:} _ L'enregistrement et la création de plusieurs menus, puis leur appel conditionnel pourraient fonctionner; Cependant, je ne pense pas qu'il s'agisse d'une solution idéale ni propre pour plusieurs raisons. De plus, il n'est pas facile de maintenir ou de mettre à jour plusieurs menus.

b. Regex Search and Replace: _ Cela pourrait m'obliger à modifier le paramètre aiguille à chaque fois que je modifie les options de jqDock, car la sortie HTML est modifiée.

(c. CSS 'display' property::} Masquer les éléments à travers la propriété d'affichage CSS fonctionne, mais puisqu'il doit être appliqué à la sortie du menu jqDock, cela affecte le rendu visuel du menu.

4. Solutions échouées:

a. Filtre sur wp_nav_menu_items: j'ai essayé d'attraper la variable '$ items' (chaîne) et de lui attribuer différentes valeurs à l'aide de 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é à partir de wp_list_pages pour renseigner 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?

16
Marventus

Méthode 1

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

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 supprimez le constructeur et définissez sa propriété $exclude avant de le transmettre en tant que promeneur à wp_nav_menu() comme ceci:

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

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

Méthode 2

Voici comment vous y parviendrez en vous connectant au filtre wp_get_nav_menu_items.

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_id est l’objet vers lequel pointe le menu, alors que ID est l’ID du menu, ils sont différents.

Laisse moi savoir ce que tu penses.

25
soulseekah

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' ) ); ?>
0
saq