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.