WordPress.org

Make WordPress Core

Changeset 41727


Ignore:
Timestamp:
10/04/2017 08:26:44 AM (22 months ago)
Author:
joehoyle
Message:

REST API: Support for objects in schema validation and sanitization.

When registering routes developers can now define their complex objects in the schema and benefit from the automatic validation and sanitization in the REST API. This also paves the way for support for complex object registration via register_meta and register_setting.

See #38583.
Props TimothyBlynJacobs5.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api.php

    r41238 r41727  
    10521052        }
    10531053    }
     1054
     1055    if ( 'object' === $args['type'] ) {
     1056        if ( $value instanceof stdClass ) {
     1057            $value = (array) $value;
     1058        }
     1059        if ( ! is_array( $value ) ) {
     1060            /* translators: 1: parameter, 2: type name */
     1061            return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'object' ) );
     1062        }
     1063
     1064        foreach ( $value as $property => $v ) {
     1065            if ( ! isset( $args['properties'][ $property ] ) ) {
     1066                continue;
     1067            }
     1068            $is_valid = rest_validate_value_from_schema( $v, $args['properties'][ $property ], $param . '[' . $property . ']' );
     1069
     1070            if ( is_wp_error( $is_valid ) ) {
     1071                return $is_valid;
     1072            }
     1073        }
     1074    }
     1075
    10541076    if ( ! empty( $args['enum'] ) ) {
    10551077        if ( ! in_array( $value, $args['enum'], true ) ) {
     
    11711193        return $value;
    11721194    }
     1195
     1196    if ( 'object' === $args['type'] ) {
     1197        if ( $value instanceof stdClass ) {
     1198            $value = (array) $value;
     1199        }
     1200        if ( ! is_array( $value ) ) {
     1201            return array();
     1202        }
     1203
     1204        foreach ( $value as $property => $v ) {
     1205            if ( ! isset( $args['properties'][ $property ] ) ) {
     1206                unset( $value[ $property ] );
     1207                continue;
     1208            }
     1209            $value[ $property ] = rest_sanitize_value_from_schema( $v, $args['properties'][ $property ] );
     1210        }
     1211
     1212        return $value;
     1213    }
     1214
    11731215    if ( 'integer' === $args['type'] ) {
    11741216        return (int) $value;
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php

    r41162 r41727  
    392392            'arg_options' => array(
    393393                'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     394                'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database()
    394395            ),
    395396            'properties'  => array(
     
    414415            'arg_options' => array(
    415416                'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     417                'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database()
    416418            ),
    417419            'properties'  => array(
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php

    r41588 r41727  
    12011201                    'arg_options'     => array(
    12021202                        'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     1203                        'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database()
    12031204                    ),
    12041205                    'properties'      => array(
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

    r41588 r41727  
    18471847                        'arg_options' => array(
    18481848                            'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     1849                            'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database()
    18491850                        ),
    18501851                        'properties'  => array(
     
    18711872                        'arg_options' => array(
    18721873                            'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     1874                            'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database()
    18731875                        ),
    18741876                        'properties'  => array(
     
    19091911                        'arg_options' => array(
    19101912                            'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     1913                            'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database()
    19111914                        ),
    19121915                        'properties'  => array(
  • trunk/tests/phpunit/tests/rest-api/rest-schema-sanitization.php

    r39296 r41727  
    147147    }
    148148
     149    public function test_type_object() {
     150        $schema = array(
     151            'type'       => 'object',
     152            'properties' => array(
     153                'a' => array(
     154                    'type' => 'number'
     155                ),
     156            ),
     157        );
     158        $this->assertEquals( array( 'a' => 1 ), rest_sanitize_value_from_schema( array( 'a' => 1 ), $schema ) );
     159        $this->assertEquals( array( 'a' => 1 ), rest_sanitize_value_from_schema( array( 'a' => '1' ), $schema ) );
     160    }
     161
     162    public function test_type_object_nested() {
     163        $schema = array(
     164            'type' => 'object',
     165            'properties' => array(
     166                'a' => array(
     167                    'type'  => 'object',
     168                    'properties' => array(
     169                        'b' => array( 'type' => 'number' ),
     170                        'c' => array( 'type' => 'number' ),
     171                    )
     172                )
     173            ),
     174        );
     175
     176        $this->assertEquals(
     177            array(
     178                'a' => array(
     179                    'b' => 1,
     180                    'c' => 3,
     181                ),
     182            ),
     183            rest_sanitize_value_from_schema(
     184                array(
     185                    'a' => array(
     186                        'b' => '1',
     187                        'c' => '3',
     188                    ),
     189                ),
     190                $schema
     191            )
     192        );
     193        $this->assertEquals(
     194            array(
     195                'a' => array(
     196                    'b' => 1,
     197                    'c' => 3,
     198                ),
     199            ),
     200            rest_sanitize_value_from_schema(
     201                array(
     202                    'a' => array(
     203                        'b' => '1',
     204                        'c' => '3',
     205                        'd' => '1',
     206                    ),
     207                    'b' => 1,
     208                ),
     209                $schema
     210            )
     211        );
     212        $this->assertEquals( array( 'a' => array() ), rest_sanitize_value_from_schema( array( 'a' => null ), $schema ) );
     213    }
     214
     215    public function test_type_object_stdclass() {
     216        $schema = array(
     217            'type'       => 'object',
     218            'properties' => array(
     219                'a' => array(
     220                    'type' => 'number'
     221                ),
     222            ),
     223        );
     224        $this->assertEquals( array( 'a' => 1 ), rest_sanitize_value_from_schema( (object) array( 'a' => '1' ), $schema ) );
     225    }
     226
    149227    public function test_type_unknown() {
    150228        $schema = array(
  • trunk/tests/phpunit/tests/rest-api/rest-schema-validation.php

    r39896 r41727  
    182182    }
    183183
     184    public function test_type_object() {
     185        $schema = array(
     186            'type'       => 'object',
     187            'properties' => array(
     188                'a' => array(
     189                    'type' => 'number'
     190                ),
     191            ),
     192        );
     193        $this->assertTrue( rest_validate_value_from_schema( array( 'a' => 1 ), $schema ) );
     194        $this->assertWPError( rest_validate_value_from_schema( array( 'a' => 'invalid' ), $schema ) );
     195    }
     196
     197    public function test_type_object_nested() {
     198        $schema = array(
     199            'type' => 'object',
     200            'properties' => array(
     201                'a' => array(
     202                    'type'  => 'object',
     203                    'properties' => array(
     204                        'b' => array( 'type' => 'number' ),
     205                        'c' => array( 'type' => 'number' ),
     206                    )
     207                )
     208            ),
     209        );
     210        $this->assertTrue(
     211            rest_validate_value_from_schema(
     212                array(
     213                    'a' => array(
     214                        'b' => '1',
     215                        'c' => 3,
     216                    ),
     217                ),
     218                $schema
     219            )
     220        );
     221        $this->assertWPError( rest_validate_value_from_schema( array( 'a' => array( 'b' => 1, 'c' => 'invalid' ) ), $schema ) );
     222        $this->assertWPError( rest_validate_value_from_schema( array( 'a' => 1 ), $schema ) );
     223    }
     224
     225    public function test_type_object_stdclass() {
     226        $schema = array(
     227            'type'       => 'object',
     228            'properties' => array(
     229                'a' => array(
     230                    'type' => 'number'
     231                ),
     232            ),
     233        );
     234        $this->assertTrue( rest_validate_value_from_schema( (object) array( 'a' => 1 ), $schema ) );
     235    }
     236
    184237    public function test_type_unknown() {
    185238        $schema = array(
Note: See TracChangeset for help on using the changeset viewer.