WordPress.org

Make WordPress Core

Ticket #38583: 38583.1.diff

File 38583.1.diff, 13.0 KB (added by TimothyBlynJacobs, 2 years ago)
  • src/wp-includes/rest-api.php

    diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php
    index 06bb9f9..a556a39 100644
    a b function rest_get_avatar_sizes() { 
    10361036 * @return true|WP_Error
    10371037 */
    10381038function rest_validate_value_from_schema( $value, $args, $param = '' ) {
     1039
     1040        if ( $args === true ) {
     1041                return true;
     1042        }
     1043
     1044        if ( $args === false ) {
     1045                return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not allowed.' ), $param ) );
     1046        }
     1047
    10391048        if ( 'array' === $args['type'] ) {
    10401049                if ( ! is_array( $value ) ) {
    10411050                        $value = preg_split( '/[\s,]+/', $value );
    function rest_validate_value_from_schema( $value, $args, $param = '' ) { 
    10511060                        }
    10521061                }
    10531062        }
     1063
     1064        if ( 'object' === $args['type'] ) {
     1065                if ( ! is_array( $value ) ) {
     1066                        /* translators: 1: parameter, 2: type name */
     1067                        return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'object' ) );
     1068                }
     1069
     1070                // How to validate properties that are not registered.
     1071                $additional = isset( $args['additionalProperties'] ) ? $args['additionalProperties'] : true;
     1072
     1073                foreach ( $value as $property => $v ) {
     1074
     1075                        $validate = isset( $args['properties'][ $property ] ) ? $args['properties'][ $property ] : $additional;
     1076                        $is_valid = rest_validate_value_from_schema( $v, $validate, $param . '[' . $property . ']' );
     1077
     1078                        if ( is_wp_error( $is_valid ) ) {
     1079                                return $is_valid;
     1080                        }
     1081                }
     1082        }
     1083
    10541084        if ( ! empty( $args['enum'] ) ) {
    10551085                if ( ! in_array( $value, $args['enum'], true ) ) {
    10561086                        /* translators: 1: parameter, 2: list of valid values */
    function rest_sanitize_value_from_schema( $value, $args ) { 
    11701200                $value = array_values( $value );
    11711201                return $value;
    11721202        }
     1203
     1204        if ( 'object' === $args['type'] ) {
     1205                if ( ! is_array( $value ) ) {
     1206                        return array();
     1207                }
     1208
     1209                // How to sanitize properties that are not registered.
     1210                $additional = isset( $args['additionalProperties'] ) ? $args['additionalProperties'] : true;
     1211
     1212                foreach ( $value as $property => $v ) {
     1213                        $sanitize = isset( $args['properties'][ $property ] ) ? $args['properties'][ $property ] : $additional;
     1214                        $value[ $property ] = is_bool( $sanitize ) ? $v : rest_sanitize_value_from_schema( $v, $sanitize );
     1215                }
     1216
     1217                return $value;
     1218        }
     1219
    11731220        if ( 'integer' === $args['type'] ) {
    11741221                return (int) $value;
    11751222        }
  • src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php
    index 76802fe..5a2aeb3 100644
    a b class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { 
    391391                        'context'     => array( 'view', 'edit', 'embed' ),
    392392                        'arg_options' => array(
    393393                                'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     394                                'validate_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
    394395                        ),
    395396                        'properties'  => array(
    396397                                'raw' => array(
    class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { 
    413414                        'context'     => array( 'view', 'edit' ),
    414415                        'arg_options' => array(
    415416                                'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     417                                'validate_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
    416418                        ),
    417419                        'properties'  => array(
    418420                                'raw' => array(
  • src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php
    index e91fce2..aadeac9 100644
    a b class WP_REST_Comments_Controller extends WP_REST_Controller { 
    11991199                                        'context'         => array( 'view', 'edit', 'embed' ),
    12001200                                        'arg_options'     => array(
    12011201                                                'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     1202                                                'validate_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
    12021203                                        ),
    12031204                                        'properties'      => array(
    12041205                                                'raw'         => array(
  • src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

    diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
    index f9de736..99464c8 100644
    a b class WP_REST_Posts_Controller extends WP_REST_Controller { 
    18451845                                                'context'     => array( 'view', 'edit', 'embed' ),
    18461846                                                'arg_options' => array(
    18471847                                                        'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     1848                                                        'validate_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
    18481849                                                ),
    18491850                                                'properties'  => array(
    18501851                                                        'raw' => array(
    class WP_REST_Posts_Controller extends WP_REST_Controller { 
    18691870                                                'context'     => array( 'view', 'edit' ),
    18701871                                                'arg_options' => array(
    18711872                                                        'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     1873                                                        'validate_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
    18721874                                                ),
    18731875                                                'properties'  => array(
    18741876                                                        'raw' => array(
    class WP_REST_Posts_Controller extends WP_REST_Controller { 
    19071909                                                'context'     => array( 'view', 'edit', 'embed' ),
    19081910                                                'arg_options' => array(
    19091911                                                        'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
     1912                                                        'validate_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database()
    19101913                                                ),
    19111914                                                'properties'  => array(
    19121915                                                        'raw' => array(
  • tests/phpunit/tests/rest-api/rest-schema-sanitization.php

    diff --git a/tests/phpunit/tests/rest-api/rest-schema-sanitization.php b/tests/phpunit/tests/rest-api/rest-schema-sanitization.php
    index e1ae29d..1684e03 100644
    a b class WP_Test_REST_Schema_Sanitization extends WP_UnitTestCase { 
    146146                $this->assertEquals( array( '1', '2' ), rest_sanitize_value_from_schema( array( 'first' => '1', 'second' => '2' ), $schema ) );
    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_additionalProperties_not_set() {
     163                $schema = array(
     164                        'type'       => 'object',
     165                        'properties' => array(
     166                                'a' => array(
     167                                        'type' => 'number'
     168                                ),
     169                        ),
     170                );
     171                $this->assertEquals( array( 'a' => 1 ), rest_sanitize_value_from_schema( array( 'a' => 1 ), $schema ) );
     172                $this->assertEquals( array( 'b' => '1' ), rest_sanitize_value_from_schema( array( 'b' => '1' ), $schema ) );
     173        }
     174
     175        public function test_type_object_additionalProperties_true() {
     176                $schema = array(
     177                        'type'       => 'object',
     178                        'properties' => array(
     179                                'a' => array(
     180                                        'type' => 'number'
     181                                ),
     182                        ),
     183                        'additionalProperties' => true,
     184                );
     185                $this->assertEquals( array( 'a' => 1 ), rest_sanitize_value_from_schema( array( 'a' => 1 ), $schema ) );
     186                $this->assertEquals( array( 'b' => '1' ), rest_sanitize_value_from_schema( array( 'b' => '1' ), $schema ) );
     187        }
     188
     189        public function test_type_object_additionalProperties_false() {
     190                $schema = array(
     191                        'type'       => 'object',
     192                        'properties' => array(
     193                                'a' => array(
     194                                        'type' => 'number'
     195                                ),
     196                        ),
     197                        'additionalProperties' => false,
     198                );
     199                $this->assertEquals( array( 'a' => 1 ), rest_sanitize_value_from_schema( array( 'a' => 1 ), $schema ) );
     200                $this->assertEquals( array( 'b' => '1' ), rest_sanitize_value_from_schema( array( 'b' => '1' ), $schema ) );
     201        }
     202
     203        public function test_type_object_additionalProperties_schema() {
     204                $schema = array(
     205                        'type'       => 'object',
     206                        'properties' => array(
     207                                'a' => array(
     208                                        'type' => 'number'
     209                                ),
     210                        ),
     211                        'additionalProperties' => array(
     212                                'type' => 'boolean'
     213                        ),
     214                );
     215                $this->assertEquals( array( 'a' => 1 ), rest_sanitize_value_from_schema( array( 'a' => 1 ), $schema ) );
     216                $this->assertEquals( array( 'b' => true ), rest_sanitize_value_from_schema( array( 'b' => '1' ), $schema ) );
     217                $this->assertEquals( array( 'b' => true ), rest_sanitize_value_from_schema( array( 'b' => true ), $schema ) );
     218                $this->assertEquals( array( 'b' => false ), rest_sanitize_value_from_schema( array( 'b' => 'false' ), $schema ) );
     219        }
     220
     221        public function test_type_object_nested() {
     222                $schema = array(
     223                        'type' => 'object',
     224                        'properties' => array(
     225                                'a' => array(
     226                                        'type'  => 'object',
     227                                        'properties' => array(
     228                                                'b' => array( 'type' => 'number' ),
     229                                                'c' => array( 'type' => 'number' ),
     230                                        )
     231                                )
     232                        ),
     233                );
     234
     235                $this->assertEquals(
     236                        array( 'a' => array( 'b' => 1, 'c' => 3 ) ),
     237                        rest_sanitize_value_from_schema( array( 'a' => array( 'b' => '1', 'c' => '3' ) ), $schema )
     238                );
     239                $this->assertEquals(
     240                        array( 'a' => array( 'b' => 1, 'c' => 3, 'd' => '1' ), 'b' => '1' ),
     241                        rest_sanitize_value_from_schema( array( 'a' => array( 'b' => '1', 'c' => '3', 'd' => '1' ), 'b' => 1 ), $schema )
     242                );
     243                $this->assertEquals( array( 'a' => array() ), rest_sanitize_value_from_schema( array( 'a' => null ), $schema ) );
     244        }
     245
    149246        public function test_type_unknown() {
    150247                $schema = array(
    151248                        'type' => 'lalala',
  • tests/phpunit/tests/rest-api/rest-schema-validation.php

    diff --git a/tests/phpunit/tests/rest-api/rest-schema-validation.php b/tests/phpunit/tests/rest-api/rest-schema-validation.php
    index 82f58e5..e610592 100644
    a b class WP_Test_REST_Schema_Validation extends WP_UnitTestCase { 
    181181                $this->assertWPError( rest_validate_value_from_schema( array( 'first' => '1', 'second' => '2' ), $schema ) );
    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_additionalProperties_not_set() {
     198                $schema = array(
     199                        'type'       => 'object',
     200                        'properties' => array(
     201                                'a' => array(
     202                                        'type' => 'number'
     203                                ),
     204                        ),
     205                );
     206                $this->assertTrue( rest_validate_value_from_schema( array( 'b' => 1 ), $schema ) );
     207        }
     208
     209        public function test_type_object_additionalProperties_true() {
     210                $schema = array(
     211                        'type'       => 'object',
     212                        'properties' => array(
     213                                'a' => array(
     214                                        'type' => 'number'
     215                                ),
     216                        ),
     217                        'additionalProperties' => true,
     218                );
     219                $this->assertTrue( rest_validate_value_from_schema( array( 'a' => 1 ), $schema ) );
     220                $this->assertTrue( rest_validate_value_from_schema( array( 'b' => 1 ), $schema ) );
     221        }
     222
     223        public function test_type_object_additionalProperties_false() {
     224                $schema = array(
     225                        'type'       => 'object',
     226                        'properties' => array(
     227                                'a' => array(
     228                                        'type' => 'number'
     229                                ),
     230                        ),
     231                        'additionalProperties' => false,
     232                );
     233                $this->assertTrue( rest_validate_value_from_schema( array( 'a' => 1 ), $schema ) );
     234                $this->assertWPError( rest_validate_value_from_schema( array( 'b' => 1 ), $schema ) );
     235        }
     236
     237        public function test_type_object_additionalProperties_schema() {
     238                $schema = array(
     239                        'type'       => 'object',
     240                        'properties' => array(
     241                                'a' => array(
     242                                        'type' => 'number'
     243                                ),
     244                        ),
     245                        'additionalProperties' => array(
     246                                'type' => 'boolean'
     247                        ),
     248                );
     249                $this->assertTrue( rest_validate_value_from_schema( array( 'a' => 1 ), $schema ) );
     250                $this->assertTrue( rest_validate_value_from_schema( array( 'b' => true ), $schema ) );
     251                $this->assertWPError( rest_validate_value_from_schema( array( 'b' => 'invalid' ), $schema ) );
     252        }
     253
     254        public function test_type_object_nested() {
     255                $schema = array(
     256                        'type' => 'object',
     257                        'properties' => array(
     258                                'a' => array(
     259                                        'type'  => 'object',
     260                                        'properties' => array(
     261                                                'b' => array( 'type' => 'number' ),
     262                                                'c' => array( 'type' => 'number' ),
     263                                        )
     264                                )
     265                        ),
     266                );
     267                $this->assertTrue( rest_validate_value_from_schema( array( 'a' => array( 'b' => 1, 'c' => 3 ) ), $schema ) );
     268                $this->assertWPError( rest_validate_value_from_schema( array( 'a' => array( 'b' => 1, 'c' => 'invalid' ) ), $schema ) );
     269                $this->assertWPError( rest_validate_value_from_schema( array( 'a' => 1 ), $schema ) );
     270        }
     271
    184272        public function test_type_unknown() {
    185273                $schema = array(
    186274                        'type'  => 'lalala',