Make WordPress Core


Ignore:
Timestamp:
07/05/2020 12:13:37 AM (4 years ago)
Author:
TimothyBlynJacobs
Message:

REST API: Make multi-typed schemas more robust.

A multi-type schema is a schema where the type keyword is an array of possible types instead of a single type. For instance, [ 'object', 'string' ] would allow objects or string values.

In [46249] basic support for these schemas was introduced. The validator would loop over each schema type trying to find a version that matched. This worked for valid values, but for invalid values it provided unhelpful error messages. The sanitizer also had its utility restricted.

In this commit, the validators and sanitizers will first determine the best type of the passed value and then apply the schema with that set type. In the case that a value could match multiple types, the schema of the first matching type will be used.

To maintain backward compatibility, if unsupported schema types are used, the value will always pass validation. A doing it wrong notice is issued in this case.

Fixes #50300.
Props pentatonicfunk, dlh, TimothyBlynJacobs.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/rest-api/rest-schema-validation.php

    r48300 r48306  
    388388        $this->assertTrue( rest_validate_value_from_schema( null, $schema ) );
    389389        $this->assertTrue( rest_validate_value_from_schema( '2019-09-19T18:00:00', $schema ) );
    390         $this->assertWPError( rest_validate_value_from_schema( 'some random string', $schema ) );
     390
     391        $error = rest_validate_value_from_schema( 'some random string', $schema );
     392        $this->assertWPError( $error );
     393        $this->assertEquals( 'Invalid date.', $error->get_error_message() );
    391394    }
    392395
     
    403406        $this->assertTrue( rest_validate_value_from_schema( 'My Value', $schema ) );
    404407        $this->assertTrue( rest_validate_value_from_schema( array( 'raw' => 'My Value' ), $schema ) );
    405         $this->assertWPError( rest_validate_value_from_schema( array( 'raw' => array( 'a list' ) ), $schema ) );
     408
     409        $error = rest_validate_value_from_schema( array( 'raw' => array( 'a list' ) ), $schema );
     410        $this->assertWPError( $error );
     411        $this->assertEquals( '[raw] is not of type string.', $error->get_error_message() );
     412    }
     413
     414    /**
     415     * @ticket 50300
     416     */
     417    public function test_null_or_integer() {
     418        $schema = array(
     419            'type'    => array( 'null', 'integer' ),
     420            'minimum' => 10,
     421            'maximum' => 20,
     422        );
     423
     424        $this->assertTrue( rest_validate_value_from_schema( null, $schema ) );
     425        $this->assertTrue( rest_validate_value_from_schema( 15, $schema ) );
     426        $this->assertTrue( rest_validate_value_from_schema( '15', $schema ) );
     427
     428        $error = rest_validate_value_from_schema( 30, $schema, 'param' );
     429        $this->assertWPError( $error );
     430        $this->assertEquals( 'param must be between 10 (inclusive) and 20 (inclusive)', $error->get_error_message() );
     431    }
     432
     433    /**
     434     * @ticket 50300
     435     */
     436    public function test_multi_type_with_no_known_types() {
     437        $this->setExpectedIncorrectUsage( 'rest_handle_multi_type_schema' );
     438        $this->setExpectedIncorrectUsage( 'rest_validate_value_from_schema' );
     439
     440        $schema = array(
     441            'type' => array( 'invalid', 'type' ),
     442        );
     443
     444        $this->assertTrue( rest_validate_value_from_schema( 'My Value', $schema ) );
     445    }
     446
     447    /**
     448     * @ticket 50300
     449     */
     450    public function test_multi_type_with_some_unknown_types() {
     451        $this->setExpectedIncorrectUsage( 'rest_handle_multi_type_schema' );
     452        $this->setExpectedIncorrectUsage( 'rest_validate_value_from_schema' );
     453
     454        $schema = array(
     455            'type' => array( 'object', 'type' ),
     456        );
     457
     458        $this->assertTrue( rest_validate_value_from_schema( 'My Value', $schema ) );
    406459    }
    407460
Note: See TracChangeset for help on using the changeset viewer.