Repository navigation
Boolean request args fail validation #2616
Description
Activity
Hi @rachelbaker,
my first thought was:if ( 'boolean' === $args['type'] && ( ! is_bool( $value ) && ! in_array( $value, array( 'true', 'false' ) ) ) )But this passes strings, and maybe we run into problems later on. Wouldn't this be better:
class-wp-rest-terms-controller.php:
$query_params['hide_empty'] = array( 'description' => __( 'Whether to hide resources not assigned to any posts.' ), 'type' => 'boolean', 'default' => false, 'sanitize_callback' => 'rest_sanitize_request_arg', 'validate_callback' => 'rest_validate_request_arg', );plugin.php
function rest_sanitize_request_arg( $value, $request, $param ) { $attributes = $request->get_attributes(); if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) { return $value; } $args = $attributes['args'][ $param ]; if( 'boolean' === $args['type'] && in_array( $value, array( 'true', 'false' ) ) ) { if( 'true' === $value ) return true; return false; }EDIT:
Maybe it should also be extended for0and1...I think this might be a better approach.
$prepared_args['hide_empty'] = filter_var($prepared_args['hide_empty'], FILTER_VALIDATE_BOOLEAN);Hi @joelstransky,
where would this code be placed? If it is in theget_items()it would be too late, since validation takes place before.But, as far as I can see it sanitization takes place before validation (Actually, it works, but I am a bit unsure why, I thought there was some problem using both sanitization and validation together). So, if we add the boolean sanitization, it would pass the validation and we would reach
get_items().@websupporter It would need to be in
rest_validate_request_arg()for any 'type = booleanarg. We can't usefilter_var()` though because we cannot guarantee the extenstion is enabled in every installation of WordPress.Hmmm... not sure if I am on the right track, but if its okay for all to sanitize in the
get_items()let me introduce you toa neat little helper I've quickly wrote and which can sanitize and validate:<?php /** * Takes 'true', true, 1, 'yes, 'false', false, 0, 'no' as parameter and returns an boolean * @param $to_bool (mixed) * @return boolean|WP_Error **/ function wp_bool( $to_bool ) { $true = array( true, 1, '1', 'true', 'yes', ); $false = array( false, 0, '0', 'false', 'no', ); if ( in_array( $to_bool, $true, true ) ) { return true; } if ( in_array( $to_bool, $false, true ) ) { return false; } return new WP_Error( 'no-bool', __( 'The parameter was no boolean.' ) ); } ?>Instead of
is_bool()we would check inrest_validate_request_arg()if the outcome ofwp_bool()is an WP_Error. Inget_items()we can use it to sanitize.Would this be a better way?
@websupporter I took a similar approach in #2630. What do you think?
- added a commit that references this issue
on Sep 17, 2016
In rest_validate_request_arg() we cannot use the
! is_bool()conditional to validate if a request argument is eithertrueorfalse. The query string in the url (example: https://demo.wp-api.org/wp-json/wp/v2/categories?hide_empty=true) will be parsed as a string. Which means you will always get the error:{ code: "rest_invalid_param", message: "Invalid parameter(s): hide_empty", data: { status: 400, params: { hide_empty: "hide_empty is not of type boolean" } } }