REST API: Support the multipleOf JSON Schema keyword.

Props yakimun.
Fixes #51022.


git-svn-id: https://develop.svn.wordpress.org/trunk@49063 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Timothy Jacobs 2020-09-27 19:01:18 +00:00
parent 7b64dc237a
commit dbf692583c
4 changed files with 50 additions and 4 deletions

View File

@ -1552,6 +1552,7 @@ function rest_stabilize_value( $value ) {
* Support the "minItems", "maxItems" and "uniqueItems" keywords for arrays. * Support the "minItems", "maxItems" and "uniqueItems" keywords for arrays.
* Validate required properties. * Validate required properties.
* @since 5.6.0 Support the "minProperties" and "maxProperties" keywords for objects. * @since 5.6.0 Support the "minProperties" and "maxProperties" keywords for objects.
* Support the "multipleOf" keyword for numbers and integers.
* *
* @param mixed $value The value to validate. * @param mixed $value The value to validate.
* @param array $args Schema array to use for validation. * @param array $args Schema array to use for validation.
@ -1691,9 +1692,16 @@ function rest_validate_value_from_schema( $value, $args, $param = '' ) {
} }
} }
if ( in_array( $args['type'], array( 'integer', 'number' ), true ) && ! is_numeric( $value ) ) { if ( in_array( $args['type'], array( 'integer', 'number' ), true ) ) {
/* translators: 1: Parameter, 2: Type name. */ if ( ! is_numeric( $value ) ) {
return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, $args['type'] ) ); /* translators: 1: Parameter, 2: Type name. */
return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, $args['type'] ) );
}
if ( isset( $args['multipleOf'] ) && fmod( $value, $args['multipleOf'] ) !== 0.0 ) {
/* translators: 1: Parameter, 2: Multiplier. */
return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be a multiple of %2$s.' ), $param, $args['multipleOf'] ) );
}
} }
if ( 'integer' === $args['type'] && ! rest_is_integer( $value ) ) { if ( 'integer' === $args['type'] && ! rest_is_integer( $value ) ) {
@ -2298,6 +2306,7 @@ function rest_get_endpoint_args_for_schema( $schema, $method = WP_REST_Server::C
'maximum', 'maximum',
'exclusiveMinimum', 'exclusiveMinimum',
'exclusiveMaximum', 'exclusiveMaximum',
'multipleOf',
'minLength', 'minLength',
'maxLength', 'maxLength',
'pattern', 'pattern',

View File

@ -281,7 +281,7 @@ class WP_Test_REST_Controller extends WP_Test_REST_TestCase {
$this->assertArrayHasKey( $property, $args['somestring'] ); $this->assertArrayHasKey( $property, $args['somestring'] );
} }
foreach ( array( 'minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum' ) as $property ) { foreach ( array( 'multipleOf', 'minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum' ) as $property ) {
$this->assertArrayHasKey( $property, $args['someinteger'] ); $this->assertArrayHasKey( $property, $args['someinteger'] );
} }

View File

@ -435,6 +435,42 @@ class WP_Test_REST_Schema_Validation extends WP_UnitTestCase {
$this->assertSame( 'param must be between 10 (inclusive) and 20 (inclusive)', $error->get_error_message() ); $this->assertSame( 'param must be between 10 (inclusive) and 20 (inclusive)', $error->get_error_message() );
} }
/**
* @ticket 51022
*
* @dataProvider data_multiply_of
*
* @param int|float $value
* @param int|float $divisor
* @param bool $expected
*/
public function test_numeric_multiple_of( $value, $divisor, $expected ) {
$schema = array(
'type' => 'number',
'multipleOf' => $divisor,
);
$result = rest_validate_value_from_schema( $value, $schema );
if ( $expected ) {
$this->assertTrue( $result );
} else {
$this->assertWPError( $result );
}
}
public function data_multiply_of() {
return array(
array( 0, 2, true ),
array( 4, 2, true ),
array( 3, 1.5, true ),
array( 2.4, 1.2, true ),
array( 1, 2, false ),
array( 2, 1.5, false ),
array( 2.1, 1.5, false ),
);
}
/** /**
* @ticket 50300 * @ticket 50300
*/ */

View File

@ -46,6 +46,7 @@ class WP_REST_Test_Controller extends WP_REST_Controller {
), ),
'someinteger' => array( 'someinteger' => array(
'type' => 'integer', 'type' => 'integer',
'multipleOf' => 10,
'minimum' => 100, 'minimum' => 100,
'maximum' => 200, 'maximum' => 200,
'exclusiveMinimum' => true, 'exclusiveMinimum' => true,