Plugin: Automatic submenu items - Cobbled Code

At some point our navigation menu started to mimic the hierarchical structure of the posts itself. Manually adding all items just seemed silly. This sounded like a good candidate for wp_list_pages(). Hardcoding the menu would mean losing flexibility, however. It would be nice if all child posts would be added automatically, with the option of overriding that behaviour by manually adding menu items.

With WordPress it’s like “Filter all the Things”, hence the Submenu 3000 plugin.

Customise behaviour

Per default, the plugin acts on menus in all theme menu locations. This can be changed via the submenu_3000 filter. To restrict the automatic submenus to a specific menu location, look at the $args->theme_location value:

add_filter( 'submenu_3000', 'prefix_filter_submenu_3000', 10, 4 );

/**
 * Only add submenu items to a specific theme location.
 *
 * @param string   $item_output The menu item's starting HTML output.
 * @param WP_Post  $item        Menu item data object.
 * @param int      $depth       Depth of menu item. Used for padding.
 * @param stdClass $args        An object of wp_nav_menu() arguments.
 */
function prefix_filter_submenu_3000( $item_output, $item, $depth, $args ) {

	if ( 'primary' !== $args->theme_location ) {
		return false;
	}
}

We can also add menu items only for specific post types. The $item object provides information about the post that the menu item links to:

add_filter( 'submenu_3000', array( $this, 'filter_submenu_3000' ), 10, 4 );

/**
 * Only automatically add submenu to menu items linking to pages.
 *
 * @param string   $item_output The menu item's starting HTML output.
 * @param WP_Post  $item        Menu item data object.
 * @param int      $depth       Depth of menu item. Used for padding.
 * @param stdClass $args        An object of wp_nav_menu() arguments.
 */
function filter_submenu_3000( $item_output, $item, $depth, $args ) {

	/*
	 * Note that $item will be a 'nav_menu_item' post type.
	 * The post type of item it links to is found in $item->object,
	 * the original ID in $item->object_id.
	 */
	if ( 'page' !== $item->object ) {
		return false;
	}
}

Download the latest release as a .zip file. Or fork, create an issue or pull request on GitHub.

Build Status

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.