Skip to content

Commit 8871bf0

Browse files
fixes
1 parent ea139cb commit 8871bf0

File tree

2 files changed

+77
-4
lines changed

2 files changed

+77
-4
lines changed

src/wp-includes/rest-api/endpoints/class-wp-rest-abilities-v1-list-controller.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,14 @@ private function normalize_schema_empty_object_defaults( array $schema ): array
215215
return $schema;
216216
}
217217

218+
/**
219+
* WordPress-internal schema keywords to strip from REST responses.
220+
*
221+
* @since 6.9.0
222+
* @var array<int, string>
223+
*/
224+
private const INTERNAL_SCHEMA_KEYWORDS = array( 'sanitize_callback', 'validate_callback', 'arg_options' );
225+
218226
/**
219227
* Recursively removes WordPress-internal keywords from a schema.
220228
*
@@ -228,13 +236,14 @@ private function normalize_schema_empty_object_defaults( array $schema ): array
228236
* @param array<string, mixed> $schema The schema array.
229237
* @return array<string, mixed> The schema without WordPress-internal keywords.
230238
*/
231-
private const INTERNAL_SCHEMA_KEYWORDS = array( 'sanitize_callback', 'validate_callback', 'arg_options' );
232-
233239
private function strip_internal_schema_keywords( array $schema ): array {
234240
$schema = array_diff_key( $schema, array_flip( self::INTERNAL_SCHEMA_KEYWORDS ) );
235241

236242
// Sub-schema maps: keys are user-defined, values are sub-schemas.
237-
foreach ( array( 'properties', 'patternProperties', 'definitions' ) as $keyword ) {
243+
// Note: 'dependencies' values can also be property-dependency arrays
244+
// (numeric arrays of strings), which is_array() will pass through
245+
// harmlessly since array_diff_key won't match any denylist keys.
246+
foreach ( array( 'properties', 'patternProperties', 'definitions', 'dependencies' ) as $keyword ) {
238247
if ( isset( $schema[ $keyword ] ) && is_array( $schema[ $keyword ] ) ) {
239248
foreach ( $schema[ $keyword ] as $key => $child_schema ) {
240249
if ( is_array( $child_schema ) ) {

tests/phpunit/tests/rest-api/wpRestAbilitiesV1ListController.php

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ public function test_internal_schema_keywords_stripped_from_nested_sub_schemas()
849849
'test/nested-internal-keywords',
850850
array(
851851
'label' => 'Test Nested Keywords',
852-
'description' => 'Tests stripping from items, anyOf, and additionalProperties',
852+
'description' => 'Tests stripping from all sub-schema locations',
853853
'category' => 'general',
854854
'input_schema' => array(
855855
'type' => 'object',
@@ -869,6 +869,41 @@ public function test_internal_schema_keywords_stripped_from_nested_sub_schemas()
869869
'arg_options' => array( 'sanitize_callback' => 'absint' ),
870870
),
871871
),
872+
'oneOf' => array(
873+
array(
874+
'type' => 'string',
875+
'sanitize_callback' => 'sanitize_text_field',
876+
),
877+
),
878+
'allOf' => array(
879+
array(
880+
'type' => 'object',
881+
'validate_callback' => 'rest_validate_request_arg',
882+
),
883+
),
884+
'not' => array(
885+
'type' => 'null',
886+
'arg_options' => array( 'sanitize_callback' => 'absint' ),
887+
),
888+
'patternProperties' => array(
889+
'^S_' => array(
890+
'type' => 'string',
891+
'sanitize_callback' => 'sanitize_text_field',
892+
),
893+
),
894+
'dependencies' => array(
895+
'bar' => array(
896+
'type' => 'object',
897+
'validate_callback' => 'rest_validate_request_arg',
898+
'properties' => array(
899+
'baz' => array(
900+
'type' => 'string',
901+
'sanitize_callback' => 'sanitize_text_field',
902+
),
903+
),
904+
),
905+
'qux' => array( 'bar' ),
906+
),
872907
'additionalProperties' => array(
873908
'type' => 'string',
874909
'sanitize_callback' => 'sanitize_text_field',
@@ -905,6 +940,35 @@ public function test_internal_schema_keywords_stripped_from_nested_sub_schemas()
905940
$this->assertArrayNotHasKey( 'arg_options', $data['input_schema']['anyOf'][1] );
906941
$this->assertSame( 'number', $data['input_schema']['anyOf'][1]['type'] );
907942

943+
// Verify internal keywords are stripped from oneOf sub-schemas.
944+
$this->assertArrayHasKey( 'oneOf', $data['input_schema'] );
945+
$this->assertArrayNotHasKey( 'sanitize_callback', $data['input_schema']['oneOf'][0] );
946+
$this->assertSame( 'string', $data['input_schema']['oneOf'][0]['type'] );
947+
948+
// Verify internal keywords are stripped from allOf sub-schemas.
949+
$this->assertArrayHasKey( 'allOf', $data['input_schema'] );
950+
$this->assertArrayNotHasKey( 'validate_callback', $data['input_schema']['allOf'][0] );
951+
$this->assertSame( 'object', $data['input_schema']['allOf'][0]['type'] );
952+
953+
// Verify internal keywords are stripped from not sub-schema.
954+
$this->assertArrayHasKey( 'not', $data['input_schema'] );
955+
$this->assertArrayNotHasKey( 'arg_options', $data['input_schema']['not'] );
956+
$this->assertSame( 'null', $data['input_schema']['not']['type'] );
957+
958+
// Verify internal keywords are stripped from patternProperties sub-schemas.
959+
$this->assertArrayHasKey( 'patternProperties', $data['input_schema'] );
960+
$this->assertArrayNotHasKey( 'sanitize_callback', $data['input_schema']['patternProperties']['^S_'] );
961+
$this->assertSame( 'string', $data['input_schema']['patternProperties']['^S_']['type'] );
962+
963+
// Verify internal keywords are stripped from dependencies schema values.
964+
$this->assertArrayHasKey( 'dependencies', $data['input_schema'] );
965+
$this->assertArrayNotHasKey( 'validate_callback', $data['input_schema']['dependencies']['bar'] );
966+
$this->assertSame( 'object', $data['input_schema']['dependencies']['bar']['type'] );
967+
$this->assertArrayNotHasKey( 'sanitize_callback', $data['input_schema']['dependencies']['bar']['properties']['baz'] );
968+
$this->assertSame( 'string', $data['input_schema']['dependencies']['bar']['properties']['baz']['type'] );
969+
// Property dependencies (numeric arrays) should pass through unchanged.
970+
$this->assertSame( array( 'bar' ), $data['input_schema']['dependencies']['qux'] );
971+
908972
// Verify internal keywords are stripped from additionalProperties sub-schema.
909973
$this->assertArrayHasKey( 'additionalProperties', $data['input_schema'] );
910974
$this->assertArrayNotHasKey( 'sanitize_callback', $data['input_schema']['additionalProperties'] );

0 commit comments

Comments
 (0)