Implements navigation menu support with two new types: Menu and MenuItem. Each have singular and plural root queries. MenuItems are connected to both Menus and to themselves—this allows for the implementation of childItems (hierarchical nav menu queries):
Query{
menus( location: MAIN ) {
edges {
node {
id
menuItems {
edges {
node {
id
label
url
title
target
linkRelationship
description
childItems {
edges {
node {
cssClasses
description
id
label
linkRelationship
menuItemId
target
title
url
connectedObject {
... on Post {
id
title
content
}
}
}
}
}
connectedObject {
... on Post {
id
title
content
}
}
}
}
}
}
}
}
}
MenuItems can also be queried directly with an id or location:
{
menuItems( first: 1 where: { location: FOOTER } ){
edges {
node {
id
connectedObject {
... on Post {
id
title
content
}
}
}
}
}
}
Menu locations are implemented as an Enum. This allows the schema to communicate which menu locations have been registered for the current active theme.
The connectedObject field returns a Union of types that can be added the nav menus: post types, taxonomy terms, and custom links (itself a MenuItem). This provides consistent communication of the information about a nav menu object (which is usually the thing the user is trying to query).
MenuItems are tightly tied to the hierarchy of their Menu (parent-child relationships are stored in post meta), so we cannot resolve MenuItems if we cannot resolve the Menu that they belong to. In other words, this query returns an empty array:
{
menuItems {
edges {
node {
id
}
}
}
}
The "type" of a WP nav menu item is stored in the post meta key _menu_item_type and describes whether the menu item points to a post or a term or is a custom link. In WPGraphQL-speak, it describes the type of the object that is connected to the menuItem; in the query below, it informs the __typename
of the connectedObject field:
menuItems(
where: {
location: MY_MENU_LOCATION
}
) {
nodes {
connectedObject {
__typename
... on Post { # post, _menu_item_type = post_type
title
}
... on Book { # custom post type, _menu_item_type = post_type
title
}
... on Category { # tax term, _menu_item_type = taxonomy
name
}
... on MenuItem { # "custom link", _menu_item_type is empty
title
}
}
}
}
}
You can see that the meta key value of _menu_item_type quickly becomes irrelevant, because it not connected to WPGraphQL's type system. What you're really asking for is a way to filter the menuItems by the __typename
of their connectedObject.
You can do that manually, of course, once you get the results back. Implementing it as a query arg, however, would mean either (a) using a post meta query (non-starter, too expensive), or (b) getting all of the menu items and then filtering them on the WPGraphQL side.
I'm not sure if doing (b) makes sense or might lead to issues (e.g., complicated pagination). Under the hood, we're using wp_get_nav_menu_items to the get the menu items so it's not straightforward to combine query args.
So this needs some investigation. In the meantime, I can recommend filtering by __typename
on the consuming side.