Skip to content

Instantly share code, notes, and snippets.

@abrarfahad
Forked from levymetal/direct_parent.php
Last active August 29, 2015 14:06
Show Gist options
  • Save abrarfahad/e75d42e373b90714a29c to your computer and use it in GitHub Desktop.
Save abrarfahad/e75d42e373b90714a29c to your computer and use it in GitHub Desktop.
<?php
// add hook
add_filter( 'wp_nav_menu_objects', 'my_wp_nav_menu_objects_sub_menu', 10, 2 );
// filter_hook function to react on sub_menu flag
function my_wp_nav_menu_objects_sub_menu( $sorted_menu_items, $args ) {
if ( isset( $args->sub_menu ) ) {
$root_id = 0;
// find the current menu item
foreach ( $sorted_menu_items as $menu_item ) {
if ( $menu_item->current ) {
// set the root id based on whether the current menu item has a parent or not
$root_id = ( $menu_item->menu_item_parent ) ? $menu_item->menu_item_parent : $menu_item->ID;
break;
}
}
// find the top level parent
if ( ! isset( $args->direct_parent ) ) {
$prev_root_id = $root_id;
while ( $prev_root_id != 0 ) {
foreach ( $sorted_menu_items as $menu_item ) {
if ( $menu_item->ID == $prev_root_id ) {
$prev_root_id = $menu_item->menu_item_parent;
// don't set the root_id to 0 if we've reached the top of the menu
if ( $prev_root_id != 0 ) $root_id = $menu_item->menu_item_parent;
break;
}
}
}
}
$menu_item_parents = array();
foreach ( $sorted_menu_items as $key => $item ) {
// init menu_item_parents
if ( $item->ID == $root_id ) $menu_item_parents[] = $item->ID;
if ( in_array( $item->menu_item_parent, $menu_item_parents ) ) {
// part of sub-tree: keep!
$menu_item_parents[] = $item->ID;
} else if ( ! ( isset( $args->show_parent ) && in_array( $item->ID, $menu_item_parents ) ) ) {
// not part of sub-tree: away with it!
unset( $sorted_menu_items[$key] );
}
}
return $sorted_menu_items;
} else {
return $sorted_menu_items;
}
}
<?php
wp_nav_menu( array(
'theme_location' => 'primary',
'sub_menu' => true
) );
<?php
$menu_to_count = wp_nav_menu( array(
'theme_location' => 'primary',
'sub_menu' => true,
'echo' => false
) );
$menu_items = substr_count( $menu_to_count, 'class="menu-item ' );
if ( $menu_items != 0 ) echo $menu_to_count;
@abrarfahad
Copy link
Author

The menu builder in WordPress is great, however quite often I find myself needing to create a secondary menu on pages, containing just a subset of the menu. In my case the rules are simple: when viewing a top level page we want to list all child pages nested beneath it. When viewing a second level page, we want to list all sibling pages nested under the same parent. We could just use wp_list_pages and filter by a parent, but it won’t match the structure designed in the menu builder, which defeats the purpose of using it.

Surprisingly there’s little information or working solutions to this problem, so I’ve put together the following code which does exactly what we want. You can view a demo of the code (and all combinations of options) on the demo page here: http://wp-sub-menu-demo.christianvarga.com/.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment