Opened 3 years ago
Last modified 4 days ago
#54304 new enhancement
Expose menu data public in Menus REST API
Reported by: | spacedmonkey | Owned by: | |
---|---|---|---|
Milestone: | 6.8 | Priority: | normal |
Severity: | normal | Version: | 4.7 |
Component: | REST API | Keywords: | has-patch needs-testing needs-refresh |
Focuses: | rest-api | Cc: |
Description
Menus endpoints will be added in #40878. However by default this data requires the user to be logged in with the correct capability to access this data.
There should be a way to allow developers or users to expose menu / menu item / menu location publically in REST API.
Change History (24)
This ticket was mentioned in PR #1863 on WordPress/wordpress-develop by spacedmonkey.
3 years ago
#1
- Keywords has-patch added; needs-patch removed
This ticket was mentioned in PR #1863 on WordPress/wordpress-develop by spacedmonkey.
3 years ago
#2
Trac ticket: https://core.trac.wordpress.org/ticket/54304
#3
@
3 years ago
As a talking point I have create a POC PR at #1863.
What this does, add a filter new property to the WP_Term object for the menu called, show_in_rest. This property has a filter. To expose the data simple use this filter.
apply_filters( 'wp_get_nav_menu_show_in_rest', false, $menu_obj, $menu )
To make all the menus public, you simple need to this.
add_filter('wp_get_nav_menu_show_in_rest', '__return_true');
Having this filter on the menu level makes sense for a couple of reasons.
- Adding a filter on menu item does make sense, as either you make the whole menu public or not all.
- Location does not make sense, as some menus may not be used in locations, like widgets or other custom implements.
- Menu, are already an object and is easy to add a property to it.
#4
@
7 months ago
It would be really nice to get this Feature. It would move WordPress to be easier to use as a Headless CMS.
This ticket was mentioned in Slack in #core by stoyangeorgiev. View the logs.
6 weeks ago
#6
@
6 weeks ago
- Keywords needs-testing added
Adding need-testing since it has patch and it passed all checks.
#8
@
4 weeks ago
Thanks for your help here @ignatggeorgiev!
Would it be possible to assign the milestone 6.7 here @chaion07?
Would be glad to get this into 6.7 :)
#9
@
4 weeks ago
- Milestone changed from Future Release to 6.7
Updated the milestone to 6.7 as suggested by @masteradhoc
Thank you for notifying and let us hope that we can take this Ticket forward and closer to a resolution.
Props to @masteradhoc
#10
@
13 days ago
- Keywords needs-refresh added
I wanted to test the PR, but It seems that it may need to be refreshed, as it introduces a dynamic class property.
#11
@
13 days ago
I have been considering this ticket. I am not sure this ticket belongs in core. If it had landed in core when the menu endpoint did, this would make sense, but now block themes are more common, this menu endpoint is less and less useful.
I am worried about any solution that requires opt-in would makes for lot of duplicated code for developers. Lots of the following across many codebases
<?php add_filter( 'menu_endpoint_public', '__return_true' );
My suggetion, we create a canonical plugin maintained by the REST API / core team to make, menu, menu item and menu locations public endpoints. If developers / users want to make this data public, they can install this plugin / make it is a dependency to your theme / plugin.
I made a start on this plugin here. If the rest of the REST API team, I will look at transfering the repo to the REST API github org and get this plugin on repo.
Would love the throught of @TimothyBlynJacobs @kadamwhite @antonvlasenko
#12
@
12 days ago
I'm open to the idea of adding this to a plugin. I'd like to share a few thoughts to initiate the discussion:
- Moving the code to a plugin could relieve the burden of maintaining functionality that may be becoming obsolete. That seems like a positive step.
- However, the plugin would also require ongoing maintenance. I wonder if maintaining a plugin might be more time-consuming compared to keeping the code within Core (if the PR were to be merged).
- As of today (October 2, 2024), there are 5 950 non-FSE themes and 984 FSE themes in the WordPress.org theme directory. While I agree that block themes are gaining popularity, it seems that classic themes still hold a significant share.
#13
@
11 days ago
Totally second @antonvlasenko's opinion here. The usage is still really high and quite a lot headless sites will still be built in a hybrid mode using the block editor for content editing and the classic way to manage menu's.This will still be beneficial for a long time.
This ticket was mentioned in Slack in #core by stoyangeorgiev. View the logs.
10 days ago
This ticket was mentioned in PR #7501 on WordPress/wordpress-develop by @spacedmonkey.
10 days ago
#15
- Keywords needs-refresh removed
Introduce 'rest_menu_read_access' filter to allow customization of read access permissions in REST API endpoints for menus, menu items, and menu locations. This facilitates more flexible access control based on custom criteria.
Trac ticket: https://core.trac.wordpress.org/ticket/54304
#16
follow-up:
↓ 21
@
10 days ago
- Keywords needs-refresh added
@antonvlasenko @masteradhoc To be clear, I still think this ticket is important and worthwile.
To that end, I have another solution. I have put together a simple PR that adds a new opt-in filter that makes the data public. See https://github.com/WordPress/wordpress-develop/pull/7501
I think this is the simpliest solution.
This ticket was mentioned in Slack in #core-restapi by spacedmonkey. View the logs.
10 days ago
#18
@
8 days ago
@spacedmonkey Thanks for the feedback and the updated PR!
Just checked on a fresh WP 6.6.2 with GeneratePress Theme / GeneratePress Childtheme installed.
These Endpoints got checked:
- /wp-json/wp/v2/menus/
- /wp-json/wp/v2/menus/5
- /wp-json/wp/v2/menu-items
- /wp-json/wp/v2/menu-items/15
- /wp-json/wp/v2/menu-locations
- /wp-json/wp/v2/menu-locations/primary
By default without any change or PR applied i get this. Same also when not being loggedin:
{ "code": "rest_cannot_view", "message": "Sorry, you are not allowed to view menu locations.", "data": { "status": 401 } }
Lets apply the PR and enter the following filter in the functions.php of the child theme:
// https://core.trac.wordpress.org/ticket/54304 add_filter( 'rest_menu_read_access', '__return_true' );
All works fine as i see! All the noted endpoints show up although im not logged in.
Thanks @spacedmonkey!
#19
@
7 days ago
- Milestone changed from 6.7 to 6.8
- Type changed from defect (bug) to enhancement
I'm moving this to the next milestone and reclassifying the ticket as an enhancement. The permissions work at present, it appears what's been discussed is whether they should be changed to allow additional users access.
#20
@
7 days ago
I agree this changing milestone and ticket type.
@peterwilsoncc I would love your thoughts my latest PR. Is a filter the right course here or should we do something clever with user permissoins.
#21
in reply to:
↑ 16
@
7 days ago
Replying to spacedmonkey:
@antonvlasenko @masteradhoc To be clear, I still think this ticket is important and worthwile.
I agree it's important and worthwhile, @spacedmonkey.
I think choosing between a filter or a plugin boils down to how other similar features are handled in Core and what's best for this particular case.
Filters don't seem to be used much for this type of job, as opposed to capabilities, so adding a new capability seems right from an architectural standpoint. But adding a new capability is more labor-intensive. Tough choice.
#22
@
5 days ago
Responding to @spacedmonkey's question in Slack,
So are you okay with the filter option or should this live in a plugin?
I'm fine with the filter, I think it's the simplest solution. We have a lot of areas in REST code already that encourage developers to copy-paste specific filter code on all projects (many people disable public REST access entirely, many people set all their endpoint permissions_callbacks to __return_true
whether they should or not, etc), and this doesn't feel like it makes that situation any different.
Should it be 1 filter for all menus or one filter per endpoints, one for menus, menu items and menu locations?
I feel personally that the boolean toggle is enough. However, if others disagree, what if we did something like allowed_block_types_all
, where you could return a boolean true
for "all access" or an array of route string paths to be selective?
#23
@
5 days ago
The I have the filter setup is like this
/**
* Filters whether the current user has read access to menu items via the REST API.
*
* @since 6.8.0
* @param $read_only_access bool Whether the current user has read access to menu items via the REST API.
* @param $request WP_REST_Request Full details about the request.
* @param $this WP_REST_Controller The current instance of the controller.
*/
$read_only_access = apply_filters( 'rest_menu_read_access', false, $request, $this );
This filter has WP_REST_Request
and current controller WP_REST_Controller
as context. If you, for example wanted to limit the filter, you could do this.
add_filter( 'rest_menu_read_access', function( $current, $request, $controller ){
if ( $controller instanceof WP_REST_Menu_Locations_Controller ) {
return false;
}
return true;
}, 10, 3 );
You can also limit by the request,
add_filter( 'rest_menu_read_access', function( $current, $request){
if ( ! empty( $request['id'] ) ) {
return false;
}
return true;
}, 10, 2 );
I personally can't think of how else you might want to limit this access. But this filter seems to cover all bases.
Are you happy @kadamwhite ?
Trac ticket: https://core.trac.wordpress.org/ticket/54304