Make WordPress Core

Opened 3 years ago

Last modified 11 months ago

#40878 assigned feature request

Adding menus route

Reported by: dingo_d Owned by: spacedmonkey
Milestone: Future Release Priority: normal
Severity: normal Version: 4.7
Component: REST API Keywords: has-patch dev-feedback needs-unit-tests
Focuses: rest-api Cc:


Currently there is no ${appUrl}/wp-json/wp/v2/menus route inside REST API for WordPress.

I know I can create a custom endpoint and define a route for it, or use a plugin, but wouldn't it be better to have it in the core?

I couldn't find a ticket for this, and inspecting the routes via postman showed no menus which means that it doesn't exists yet.

Is there any plan to add it to core?

Attachments (5)

40878.1.diff (11.3 KB) - added by schlessera 3 years ago.
First draft implementation to start discussion.
40878.2.diff (11.3 KB) - added by schlessera 3 years ago.
Fresh patch from clean source tree.
40878.diff (20.5 KB) - added by ryelle 2 years ago.
40878.3.diff (20.5 KB) - added by ryelle 2 years ago.
40878.4.diff (35.2 KB) - added by wpscholar 14 months ago.
Implemented REST API endpoints for menus, menu items, menu locations, and menu settings.

Download all attachments as: .zip

Change History (39)

#1 @johnbillion
3 years ago

  • Version changed from 4.7.5 to 4.7

There are no immediate plans to add support for menus to the REST API, and throughout 2017 the plans for the REST API only consist of stabilising the existing endpoints and looking into implementing them in the WordPress admin area.

There's a plugin available which adds support for menus in the REST API though: https://wordpress.org/plugins/wp-api-menus/

#2 @dingo_bastard
3 years ago

Yeah, I'm aware of the plugin, but it seemed like something that would be good to include in the future :)

#3 @web2033
3 years ago

I also hope to see this feature in the core...

#4 @schlessera
3 years ago

As discussed in Slack #core-js channel, I'm uploading my current code for working with WordPress menus through the REST API.

The basic code works:

menu-locations endpoint:
This provides basic enumeration, direct access through their slug, as well as linking and embedding the attached menus.
This is read-only, as the locations are defined in code, not stored in the database.

menus endpoint:
Extension of the terms controller. Provides all terms functionality, with the addition of making the linked menu items embeddable, as this would be a common use case.

menu-items endpoint:
Extension of the posts controller. Provides all posts functionality, with no customizations as of yet.
Shows the associated menu in the 'menus' property, which can also be queried: menu-items/?menus=2.

I assume that these implementations are still missing some subtleties, so consider this a first draft to serve as a basis for discussion.

Version 0, edited 3 years ago by schlessera (next)

3 years ago

First draft implementation to start discussion.

#5 @schlessera
3 years ago

  • Keywords has-patch dev-feedback added

#6 @schlessera
3 years ago

Some additional observations:

A first implementation I did created custom implementations for the menus and menu-items controllers. However, I think the more correct approach is to reuse the posts and terms controllers, and then add whatever information is needed to the post-type/taxonomy registration arguments to adapt them as needed.

With the above patch, the menu-items controller is just the standard posts controller.

The only thing that the additional menus-controller now does is make the menu items embeddable. But I think that could actually be a default for all post-type/posts relationships.

#7 @dingo_bastard
3 years ago

This is read-only, as the locations are defined in code, not stored in the database.

A POST request could be made on the same endpoint where you provide location name, then a check could be made in the callback function that will check if the location name is taken using get_registered_nav_menus(), and if the check passes one could register new nav menu using register_nav_menus().

I can try to make a patch for this.

Also when I try to apply the patch it fails on src/wp-includes/taxonomy.php (where 'rest_controller_class' => 'WP_REST_Menus_Controller' is)...

Last edited 3 years ago by dingo_bastard (previous) (diff)

#8 @schlessera
3 years ago

@dingo_bastard : I'm not sure I understand. Doing a POST request would allow to add a new menu location, but it wouldn't be persisted. Unless you add a new PHP file somewhere, or start storing menu locations in the database, any changes you could make would be gone with the next page request.

3 years ago

Fresh patch from clean source tree.

#9 @schlessera
3 years ago

@dingo_bastard : I uploaded a fresh patch from a clean source tree. Apparently, the previous one started from a changed code base already, sorry for that.

#10 @dingo_bastard
3 years ago

Oh right, my bad. I was working on a theme some time ago and we added additional menus via customizer settings, but those get saved in the database. Totally forgot about that.

We could add an option ${theme_name}_registered_menu_locations that could be saved for each theme and would contain menu locations. Although that would probably be a case for another ticket (one concerning registering menu locations and saving them in the database programmatically).

This ticket was mentioned in Slack in #core-restapi by adamsilverstein. View the logs.

3 years ago

#12 @dingo_bastard
2 years ago

Any news when will this be added to the core?

This ticket was mentioned in Slack in #core-restapi by dingo_d. View the logs.

2 years ago

This ticket was mentioned in Slack in #core-restapi by dingo_d. View the logs.

2 years ago

2 years ago

2 years ago

#15 @ryelle
2 years ago

40878.3.diff builds on @schlessera's earlier patch. I didn't see a controller for menu items, so this extends the WP_REST_Posts_Controller for GET requests to menu-items. You can now make requests like:

  • GET /wp/v2/menu-items/ for a full list of menu items
  • GET /wp/v2/menu-items/:id for a single menu item
  • GET /wp/v2/menu-items/?menus=2 for a list of menu items in menu with ID=2

I've added these so that we can get a Custom/Navigation Menu block in gutenberg, see this issue & PR. These are read-only, and they contain the extra menu-related fields like target, classes, attr_title, etc. This also replaces the post's link with the menu destination link (the link to the nav_menu_item post type does not exist).

For reference, the endpoints from schlessera's patch:

  • GET /wp/v2/menus for a list of available menus
  • POST /wp/v2/menus to create a new menu (taxonomy object)
  • GET /wp/v2/menus/:id for a single menu object
  • POST /wp/v2/menus/:id to update a single menu object
  • DELETE /wp/v2/menus/:id to delete a single menu object
  • GET /wp/v2/menu-locations for a list of available menu locations (theme-dependent)

You can also do an OPTIONS request on any of these to get more info.

Deleting a menu does not delete the sub-items in the menu, I think we'd want to call wp_delete_nav_menu in the menus controller. This also doesn't include any tests.

Note, the two uploads (40878.diff & 40878.3.diff) are the same file, re-uploaded to get the .3

Last edited 2 years ago by ryelle (previous) (diff)

#16 @schlessera
2 years ago

@ryelle Erm... I'm pretty sure I coded a menu items controller (you can even see screenshots of its output above). Not sure what happened to it and why it wasn't in the patch, but I'll try to find the code and compare with yours to see if we did the same thing.

This ticket was mentioned in Slack in #core-restapi by kadamwhite. View the logs.

2 years ago

#18 @schlessera
2 years ago

I looked through my code to see how I handled the menu-items endpoint.

I basically just reused the posts controller, by adding the following to the register_post_type() call for the nav_menu_item post type:

'show_in_rest'          => true,
'rest_base'             => 'menu-items',
'rest_controller_class' => 'WP_REST_Posts_Controller',

Through all the built-in mechanisms that the controller, and more specifically the posts controller provide, this allows for all general manipulations you might need.

Of course, as soon as we want to add menu-item-specific code, we'd need to extend the posts controller anyway, so @ryelle 's approach above makes sense.

This ticket was mentioned in Slack in #core-restapi by danbeil. View the logs.

2 years ago

#20 @dingo_bastard
18 months ago

Will this be added in the 5.x release? It would be a nice feature to have out of the box.

#21 @SergeyBiryukov
18 months ago

#45717 was marked as a duplicate.

This ticket was mentioned in Slack in #core-restapi by dingo_d. View the logs.

16 months ago

#23 @dd32
16 months ago

  • Reporter changed from dingo_bastard to dingo_d

14 months ago

Implemented REST API endpoints for menus, menu items, menu locations, and menu settings.

#24 @wpscholar
14 months ago

My latest attachment includes fully functional API endpoints for menus, menu items, menu locations, and menu settings.

There was a good bit of logic that is part of the wp_wpdate_nav_menu_item() function that needed to be duplicated to get it working properly in the menu items endpoint. One of these was the handling of orphaned menu items.

I made menu locations writeable, but only for updating the menu ID assigned to a menu location.

Menu settings is a new introduction that provides access to the auto_add option to automatically add top-level pages to a menu.

With all of these endpoints, it would be possible to completely replace the existing screen under Appearance -> Menus with a single page JavaScript app.

These endpoints are key to the initiative being explored here: https://github.com/WordPress/gutenberg/issues/13206

This ticket was mentioned in Slack in #core-restapi by wpscholar. View the logs.

14 months ago

This ticket was mentioned in Slack in #core-restapi by wpscholar. View the logs.

14 months ago

This ticket was mentioned in Slack in #core-restapi by wpscholar. View the logs.

13 months ago

This ticket was mentioned in Slack in #core-restapi by spacedmonkey. View the logs.

13 months ago

#29 @spacedmonkey
12 months ago

  • Keywords needs-unit-tests added

Thanks for everyone's work on this. I spent some time reviewing the patch and on the face of it looks good. But I personally believe that there is no way to have a meaningful code review via svn patches. I can not do code level reviews and discuss this. Any feature of this size, should start as a feature plugin.

To that end, we already have a feature plugin for this at wp-api-menus-widgets-endpoints. @wpscholar if you could take your patch and make it a pull request on that repo, we can work on it there. Once we have a solid api there, we can create a core patch from that, that should just a copy and paste in core.

#30 @wpscholar
12 months ago

@spacedmonkey Absolutely!

#32 @spacedmonkey
12 months ago

  • Milestone changed from Awaiting Review to Future Release
  • Owner set to spacedmonkey
  • Status changed from new to assigned

After today’s api dev chat. We agreed that the pr, should be merged as is and work on the code from there.

We need to work on unit tests, but we need to do that after finalised the design of the api.

#33 @spacedmonkey
12 months ago

Spent some time on this PR - https://github.com/WP-API/wp-api-menus-widgets-endpoints/pull/22 . I think it has a future, as it is pretty simple and easy to implement.

These endpoints, use override WP_REST_Terms_Controller and WP_REST_Posts_Controller, with some slight modifications.

If someone else from the REST API team could review, that would be extremely useful.

#34 @spacedmonkey
11 months ago

I have merged the last PR so we now have a functional feature plugin.

I am working some two new PRs.

These PRs have been done on my fork, but future PRs will be done as branches. Any subscribed to this ticket, please give comments to these PRs.

Note: See TracTickets for help on using tickets.