Excluir dinámicamente los elementos del menú de wp_nav_menu

15

Intenté buscar información sobre cómo excluir / eliminar elementos del menú de navegación de menús personalizados, y el único hilo encontré que no tenía ninguna respuesta que me fuera útil.

1. Antecedentes:

Reuní un menú Dock utilizando los menús personalizados de WP (wp_nav_menu) y jqDock en mi sitio. Ya que jqDock necesita imágenes continuas o enlaces de imágenes para hacer su magia, estoy usando un andador personalizado para que la salida HTML del menú de navegación se vea así:

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

Elcódigoparamicaminantepersonalizadoes:

classcustom_nav_walkerextendsWalker_Nav_Menu{var$tree_type=array('post_type','taxonomy','custom');var$db_fields=array('parent'=>'menu_item_parent','id'=>'db_id');functionstart_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 .= "";
    }

}

La secuencia de comandos jqDock luego captura el ID de menú ('menu-first') y reemplaza la salida de wp_nav_menu con los menús del Dock. La salida HTML del menú Dock cambia según las opciones especificadas al cargar jqDock.

2. La pregunta:

Me gustaría no mostrar (es decir, excluir) ciertos elementos del menú según el lugar en el que se encuentre el usuario. Por ejemplo, me gustaría mostrar solo el elemento de inicio cuando el usuario no está en el inicio y el elemento de publicación aleatoria solo cuando está.

3. Soluciones descartadas:

a. Múltiples menús: Registrar y crear múltiples menús y luego llamarlos condicionalmente podría funcionar; sin embargo, no creo que esta sea una solución ideal ni limpia en absoluto por muchas razones. Además, los menús múltiples no son fáciles de mantener o actualizar.

b. Regex Search and Replace: Esto podría forzarme a cambiar el parámetro needle cada vez que cambio las opciones de jqDock porque se modifica la salida HTML.

c. Propiedad 'display' de CSS: La ocultación de los elementos a través de la propiedad de visualización de CSS funciona, pero como debe aplicarse a la salida del menú jqDock, afecta la representación visual del menú.

4. Soluciones fallidas:

a. Filtrar a wp_nav_menu_items : intenté capturar la variable (cadena) '$ items' y asignarle valores diferentes mediante etiquetas condicionales con el siguiente código:

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');

Esto funciona solo parcialmente, porque los elementos del menú sí cambian, pero las etiquetas condicionales se ignoran. Supongo que esto tiene sentido debido al momento en que se aplica el filtro.

b. Función de menú de navegación personalizada : intenté crear mi propia función de menú de navegación personalizada para poder agregar un argumento de exclusión a la matriz $ por defecto y usar este código ligeramente modificado de wp_list_pages para completar el argumento adicional:

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

¿Alguna idea?

    
pregunta Marventus 21.10.2011 - 19:14

2 respuestas

25

Método 1

Puedes agregar un constructor a tu Walker personalizado para almacenar algunos argumentos de exclusión adicionales, como:

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

O elimine el constructor y establezca su propiedad $exclude antes de pasarlo como paseante a wp_nav_menu() de esta forma:

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

Dependiendo de lo que esté excluyendo, proporcione el formulario correcto a la exclusión.

Método 2

Esta es la forma en que harías esto al enganchar en el filtro 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 );

Nota: object_id es el objeto al que apunta el menú, mientras que ID es el ID del menú, estos son diferentes.

Déjame saber tus pensamientos.

    
respondido por el soulseekah 21.10.2011 - 20:08
0

ayuda esto

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

como ejemplo

< ?php wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary', 'exclude' => '66' ) ); ?>
    
respondido por el saq 22.10.2011 - 02:11

Lea otras preguntas en las etiquetas