wp-cli / restful

Unlocking the potential of the WP REST API at the command line

Home Page:https://wp-cli.org/restful/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

wrong schema loaded for commands causes fault

diablodale opened this issue · comments

fail case:
wp-cli --http=myserver.com rest user list

result:
Error: Invalid field: password.

I believe this is due to the wrong schema being loaded. The schema for POST on the user route is used with a list command. It should use the GET schema since this is a list command. Specifically in this scenario, the core WP rest routes define the password field as required in the POST schema. Same time, the password field is absent from the GET schema. When the core WP REST api returns results for users, it does not send a password field. This causes a fault in the wpcli formatter because it tries to access a password field on the array.

I believe this is due to the wrong schema being loaded.

Correct.

I suppose we could store the schema declared on each route, although technically the schema is supposed to remain the same between routes.

I found related info. You'll know your codebase more.
Something in the code is changing the result from /wp-json/ -> into a json schema. Where is that code?
For password, when I look at the raw json schema, the
$route_data['schema']['properties']['password']['context']
is empty. Which I suspect then causes code to fallback to 'view'. The fallback either being a code problem --or- that the raw /wp-json/ defines the default like this:

"\/wp\/v2\/users": {
			"namespace": "wp\/v2",
			"methods": ["GET",
			"POST"],
			"endpoints": [{
				"methods": ["GET"],
				"args": {
					"context": {
						"required": false,
						"default": "view",

In the latter case, the code is probably working correctly and instead perhaps a fault in core WP.

If I hack in the following in load_remote_commands the problem goes away:

if (isset($route_data['schema']['properties']['password'])) $route_data['schema']['properties']['password']['context'] = ['edit'];

This leads me to believe it is related to the empty array for context and a fallback to view

I think I found the issue in get_context_fields()

if ( empty( $args['context'] ) || in_array( $context, $args['context'] ) ) {

should instead be:

if ( isset( $args['context'] ) && in_array( $context, $args['context'] ) ) {

My thinking is that if the context for a field is empty, then it should never be used for anything. This is the case for password and I likely for any field.

Closing for now. We can revisit when this project is actively used and maintained.