diff --git a/src/wp-includes/rest-api.php b/src/wp-includes/rest-api.php
index 06bb9f9..bc775f2 100644
a
|
b
|
function rest_validate_value_from_schema( $value, $args, $param = '' ) { |
1051 | 1051 | } |
1052 | 1052 | } |
1053 | 1053 | } |
| 1054 | |
| 1055 | if ( 'object' === $args['type'] ) { |
| 1056 | if ( ! is_array( $value ) ) { |
| 1057 | /* translators: 1: parameter, 2: type name */ |
| 1058 | return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'object' ) ); |
| 1059 | } |
| 1060 | |
| 1061 | foreach ( $value as $property => $v ) { |
| 1062 | if ( ! isset( $args['properties'][ $property ] ) ) { |
| 1063 | continue; |
| 1064 | } |
| 1065 | $is_valid = rest_validate_value_from_schema( $v, $args['properties'][ $property ], $param . '[' . $property . ']' ); |
| 1066 | |
| 1067 | if ( is_wp_error( $is_valid ) ) { |
| 1068 | return $is_valid; |
| 1069 | } |
| 1070 | } |
| 1071 | } |
| 1072 | |
1054 | 1073 | if ( ! empty( $args['enum'] ) ) { |
1055 | 1074 | if ( ! in_array( $value, $args['enum'], true ) ) { |
1056 | 1075 | /* translators: 1: parameter, 2: list of valid values */ |
… |
… |
function rest_sanitize_value_from_schema( $value, $args ) { |
1170 | 1189 | $value = array_values( $value ); |
1171 | 1190 | return $value; |
1172 | 1191 | } |
| 1192 | |
| 1193 | if ( 'object' === $args['type'] ) { |
| 1194 | if ( ! is_array( $value ) ) { |
| 1195 | return array(); |
| 1196 | } |
| 1197 | |
| 1198 | foreach ( $value as $property => $v ) { |
| 1199 | if ( ! isset( $args['properties'][ $property ] ) ) { |
| 1200 | unset( $value[ $property ] ); |
| 1201 | continue; |
| 1202 | } |
| 1203 | $value[ $property ] = rest_sanitize_value_from_schema( $v, $args['properties'][ $property ] ); |
| 1204 | } |
| 1205 | |
| 1206 | return $value; |
| 1207 | } |
| 1208 | |
1173 | 1209 | if ( 'integer' === $args['type'] ) { |
1174 | 1210 | return (int) $value; |
1175 | 1211 | } |
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..ed10181 100644
a
|
b
|
class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { |
391 | 391 | 'context' => array( 'view', 'edit', 'embed' ), |
392 | 392 | 'arg_options' => array( |
393 | 393 | '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() |
394 | 395 | ), |
395 | 396 | 'properties' => array( |
396 | 397 | 'raw' => array( |
… |
… |
class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller { |
413 | 414 | 'context' => array( 'view', 'edit' ), |
414 | 415 | 'arg_options' => array( |
415 | 416 | '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() |
416 | 418 | ), |
417 | 419 | 'properties' => array( |
418 | 420 | 'raw' => array( |
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 810a3fb..415ba8e 100644
a
|
b
|
class WP_REST_Comments_Controller extends WP_REST_Controller { |
1200 | 1200 | 'context' => array( 'view', 'edit', 'embed' ), |
1201 | 1201 | 'arg_options' => array( |
1202 | 1202 | '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() |
1203 | 1204 | ), |
1204 | 1205 | 'properties' => array( |
1205 | 1206 | 'raw' => array( |
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 018b66e..80027cf 100644
a
|
b
|
class WP_REST_Posts_Controller extends WP_REST_Controller { |
1846 | 1846 | 'context' => array( 'view', 'edit', 'embed' ), |
1847 | 1847 | 'arg_options' => array( |
1848 | 1848 | '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() |
1849 | 1850 | ), |
1850 | 1851 | 'properties' => array( |
1851 | 1852 | 'raw' => array( |
… |
… |
class WP_REST_Posts_Controller extends WP_REST_Controller { |
1870 | 1871 | 'context' => array( 'view', 'edit' ), |
1871 | 1872 | 'arg_options' => array( |
1872 | 1873 | '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() |
1873 | 1875 | ), |
1874 | 1876 | 'properties' => array( |
1875 | 1877 | 'raw' => array( |
… |
… |
class WP_REST_Posts_Controller extends WP_REST_Controller { |
1908 | 1910 | 'context' => array( 'view', 'edit', 'embed' ), |
1909 | 1911 | 'arg_options' => array( |
1910 | 1912 | '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() |
1911 | 1914 | ), |
1912 | 1915 | 'properties' => array( |
1913 | 1916 | 'raw' => array( |
diff --git a/tests/phpunit/tests/rest-api/rest-schema-sanitization.php b/tests/phpunit/tests/rest-api/rest-schema-sanitization.php
index e1ae29d..a365d9c 100644
a
|
b
|
class WP_Test_REST_Schema_Sanitization extends WP_UnitTestCase { |
146 | 146 | $this->assertEquals( array( '1', '2' ), rest_sanitize_value_from_schema( array( 'first' => '1', 'second' => '2' ), $schema ) ); |
147 | 147 | } |
148 | 148 | |
| 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 | |
149 | 215 | public function test_type_unknown() { |
150 | 216 | $schema = array( |
151 | 217 | 'type' => 'lalala', |
diff --git a/tests/phpunit/tests/rest-api/rest-schema-validation.php b/tests/phpunit/tests/rest-api/rest-schema-validation.php
index 82f58e5..c47ed10 100644
a
|
b
|
class WP_Test_REST_Schema_Validation extends WP_UnitTestCase { |
181 | 181 | $this->assertWPError( rest_validate_value_from_schema( array( 'first' => '1', 'second' => '2' ), $schema ) ); |
182 | 182 | } |
183 | 183 | |
| 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 | |
184 | 225 | public function test_type_unknown() { |
185 | 226 | $schema = array( |
186 | 227 | 'type' => 'lalala', |