Aggiungere voci di menu dinamicamente usando wp_nav_menu_objects
Nella mia navigazione principale, voglio che ogni pagina di primo livello mostri un elenco delle relative sottopagine. Ho creato del codice che aggiunge dinamicamente voci di menu alla navigazione principale. Questo funziona solo per il primo livello di sottopagine. Come puoi vedere, ho commentato il codice che gestisce il secondo livello perché mostrava quei link al livello principale. Non capisco perché non funzioni al secondo livello. Potrebbe essere che non possiamo assegnare una voce di menu a un elemento genitore generato dinamicamente?
Ecco come appare:
add_filter( 'wp_nav_menu_objects', 'epc_wp_nav_menu_items', 10, 2 );
function epc_wp_nav_menu_items($items, $args) {
if ($args->theme_location == 'primary') {
$menu_order = 10000;
$menu_order2 = 20000;
global $wpdb;
global $post;
$post_id = 0;
if($post){
$post_id = $post->ID;
}
foreach($items as $item){
$pageChildren = $wpdb->get_results("SELECT post_title, ID FROM wp_posts WHERE post_parent = ".$item->object_id." AND post_status = 'publish' AND post_type='page' ORDER BY menu_order", 'OBJECT' );
foreach($pageChildren as $child){
$menu_order++;
$new_item = epc_add_menu_item($post_id, $menu_order, $item, $child);
$items[] = (object)$new_item;
/*
$pageChildrenSecondLevel = $wpdb->get_results("SELECT post_title, ID FROM wp_posts WHERE post_parent = ".$child->ID." AND post_status = 'publish' AND post_type='page' ORDER BY menu_order", 'OBJECT' );
foreach($pageChildrenSecondLevel as $child2){
$menu_order2++;
$new_item2 = epc_add_menu_item($post_id, $menu_order2, $new_item, $child2);
$items[] = (object)$new_item2;
}
*/
}
}
}
return $items;
}
function epc_add_menu_item($post_id, $menu_order, $item, $child){
$new_item = new stdClass;
$new_item->ID = $menu_order;
$new_item->menu_item_parent = $item->ID;
$new_item->url = get_permalink( $child->ID );
$new_item->title = $child->post_title;
$new_item->menu_order = $menu_order;
$new_item->object_id = $child->ID;
$new_item->post_parent = $item->object_id;
$classes = 'menu-item';
$classes .= ' menu-item-parent-' . $item->ID;
$classes .= ' menu-item-type-post_type';
$classes .= ' menu-item-object-page';
if($post_id == $child->ID){
$classes .= ' current-menu-item';
$classes .= ' page-item';
$classes .= ' page-item-' . $child->ID ;
$classes .= ' current_page_item';
}
$new_item->classes = $classes;
return $new_item;
}

Dovresti anche specificare il campo db_id
per la voce di menu genitore:
function epc_add_menu_item( $post_id, $menu_order, $item, $child ) {
...
$new_item->db_id = $menu_order;
...
}
Nota a margine: una voce di menu che ha elementi figli dovrebbe avere anche la classe menu-item-has-children
.

Utilizza questa classe personalizzata per visualizzare il sottomenu:
class Wp_Sublevel_Walker extends Walker_Nav_Menu {
function start_lvl(&$output, $depth = 0, $args = array()) {
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul class='submenu'>\n";
}
function end_lvl(&$output, $depth = 0, $args = array()) {
$indent = str_repeat("\t", $depth);
$output .= "$indent</ul>\n";
}
}

Se le voci del tuo menu personalizzato sono basate su post, categorie o altri oggetti di WordPress, puoi utilizzare wp_setup_nav_menu_item(oggetto_WP) per ottenere un oggetto voce di menu.
$item=wp_setup_nav_menu_item(get_post());
Questo oggetto avrà la maggior parte delle informazioni impostate correttamente, ma non tutte le informazioni sono presenti. Dobbiamo ancora impostare alcune proprietà dell'elemento. Dobbiamo impostare la voce di menu genitore, se vuoi che sia al livello superiore assegna il valore 0.
$item->menu_item_parent = $parentitem->ID;
Affinché una voce abbia figli, devi assegnare un db_id, ma questo DEVE essere l'ID dell'oggetto WordPress, non funzionerà (o meglio, non sono riuscito a farlo funzionare) con altri valori. Quindi dobbiamo impostarlo:
$item->db_id = get_the_ID();
Se la voce corrente avrà figli, aggiungi menu-has-children
alla variabile delle classi. Nota che aggiungo anche altre classi (css) richieste dal mio tema.
$item->classes = array("menu-item", "menu-item-type-post_type", "menu-item-object-page", "menu-item-has-children");
Potresti essere in grado di creare un elemento personalizzato creando la voce come descritto sopra e poi modificando $item->title
e $item->url
ma mantenendo gli ID. Assicurati solo che l'ID sia univoco nel livello del menu (non ho verificato se deve essere univoco nell'intero menu).
(Per altri come me che hanno trovato questo thread cercando di creare un menu personalizzato: L'ordine del menu deve essere tale che il genitore sia seguito direttamente dai suoi figli.)
