From 82c76faedc99549843f10509e16d22c566ed64a6 Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Sun, 14 Sep 2025 12:58:52 -0600 Subject: [PATCH 01/24] Comments REST endpoint - support for multiple status values --- .../rest-api/endpoints/class-wp-rest-comments-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a0b68759f9942..7a3824ca7080e 100644 --- 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 @@ -1681,7 +1681,7 @@ public function get_collection_params() { 'default' => 'approve', 'description' => __( 'Limit result set to comments assigned a specific status. Requires authorization.' ), 'sanitize_callback' => 'sanitize_key', - 'type' => 'string', + 'type' => array( 'string', 'array' ), 'validate_callback' => 'rest_validate_request_arg', ); From 1fc983f88631c0b0d119265f5cd09c836f5e8424 Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Sun, 14 Sep 2025 13:59:14 -0600 Subject: [PATCH 02/24] =?UTF-8?q?Add=20tests=20for=20getting=20comments=20?= =?UTF-8?q?by=20status,=20statuses=20or=20=E2=80=98all=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rest-api/rest-comments-controller.php | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index 0bfe4e778d870..ada28ab985dd6 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -119,6 +119,7 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { array( 'comment_content' => "Comment {$i}", 'comment_post_ID' => self::$post_id, + 'status' => ( rand( 0, 100 ) % 2 === 0 ) ? 'approve' : 'hold', ) ); } @@ -224,6 +225,70 @@ public function test_get_items() { $this->assertCount( self::$total_comments, $comments ); } + /** + * Test getting items of a specific status. + */ + public function test_get_items_by_status() { + $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); + $request->set_param( 'status', 'approve' ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 200, $response->get_status() ); + + $q = new WP_Comment_Query(); + $found = $q->query( + array( + 'status' => 'approve', + ) + ); + + $comments = $response->get_data(); + $this->assertCount( $found, $comments ); + } + + /** + * Test getting comments of all statuses. + */ + public function test_get_items_by_all_status() { + $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); + $request->set_param( 'status', 'all' ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 200, $response->get_status() ); + + $q = new WP_Comment_Query(); + $found = $q->query( + array( + 'status' => 'all', + ) + ); + + $comments = $response->get_data(); + $this->assertCount( $found, $comments ); + } + + /** + * Test getting items of multiple statuses. + */ + public function test_get_items_by_multiple_status() { + $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); + $request->set_param( 'status', array( 'approve', 'hold' ) ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 200, $response->get_status() ); + + $q = new WP_Comment_Query(); + $found = $q->query( + array( + 'status' => array( 'approve', 'hold' ), + ) + ); + + $comments = $response->get_data(); + $this->assertCount( $found, $comments ); + + } + /** * @ticket 38692 */ From 4ee6fe84ae2ae6b67cbd81e897d92d10180cc314 Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Sun, 14 Sep 2025 14:00:38 -0600 Subject: [PATCH 03/24] spacing fixes for linter --- tests/phpunit/tests/rest-api/rest-comments-controller.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index ada28ab985dd6..70aff9a1345bc 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -235,7 +235,7 @@ public function test_get_items_by_status() { $response = rest_get_server()->dispatch( $request ); $this->assertSame( 200, $response->get_status() ); - $q = new WP_Comment_Query(); + $q = new WP_Comment_Query(); $found = $q->query( array( 'status' => 'approve', @@ -256,7 +256,7 @@ public function test_get_items_by_all_status() { $response = rest_get_server()->dispatch( $request ); $this->assertSame( 200, $response->get_status() ); - $q = new WP_Comment_Query(); + $q = new WP_Comment_Query(); $found = $q->query( array( 'status' => 'all', @@ -277,7 +277,7 @@ public function test_get_items_by_multiple_status() { $response = rest_get_server()->dispatch( $request ); $this->assertSame( 200, $response->get_status() ); - $q = new WP_Comment_Query(); + $q = new WP_Comment_Query(); $found = $q->query( array( 'status' => array( 'approve', 'hold' ), @@ -286,7 +286,6 @@ public function test_get_items_by_multiple_status() { $comments = $response->get_data(); $this->assertCount( $found, $comments ); - } /** From bdd5a6d8204b6cddb1b3fefde25a95568d5cf16c Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Sun, 14 Sep 2025 14:13:10 -0600 Subject: [PATCH 04/24] Use count --- .../phpunit/tests/rest-api/rest-comments-controller.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index 70aff9a1345bc..7da163d73503d 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -227,6 +227,8 @@ public function test_get_items() { /** * Test getting items of a specific status. + * + * @ticket 99999 */ public function test_get_items_by_status() { $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); @@ -239,6 +241,7 @@ public function test_get_items_by_status() { $found = $q->query( array( 'status' => 'approve', + 'count' => true, ) ); @@ -248,6 +251,8 @@ public function test_get_items_by_status() { /** * Test getting comments of all statuses. + * + * @ticket 99999 */ public function test_get_items_by_all_status() { $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); @@ -260,6 +265,7 @@ public function test_get_items_by_all_status() { $found = $q->query( array( 'status' => 'all', + 'count' => true, ) ); @@ -269,6 +275,8 @@ public function test_get_items_by_all_status() { /** * Test getting items of multiple statuses. + * + * @ticket 99999 */ public function test_get_items_by_multiple_status() { $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); @@ -281,6 +289,7 @@ public function test_get_items_by_multiple_status() { $found = $q->query( array( 'status' => array( 'approve', 'hold' ), + 'count' => true, ) ); From b878d8be612f1c6b478a89bff044dddb4abca058 Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Sun, 14 Sep 2025 23:15:01 -0600 Subject: [PATCH 05/24] Complete tests for status field --- .../rest-api/rest-comments-controller.php | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index 7da163d73503d..a87106342f45b 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -227,14 +227,15 @@ public function test_get_items() { /** * Test getting items of a specific status. - * - * @ticket 99999 */ public function test_get_items_by_status() { + wp_set_current_user( self::$admin_id ); + $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); $request->set_param( 'status', 'approve' ); - + $request->set_param( 'per_page', self::$per_page ); $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 200, $response->get_status() ); $q = new WP_Comment_Query(); @@ -246,19 +247,21 @@ public function test_get_items_by_status() { ); $comments = $response->get_data(); + $this->assertCount( $found, $comments ); } /** * Test getting comments of all statuses. - * - * @ticket 99999 */ public function test_get_items_by_all_status() { + wp_set_current_user( self::$admin_id ); + $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); $request->set_param( 'status', 'all' ); - + $request->set_param( 'per_page', self::$per_page ); $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 200, $response->get_status() ); $q = new WP_Comment_Query(); @@ -275,12 +278,13 @@ public function test_get_items_by_all_status() { /** * Test getting items of multiple statuses. - * - * @ticket 99999 */ public function test_get_items_by_multiple_status() { + wp_set_current_user( self::$admin_id ); + $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); $request->set_param( 'status', array( 'approve', 'hold' ) ); + $request->set_param( 'per_page', self::$per_page ); $response = rest_get_server()->dispatch( $request ); $this->assertSame( 200, $response->get_status() ); From f435d93c1d813ec0e39dc472037c7591bbdc9b2b Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Sun, 14 Sep 2025 23:32:51 -0600 Subject: [PATCH 06/24] update wp-api-generated --- tests/qunit/fixtures/wp-api-generated.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 6626758a8a9dc..bc5048a232504 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -10335,7 +10335,10 @@ mockedApiResponse.Schema = { "status": { "default": "approve", "description": "Limit result set to comments assigned a specific status. Requires authorization.", - "type": "string", + "type": [ + "string", + "array" + ], "required": false }, "type": { From 7b22c3915459576233a10ae05147902ca0200268 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Mon, 15 Sep 2025 08:44:06 -0600 Subject: [PATCH 07/24] Update tests/phpunit/tests/rest-api/rest-comments-controller.php Co-authored-by: Pascal Birchler --- tests/phpunit/tests/rest-api/rest-comments-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index a87106342f45b..462e0efd5f32d 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -119,7 +119,7 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { array( 'comment_content' => "Comment {$i}", 'comment_post_ID' => self::$post_id, - 'status' => ( rand( 0, 100 ) % 2 === 0 ) ? 'approve' : 'hold', + 'status' => ( $i % 2 === 0 ) ? 'approve' : 'hold', ) ); } From 6225ae603f99f6b0d88a9f933bc0adee3e355a0b Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Mon, 15 Sep 2025 08:47:17 -0600 Subject: [PATCH 08/24] hello yoda my old friend --- tests/phpunit/tests/rest-api/rest-comments-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index 462e0efd5f32d..f826fefbe4ebf 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -119,7 +119,7 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { array( 'comment_content' => "Comment {$i}", 'comment_post_ID' => self::$post_id, - 'status' => ( $i % 2 === 0 ) ? 'approve' : 'hold', + 'status' => ( 0 === $i % 2 ) ? 'approve' : 'hold', ) ); } From f121b3e3d930f221e5324168a75f28c0e23acaef Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Mon, 15 Sep 2025 15:26:44 -0600 Subject: [PATCH 09/24] API handles strings automatically when array type given --- .../rest-api/endpoints/class-wp-rest-comments-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7a3824ca7080e..13cd7c139f499 100644 --- 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 @@ -1681,7 +1681,7 @@ public function get_collection_params() { 'default' => 'approve', 'description' => __( 'Limit result set to comments assigned a specific status. Requires authorization.' ), 'sanitize_callback' => 'sanitize_key', - 'type' => array( 'string', 'array' ), + 'type' => 'array', 'validate_callback' => 'rest_validate_request_arg', ); From 5fba5f6031f335b9fdee23a1e2e7ac74e1292d8e Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Mon, 15 Sep 2025 15:36:18 -0600 Subject: [PATCH 10/24] Handle multiple status sanitization --- .../class-wp-rest-comments-controller.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) 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 13cd7c139f499..871856c0190e9 100644 --- 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 @@ -1680,7 +1680,7 @@ public function get_collection_params() { $query_params['status'] = array( 'default' => 'approve', 'description' => __( 'Limit result set to comments assigned a specific status. Requires authorization.' ), - 'sanitize_callback' => 'sanitize_key', + 'sanitize_callback' => 'sanitize_comment_statuses', 'type' => 'array', 'validate_callback' => 'rest_validate_request_arg', ); @@ -1928,4 +1928,16 @@ protected function check_is_comment_content_allowed( $prepared_comment ) { */ return '' !== $check['comment_content']; } + + /** + * Sanitize a single comment status or a list of comment statuses with `sanitize_key`. + * + * @since 6.8.0 + * @param string|array $statuses Comment status or array of comment statuses. + * @return array Sanitized array of comment statuses. + */ + public function sanitize_comment_statuses( $statuses ) { + $statuses = wp_parse_list( $statuses ); + return array_unique( array_map( 'sanitize_key', $statuses ) ); + } } From 1ee7a86641699fcc8808ae8d9ee656ef07057253 Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Mon, 15 Sep 2025 16:59:58 -0600 Subject: [PATCH 11/24] Add additional tests --- .../class-wp-rest-comments-controller.php | 2 +- .../rest-api/rest-comments-controller.php | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) 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 871856c0190e9..b33ef539505d7 100644 --- 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 @@ -1680,7 +1680,7 @@ public function get_collection_params() { $query_params['status'] = array( 'default' => 'approve', 'description' => __( 'Limit result set to comments assigned a specific status. Requires authorization.' ), - 'sanitize_callback' => 'sanitize_comment_statuses', + 'sanitize_callback' => array( $this, 'sanitize_comment_statuses' ), 'type' => 'array', 'validate_callback' => 'rest_validate_request_arg', ); diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index f826fefbe4ebf..44df920a4cd2a 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -227,6 +227,8 @@ public function test_get_items() { /** * Test getting items of a specific status. + * + * @ticket 63982 */ public function test_get_items_by_status() { wp_set_current_user( self::$admin_id ); @@ -253,6 +255,8 @@ public function test_get_items_by_status() { /** * Test getting comments of all statuses. + * + * @ticket 63982 */ public function test_get_items_by_all_status() { wp_set_current_user( self::$admin_id ); @@ -278,6 +282,8 @@ public function test_get_items_by_all_status() { /** * Test getting items of multiple statuses. + * + * @ticket 63982 */ public function test_get_items_by_multiple_status() { wp_set_current_user( self::$admin_id ); @@ -301,6 +307,69 @@ public function test_get_items_by_multiple_status() { $this->assertCount( $found, $comments ); } + /** + * Test sanization of the status parameter. + * + * @ticket 63982 + * + * @dataProvider data_get_items_by_status_sanitize + */ + public function test_get_items_by_status_sanitize( $key, $expected ) { + wp_set_current_user( self::$admin_id ); + + // Create a post with the test status. + $params = array( + 'post' => self::$post_id, + 'author_name' => 'Comic Book Guy', + 'author_email' => 'cbg@androidsdungeon.com', + 'author_url' => 'http://androidsdungeon.com', + 'content' => 'Worst Comment Ever!', + 'status' => $key, + ); + + $request = new WP_REST_Request( 'POST', '/wp/v2/comments' ); + $request->add_header( 'Content-Type', 'application/json' ); + $request->set_body( wp_json_encode( $params ) ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 201, $response->get_status() ); + + $comment = $response->get_data(); + + $this->assertEquals( $expected, $comment['status'] ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_get_items_by_status_sanitize() { + return array( + 'an empty string key' => array( + 'key' => '', + 'expected' => 'hold', + ), + 'a lowercase key with commas' => array( + 'key' => 'howdy,admin', + 'expected' => 'hold', + ), + 'a lowercase key with commas' => array( + 'key' => 'HOWDY,ADMIN', + 'expected' => 'hold', + ), + 'a mixed case key with commas' => array( + 'key' => 'HoWdY,aDmIn', + 'expected' => 'hold', + ), + 'a string with unicode' => array( + 'key' => array( 'howdy admin', 'another-value' ), + 'expected' => 'hold', + ), + ); + } + + /** * @ticket 38692 */ From 3bf31216cb3117fc0337232419f7d9002aefe954 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 16 Sep 2025 09:20:51 -0600 Subject: [PATCH 12/24] Update src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php Co-authored-by: Mukesh Panchal --- .../rest-api/endpoints/class-wp-rest-comments-controller.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 b33ef539505d7..41eefb96484c8 100644 --- 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 @@ -1932,7 +1932,8 @@ protected function check_is_comment_content_allowed( $prepared_comment ) { /** * Sanitize a single comment status or a list of comment statuses with `sanitize_key`. * - * @since 6.8.0 + * @since 6.9.0 + * * @param string|array $statuses Comment status or array of comment statuses. * @return array Sanitized array of comment statuses. */ From f210ce5a612498f5fa3a7380c2432a410d7e5053 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 18 Sep 2025 08:51:25 -0600 Subject: [PATCH 13/24] Update tests/phpunit/tests/rest-api/rest-comments-controller.php Co-authored-by: Mukesh Panchal --- tests/phpunit/tests/rest-api/rest-comments-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index 44df920a4cd2a..9572327c34fbd 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -363,7 +363,7 @@ public function data_get_items_by_status_sanitize() { 'expected' => 'hold', ), 'a string with unicode' => array( - 'key' => array( 'howdy admin', 'another-value' ), + 'key' => array( 'howdy admin', 'another-value' ), 'expected' => 'hold', ), ); From 0426084143aeb1f272e0be3955ce5fa5de9849ce Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Thu, 23 Jul 2026 09:15:17 -0700 Subject: [PATCH 14/24] Fix comments status permission check for array values With the status collection param now an array, the sanitized value never string-matches 'approve', so unauthenticated requests using the default status were rejected. Compare against the parsed list instead, define the schema as an array of strings per review feedback, and regenerate the QUnit fixture to match. --- .../endpoints/class-wp-rest-comments-controller.php | 13 ++++++++----- tests/qunit/fixtures/wp-api-generated.js | 10 +++++----- 2 files changed, 13 insertions(+), 10 deletions(-) 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 b60db5953502d..2d1188498f8f9 100644 --- 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 @@ -157,7 +157,7 @@ public function get_items_permissions_check( $request ) { foreach ( $protected_params as $param ) { if ( 'status' === $param ) { - if ( 'approve' !== $request[ $param ] ) { + if ( array( 'approve' ) !== wp_parse_list( $request[ $param ] ) ) { $forbidden_params[] = $param; } } elseif ( 'type' === $param ) { @@ -200,7 +200,7 @@ public function get_items_permissions_check( $request ) { if ( ! current_user_can( 'edit_posts' ) ) { foreach ( $protected_params as $param ) { if ( 'status' === $param ) { - if ( 'approve' !== $request[ $param ] ) { + if ( array( 'approve' ) !== wp_parse_list( $request[ $param ] ) ) { $forbidden_params[] = $param; } } elseif ( 'type' === $param ) { @@ -1777,9 +1777,12 @@ public function get_collection_params() { $query_params['status'] = array( 'default' => 'approve', - 'description' => __( 'Limit result set to comments assigned a specific status. Requires authorization.' ), - 'sanitize_callback' => array( $this, 'sanitize_comment_statuses' ), + 'description' => __( 'Limit result set to comments assigned one or more statuses. Requires authorization.' ), 'type' => 'array', + 'items' => array( + 'type' => 'string', + ), + 'sanitize_callback' => array( $this, 'sanitize_comment_statuses' ), 'validate_callback' => 'rest_validate_request_arg', ); @@ -2051,7 +2054,7 @@ protected function check_is_comment_content_allowed( $prepared_comment ) { */ public function sanitize_comment_statuses( $statuses ) { $statuses = wp_parse_list( $statuses ); - return array_unique( array_map( 'sanitize_key', $statuses ) ); + return array_values( array_unique( array_map( 'sanitize_key', $statuses ) ) ); } /** diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 179164bce80af..e4ae73cf0a706 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -10580,11 +10580,11 @@ mockedApiResponse.Schema = { }, "status": { "default": "approve", - "description": "Limit result set to comments assigned a specific status. Requires authorization.", - "type": [ - "string", - "array" - ], + "description": "Limit result set to comments assigned one or more statuses. Requires authorization.", + "type": "array", + "items": { + "type": "string" + }, "required": false }, "type": { From c4159ea9436325a20dcf5dcf37f8b2213c2ed949 Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Thu, 23 Jul 2026 09:15:17 -0700 Subject: [PATCH 15/24] Consolidate and expand comment status query tests Drop the fixture 'status' arg, which wp_insert_comment ignores, resolving the review discussion about deterministic fixtures. Consolidate the three near-identical status tests into a data provider, test the sanitize callback directly instead of via the unrelated create path, and cover the authorization boundary for the default and multiple statuses. --- .../rest-api/rest-comments-controller.php | 138 +++++++----------- 1 file changed, 49 insertions(+), 89 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index a9639bcf172db..beb3932f4f806 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -137,7 +137,6 @@ public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { array( 'comment_content' => "Comment {$i}", 'comment_post_ID' => self::$post_id, - 'status' => ( 0 === $i % 2 ) ? 'approve' : 'hold', ) ); } @@ -247,150 +246,111 @@ public function test_get_items() { } /** - * Test getting items of a specific status. + * Test getting comments filtered by one or more statuses. * * @ticket 63982 + * + * @dataProvider data_get_items_by_status + * + * @param string|array $status Status value(s) to filter by. */ - public function test_get_items_by_status() { + public function test_get_items_by_status( $status ) { wp_set_current_user( self::$admin_id ); $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); - $request->set_param( 'status', 'approve' ); + $request->set_param( 'status', $status ); $request->set_param( 'per_page', self::$per_page ); $response = rest_get_server()->dispatch( $request ); $this->assertSame( 200, $response->get_status() ); - $q = new WP_Comment_Query(); - $found = $q->query( + $query = new WP_Comment_Query(); + $found = $query->query( array( - 'status' => 'approve', + 'status' => $status, 'count' => true, ) ); - $comments = $response->get_data(); + $this->assertCount( $found, $response->get_data() ); + } - $this->assertCount( $found, $comments ); + /** + * Data provider. + * + * @return array[] + */ + public function data_get_items_by_status() { + return array( + 'a single status' => array( 'approve' ), + 'the hold status' => array( 'hold' ), + 'the all status' => array( 'all' ), + 'an array of statuses' => array( array( 'approve', 'hold' ) ), + 'a comma-separated list' => array( 'approve,hold' ), + ); } /** - * Test getting comments of all statuses. + * Test that filtering by the default status does not require authorization. * * @ticket 63982 */ - public function test_get_items_by_all_status() { - wp_set_current_user( self::$admin_id ); - + public function test_get_items_by_default_status_without_permission() { $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); - $request->set_param( 'status', 'all' ); + $request->set_param( 'status', 'approve' ); $request->set_param( 'per_page', self::$per_page ); $response = rest_get_server()->dispatch( $request ); $this->assertSame( 200, $response->get_status() ); - - $q = new WP_Comment_Query(); - $found = $q->query( - array( - 'status' => 'all', - 'count' => true, - ) - ); - - $comments = $response->get_data(); - $this->assertCount( $found, $comments ); + $this->assertCount( self::$total_comments, $response->get_data() ); } /** - * Test getting items of multiple statuses. + * Test that filtering by multiple statuses requires authorization. * * @ticket 63982 */ - public function test_get_items_by_multiple_status() { - wp_set_current_user( self::$admin_id ); - + public function test_get_items_by_multiple_statuses_without_permission() { $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); $request->set_param( 'status', array( 'approve', 'hold' ) ); - $request->set_param( 'per_page', self::$per_page ); - $response = rest_get_server()->dispatch( $request ); - $this->assertSame( 200, $response->get_status() ); - - $q = new WP_Comment_Query(); - $found = $q->query( - array( - 'status' => array( 'approve', 'hold' ), - 'count' => true, - ) - ); - $comments = $response->get_data(); - $this->assertCount( $found, $comments ); + $this->assertErrorResponse( 'rest_forbidden_param', $response, 401 ); } /** - * Test sanization of the status parameter. + * Test sanitization of the status parameter. * * @ticket 63982 * - * @dataProvider data_get_items_by_status_sanitize + * @dataProvider data_sanitize_comment_statuses + * + * @param string|array $statuses Raw status value. + * @param array $expected Expected sanitized statuses. */ - public function test_get_items_by_status_sanitize( $key, $expected ) { - wp_set_current_user( self::$admin_id ); - - // Create a post with the test status. - $params = array( - 'post' => self::$post_id, - 'author_name' => 'Comic Book Guy', - 'author_email' => 'cbg@androidsdungeon.com', - 'author_url' => 'http://androidsdungeon.com', - 'content' => 'Worst Comment Ever!', - 'status' => $key, - ); - - $request = new WP_REST_Request( 'POST', '/wp/v2/comments' ); - $request->add_header( 'Content-Type', 'application/json' ); - $request->set_body( wp_json_encode( $params ) ); - - $response = rest_get_server()->dispatch( $request ); - $this->assertSame( 201, $response->get_status() ); - - $comment = $response->get_data(); + public function test_sanitize_comment_statuses( $statuses, $expected ) { + $controller = new WP_REST_Comments_Controller(); - $this->assertEquals( $expected, $comment['status'] ); + $this->assertSame( $expected, $controller->sanitize_comment_statuses( $statuses ) ); } /** * Data provider. * - * @return array + * @return array[] */ - public function data_get_items_by_status_sanitize() { + public function data_sanitize_comment_statuses() { return array( - 'an empty string key' => array( - 'key' => '', - 'expected' => 'hold', - ), - 'a lowercase key with commas' => array( - 'key' => 'howdy,admin', - 'expected' => 'hold', - ), - 'a lowercase key with commas' => array( - 'key' => 'HOWDY,ADMIN', - 'expected' => 'hold', - ), - 'a mixed case key with commas' => array( - 'key' => 'HoWdY,aDmIn', - 'expected' => 'hold', - ), - 'a string with unicode' => array( - 'key' => array( 'howdy admin', 'another-value' ), - 'expected' => 'hold', - ), + 'a single status' => array( 'approve', array( 'approve' ) ), + 'a comma-separated list' => array( 'approve,hold', array( 'approve', 'hold' ) ), + 'an array of statuses' => array( array( 'approve', 'hold' ), array( 'approve', 'hold' ) ), + 'mixed case statuses' => array( 'APPROVE,Hold', array( 'approve', 'hold' ) ), + 'duplicate statuses' => array( array( 'approve', 'approve', 'hold' ), array( 'approve', 'hold' ) ), + 'invalid characters' => array( 'howdy admin', array( 'howdynbspadmin' ) ), + 'an empty string' => array( '', array() ), ); } - /** * @ticket 38692 */ From a2972fd11374676b90b3951f42821a1d0f99c88f Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Thu, 23 Jul 2026 09:16:04 -0700 Subject: [PATCH 16/24] Update since tag to 7.1.0 The PR predates the 7.1 cycle; 6.9 has shipped. --- .../rest-api/endpoints/class-wp-rest-comments-controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2d1188498f8f9..55479832939da 100644 --- 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 @@ -2047,7 +2047,7 @@ protected function check_is_comment_content_allowed( $prepared_comment ) { /** * Sanitizes a single comment status or a list of comment statuses. * - * @since 6.9.0 + * @since 7.1.0 * * @param string|array $statuses Comment status or array of comment statuses. * @return array Sanitized array of comment statuses. From 5217fd287448265678e1778e8d3edb5da7b79631 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 23 Jul 2026 13:16:28 -0700 Subject: [PATCH 17/24] Narrow types on sanitize_comment_statuses() method --- .../endpoints/class-wp-rest-comments-controller.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 55479832939da..dc3a1b5023a3a 100644 --- 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 @@ -2049,10 +2049,10 @@ protected function check_is_comment_content_allowed( $prepared_comment ) { * * @since 7.1.0 * - * @param string|array $statuses Comment status or array of comment statuses. - * @return array Sanitized array of comment statuses. + * @param string[]|string $statuses Comment status or array of comment statuses. + * @return list Sanitized array of comment statuses. */ - public function sanitize_comment_statuses( $statuses ) { + public function sanitize_comment_statuses( $statuses ): array { $statuses = wp_parse_list( $statuses ); return array_values( array_unique( array_map( 'sanitize_key', $statuses ) ) ); } From cd4496f6bf717acba56e6ecc534bdee068f66d7e Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 23 Jul 2026 13:39:07 -0700 Subject: [PATCH 18/24] Tighten sanitize_comment_statuses() to return list --- .../rest-api/endpoints/class-wp-rest-comments-controller.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 dc3a1b5023a3a..ba35d854c7691 100644 --- 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 @@ -2050,11 +2050,12 @@ protected function check_is_comment_content_allowed( $prepared_comment ) { * @since 7.1.0 * * @param string[]|string $statuses Comment status or array of comment statuses. - * @return list Sanitized array of comment statuses. + * @return string[] Sanitized array of comment statuses. + * @phpstan-return list */ public function sanitize_comment_statuses( $statuses ): array { $statuses = wp_parse_list( $statuses ); - return array_values( array_unique( array_map( 'sanitize_key', $statuses ) ) ); + return array_values( array_filter( array_unique( array_map( 'sanitize_key', $statuses ) ) ) ); } /** From c1c7823f930294b28fbebc031f622513bcf3c36a Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 23 Jul 2026 13:39:25 -0700 Subject: [PATCH 19/24] Add typing to data_sanitize_comment_statuses --- .../tests/rest-api/rest-comments-controller.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index beb3932f4f806..eac066452fb50 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -325,10 +325,10 @@ public function test_get_items_by_multiple_statuses_without_permission() { * * @dataProvider data_sanitize_comment_statuses * - * @param string|array $statuses Raw status value. - * @param array $expected Expected sanitized statuses. + * @param string|string[] $statuses Raw status value. + * @param list $expected Expected sanitized statuses. */ - public function test_sanitize_comment_statuses( $statuses, $expected ) { + public function test_sanitize_comment_statuses( $statuses, array $expected ) { $controller = new WP_REST_Comments_Controller(); $this->assertSame( $expected, $controller->sanitize_comment_statuses( $statuses ) ); @@ -337,9 +337,9 @@ public function test_sanitize_comment_statuses( $statuses, $expected ) { /** * Data provider. * - * @return array[] + * @return array }> */ - public function data_sanitize_comment_statuses() { + public function data_sanitize_comment_statuses(): array { return array( 'a single status' => array( 'approve', array( 'approve' ) ), 'a comma-separated list' => array( 'approve,hold', array( 'approve', 'hold' ) ), From f44de343062d903d292ef0fa273a7bdf194266e1 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 23 Jul 2026 13:49:09 -0700 Subject: [PATCH 20/24] Add native type hints to test class properties --- .../rest-api/rest-comments-controller.php | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index eac066452fb50..10b985949cff6 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -8,27 +8,27 @@ * @group restapi */ class WP_Test_REST_Comments_Controller extends WP_Test_REST_Controller_Testcase { - protected static $superadmin_id; - protected static $admin_id; - protected static $editor_id; - protected static $moderator_id; - protected static $contributor_id; - protected static $subscriber_id; - protected static $author_id; - protected static $user_ids = array(); - - protected static $post_id; - protected static $password_id; - protected static $private_id; - protected static $draft_id; - protected static $trash_id; - protected static $approved_id; - protected static $hold_id; - - protected static $comment_ids = array(); - protected static $total_comments = 30; - protected static $per_page = 50; - protected static $num_notes = 10; + protected static int $superadmin_id; + protected static int $admin_id; + protected static int $editor_id; + protected static int $moderator_id; + protected static int $contributor_id; + protected static int $subscriber_id; + protected static int $author_id; + protected static array $user_ids = array(); + + protected static int $post_id; + protected static int $password_id; + protected static int $private_id; + protected static int $draft_id; + protected static int $trash_id; + protected static int $approved_id; + protected static int $hold_id; + + protected static array $comment_ids = array(); + protected static int $total_comments = 30; + protected static int $per_page = 50; + protected static int $num_notes = 10; protected $endpoint; From b9b22de78d905835856df41ad33b647374487ec4 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 23 Jul 2026 13:49:26 -0700 Subject: [PATCH 21/24] Address PHPStan issues in tests --- .../tests/rest-api/rest-comments-controller.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index 10b985949cff6..9e79375bd0a6a 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -252,7 +252,7 @@ public function test_get_items() { * * @dataProvider data_get_items_by_status * - * @param string|array $status Status value(s) to filter by. + * @param string|list $status Status value(s) to filter by. */ public function test_get_items_by_status( $status ) { wp_set_current_user( self::$admin_id ); @@ -272,15 +272,17 @@ public function test_get_items_by_status( $status ) { ) ); - $this->assertCount( $found, $response->get_data() ); + $data = $response->get_data(); + $this->assertIsArray( $data ); + $this->assertCount( $found, $data ); } /** * Data provider. * - * @return array[] + * @return array }> */ - public function data_get_items_by_status() { + public function data_get_items_by_status(): array { return array( 'a single status' => array( 'approve' ), 'the hold status' => array( 'hold' ), @@ -302,7 +304,9 @@ public function test_get_items_by_default_status_without_permission() { $response = rest_get_server()->dispatch( $request ); $this->assertSame( 200, $response->get_status() ); - $this->assertCount( self::$total_comments, $response->get_data() ); + $data = $response->get_data(); + $this->assertIsArray( $data ); + $this->assertCount( self::$total_comments, $data ); } /** From 9a34a07fe0cdcc18c96bf3df98f984166bc99d3e Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 23 Jul 2026 13:52:12 -0700 Subject: [PATCH 22/24] Apply suggestions from code review Co-authored-by: Weston Ruter --- .../rest-api/endpoints/class-wp-rest-comments-controller.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 ba35d854c7691..e92e8572879e7 100644 --- 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 @@ -157,7 +157,7 @@ public function get_items_permissions_check( $request ) { foreach ( $protected_params as $param ) { if ( 'status' === $param ) { - if ( array( 'approve' ) !== wp_parse_list( $request[ $param ] ) ) { + if ( array( 'approve' ) !== $request[ $param ] ) { $forbidden_params[] = $param; } } elseif ( 'type' === $param ) { @@ -200,7 +200,7 @@ public function get_items_permissions_check( $request ) { if ( ! current_user_can( 'edit_posts' ) ) { foreach ( $protected_params as $param ) { if ( 'status' === $param ) { - if ( array( 'approve' ) !== wp_parse_list( $request[ $param ] ) ) { + if ( array( 'approve' ) !== $request[ $param ] ) { $forbidden_params[] = $param; } } elseif ( 'type' === $param ) { From f29b1345336e08719fca7abb49fcc4e2528d9b78 Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Thu, 23 Jul 2026 15:52:50 -0700 Subject: [PATCH 23/24] Cover comma-separated multi-status requests in the authorization test The unauthenticated 401 boundary was only covered for the array form of the status parameter. Since the permission check now relies on the sanitize callback having parsed the raw value, the comma-separated form needs its own case so it cannot regress independently. Convert the test to a data provider covering both forms. --- .../rest-api/rest-comments-controller.php | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index 9e79375bd0a6a..16f5faefb487d 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -313,15 +313,31 @@ public function test_get_items_by_default_status_without_permission() { * Test that filtering by multiple statuses requires authorization. * * @ticket 63982 + * + * @dataProvider data_get_items_by_multiple_statuses_without_permission + * + * @param string|list $status Status value(s) to filter by. */ - public function test_get_items_by_multiple_statuses_without_permission() { + public function test_get_items_by_multiple_statuses_without_permission( $status ) { $request = new WP_REST_Request( 'GET', '/wp/v2/comments' ); - $request->set_param( 'status', array( 'approve', 'hold' ) ); + $request->set_param( 'status', $status ); $response = rest_get_server()->dispatch( $request ); $this->assertErrorResponse( 'rest_forbidden_param', $response, 401 ); } + /** + * Data provider. + * + * @return array }> + */ + public function data_get_items_by_multiple_statuses_without_permission(): array { + return array( + 'an array of statuses' => array( array( 'approve', 'hold' ) ), + 'a comma-separated list' => array( 'approve,hold' ), + ); + } + /** * Test sanitization of the status parameter. * From 6dd63d23061c049c5447285e000e025ee3fd73df Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Thu, 23 Jul 2026 15:58:27 -0700 Subject: [PATCH 24/24] Preserve a literal '0' status when sanitizing the status parameter array_filter() without a callback drops all falsy strings, including '0'. WP_Comment_Query treats a literal '0' status as a direct comment_approved match (how held comments are stored), so ?status=0 is a working query today and must survive sanitization. Filter only empty strings instead. --- .../endpoints/class-wp-rest-comments-controller.php | 13 +++++++++++-- .../tests/rest-api/rest-comments-controller.php | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) 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 e92e8572879e7..96a1f6f83a42f 100644 --- 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 @@ -2054,8 +2054,17 @@ protected function check_is_comment_content_allowed( $prepared_comment ) { * @phpstan-return list */ public function sanitize_comment_statuses( $statuses ): array { - $statuses = wp_parse_list( $statuses ); - return array_values( array_filter( array_unique( array_map( 'sanitize_key', $statuses ) ) ) ); + $statuses = array_unique( array_map( 'sanitize_key', wp_parse_list( $statuses ) ) ); + + // Only drop empty values. A literal '0' is a queryable status, as comments are held with `comment_approved` of '0'. + $statuses = array_filter( + $statuses, + static function ( $status ) { + return '' !== $status; + } + ); + + return array_values( $statuses ); } /** diff --git a/tests/phpunit/tests/rest-api/rest-comments-controller.php b/tests/phpunit/tests/rest-api/rest-comments-controller.php index 16f5faefb487d..c2ae9ffcf7cf8 100644 --- a/tests/phpunit/tests/rest-api/rest-comments-controller.php +++ b/tests/phpunit/tests/rest-api/rest-comments-controller.php @@ -368,6 +368,8 @@ public function data_sanitize_comment_statuses(): array { 'duplicate statuses' => array( array( 'approve', 'approve', 'hold' ), array( 'approve', 'hold' ) ), 'invalid characters' => array( 'howdy admin', array( 'howdynbspadmin' ) ), 'an empty string' => array( '', array() ), + 'a literal 0 status' => array( '0', array( '0' ) ), + '0 mixed with a status' => array( '0,approve', array( '0', 'approve' ) ), ); }