I don't think a plugin should be used for these kind of tasks. Also hkc's answer is actually not that bad, it only needs some further explanation to make this work with the nav_menu_item
post type (the one used for wp navigation menus).
This post type is already registered and thus we need to alter it, this is easily done by hooking into the register_post_type_args
filter. This filter allows us to change the arguments for a specific post type. The code below shows just that for the nav_menu_item
post type.
add_filter('register_post_type_args', function ($args, $post_type) {
if ($post_type == 'nav_menu_item' &&
class_exists('WP_REST_Posts_Controller') &&
!class_exists('WP_REST_NavMenuItem_Controller')) {
class WP_REST_NavMenuItem_Controller extends WP_REST_Posts_Controller {
public function get_items( $request ) {
$args = wp_parse_args($request, [
'order' => 'ASC',
'orderby' => 'menu_order',
]);
$output = [];
if (empty($request['menu'])) {
$menus = get_registered_nav_menus();
foreach ( $menus as $location => $description ) {
$items = wp_get_nav_menu_items($location, $args);
$output = array_merge($output, is_array($items) ? $items : []);
}
} else {
$items = wp_get_nav_menu_items($request['menu'], $args);
$output = array_merge($output, is_array($items) ? $items : []);
}
return rest_ensure_response($output);
}
public function get_collection_params() {
$query_params = parent::get_collection_params();
$query_params['menu'] = [
'description' => __( 'The name or also known as theme_location of the menu' ),
'type' => 'string',
];
return $query_params;
}
}
// Alter the post type arguments
$args['show_in_rest'] = true;
$args['rest_controller_class'] = 'WP_REST_NavMenuItem_Controller';
}
return $args;
}, 10, 2);
As you might have noticed from the code above, the code does a little bit more than just showing the post type in the REST. It also alters the default Posts REST controller to show a somewhat similar output in the REST as described in Liren's answer. Although next to that it also does what all post type REST controllers do and thus gives you more control and functionality. Also consider this as a more stable options as it wouldn't conflict with other REST routes and last but not least, it also way more convenient to work with.