1717use Automattic \Jetpack \Status ;
1818use Automattic \Jetpack \Status \Host ;
1919use WP_Error ;
20+ use WP_Query ;
2021use WP_REST_Request ;
2122use WP_REST_Response ;
2223
@@ -290,32 +291,38 @@ public function register_routes() {
290291 'permission_callback ' => array ( $ this , 'get_items_permissions_check ' ),
291292 'callback ' => array ( $ this , 'get_status_counts ' ),
292293 'args ' => array (
293- 'search ' => array (
294+ 'search ' => array (
294295 'description ' => 'Limit results to those matching a string. ' ,
295296 'type ' => 'string ' ,
296297 'sanitize_callback ' => 'sanitize_text_field ' ,
297298 'validate_callback ' => 'rest_validate_request_arg ' ,
298299 ),
299- 'parent ' => array (
300+ 'parent ' => array (
300301 'description ' => 'Limit results to those of a specific parent ID. ' ,
301302 'type ' => 'integer ' ,
302303 'sanitize_callback ' => 'absint ' ,
303304 'validate_callback ' => 'rest_validate_request_arg ' ,
304305 ),
305- 'before ' => array (
306+ 'before ' => array (
306307 'description ' => 'Limit results to feedback published before a given ISO8601 compliant date. ' ,
307308 'type ' => 'string ' ,
308309 'format ' => 'date-time ' ,
309310 'sanitize_callback ' => 'sanitize_text_field ' ,
310311 'validate_callback ' => 'rest_validate_request_arg ' ,
311312 ),
312- 'after ' => array (
313+ 'after ' => array (
313314 'description ' => 'Limit results to feedback published after a given ISO8601 compliant date. ' ,
314315 'type ' => 'string ' ,
315316 'format ' => 'date-time ' ,
316317 'sanitize_callback ' => 'sanitize_text_field ' ,
317318 'validate_callback ' => 'rest_validate_request_arg ' ,
318319 ),
320+ 'is_unread ' => array (
321+ 'description ' => 'Limit results to read or unread feedback items. ' ,
322+ 'type ' => 'boolean ' ,
323+ 'sanitize_callback ' => 'rest_sanitize_boolean ' ,
324+ 'validate_callback ' => 'rest_validate_request_arg ' ,
325+ ),
319326 ),
320327 )
321328 );
@@ -376,10 +383,11 @@ static function ( $post_id ) {
376383 public function get_status_counts ( $ request ) {
377384 global $ wpdb ;
378385
379- $ search = $ request ->get_param ( 'search ' );
380- $ parent = $ request ->get_param ( 'parent ' );
381- $ before = $ request ->get_param ( 'before ' );
382- $ after = $ request ->get_param ( 'after ' );
386+ $ search = $ request ->get_param ( 'search ' );
387+ $ parent = $ request ->get_param ( 'parent ' );
388+ $ before = $ request ->get_param ( 'before ' );
389+ $ after = $ request ->get_param ( 'after ' );
390+ $ is_unread = $ request ->get_param ( 'is_unread ' );
383391
384392 $ where_conditions = array ( $ wpdb ->prepare ( 'post_type = %s ' , 'feedback ' ) );
385393
@@ -400,6 +408,11 @@ public function get_status_counts( $request ) {
400408 $ where_conditions [] = $ wpdb ->prepare ( 'post_date >= %s ' , $ after );
401409 }
402410
411+ if ( null !== $ is_unread ) {
412+ $ comment_status = $ is_unread ? Feedback::STATUS_UNREAD : Feedback::STATUS_READ ;
413+ $ where_conditions [] = $ wpdb ->prepare ( 'comment_status = %s ' , $ comment_status );
414+ }
415+
403416 $ where_clause = implode ( ' AND ' , $ where_conditions );
404417
405418 // Execute single query with CASE statements for all status counts.
@@ -792,6 +805,81 @@ public function prepare_item_for_response( $item, $request ) {
792805 return rest_ensure_response ( $ response );
793806 }
794807
808+ /**
809+ * Retrieves a collection of feedback items.
810+ * Overrides parent to support invalid_ids with OR logic.
811+ *
812+ * @param WP_REST_Request $request Full details about the request.
813+ * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
814+ */
815+ public function get_items ( $ request ) {
816+ $ invalid_ids = $ request ->get_param ( 'invalid_ids ' );
817+
818+ // If we have invalid_ids, we need to modify the query with a WHERE clause
819+ if ( ! empty ( $ invalid_ids ) ) {
820+ add_filter ( 'posts_where ' , array ( $ this , 'modify_query_for_invalid_ids ' ), 10 , 2 );
821+ // Store invalid_ids temporarily so the filter can access them
822+ $ this ->temp_invalid_ids = $ invalid_ids ;
823+ }
824+
825+ $ response = parent ::get_items ( $ request );
826+
827+ // Clean up
828+ if ( ! empty ( $ invalid_ids ) ) {
829+ remove_filter ( 'posts_where ' , array ( $ this , 'modify_query_for_invalid_ids ' ), 10 );
830+ unset( $ this ->temp_invalid_ids );
831+ }
832+
833+ return $ response ;
834+ }
835+
836+ /**
837+ * Modify the WHERE clause to include invalid_ids with OR logic.
838+ *
839+ * @param string $where The WHERE clause.
840+ * @param WP_Query $query The WP_Query instance.
841+ * @return string Modified WHERE clause.
842+ */
843+ public function modify_query_for_invalid_ids ( $ where , $ query ) {
844+ global $ wpdb ;
845+
846+ // Only modify our feedback queries
847+ if ( ! isset ( $ this ->temp_invalid_ids ) || empty ( $ this ->temp_invalid_ids ) ) {
848+ return $ where ;
849+ }
850+
851+ // Only modify if this is a feedback query
852+ $ post_type = $ query ->get ( 'post_type ' );
853+ if ( $ post_type !== 'feedback ' ) {
854+ return $ where ;
855+ }
856+
857+ $ invalid_ids_sql = implode ( ', ' , array_map ( 'absint ' , $ this ->temp_invalid_ids ) );
858+
859+ // Add OR condition for invalid_ids at the end of the WHERE clause
860+ // Keep the AND at the beginning since WordPress WHERE clauses start with "AND"
861+ $ where .= " OR {$ wpdb ->posts }.ID IN ( {$ invalid_ids_sql }) " ;
862+
863+ return $ where ;
864+ }
865+
866+ /**
867+ * Filters the query arguments for the feedback collection.
868+ *
869+ * @param array $args Key value array of query var to query value.
870+ * @param WP_REST_Request $request The request used.
871+ * @return array Modified query arguments.
872+ */
873+ protected function prepare_items_query ( $ args = array (), $ request = null ) {
874+ $ args = parent ::prepare_items_query ( $ args , $ request );
875+
876+ if ( isset ( $ request ['is_unread ' ] ) ) {
877+ $ args ['comment_status ' ] = $ request ['is_unread ' ] ? Feedback::STATUS_UNREAD : Feedback::STATUS_READ ;
878+ }
879+
880+ return $ args ;
881+ }
882+
795883 /**
796884 * Retrieves the query params for the feedback collection.
797885 *
@@ -818,6 +906,24 @@ public function get_collection_params() {
818906 ),
819907 'default ' => array (),
820908 );
909+ $ query_params ['is_unread ' ] = array (
910+ 'description ' => __ ( 'Limit result set to read or unread feedback items. ' , 'jetpack-forms ' ),
911+ 'type ' => 'boolean ' ,
912+ 'sanitize_callback ' => 'rest_sanitize_boolean ' ,
913+ 'validate_callback ' => 'rest_validate_request_arg ' ,
914+ );
915+ $ query_params ['invalid_ids ' ] = array (
916+ 'description ' => __ ( 'List of item IDs to include in results regardless of filters. ' , 'jetpack-forms ' ),
917+ 'type ' => 'array ' ,
918+ 'items ' => array (
919+ 'type ' => 'integer ' ,
920+ ),
921+ 'default ' => array (),
922+ 'sanitize_callback ' => function ( $ param ) {
923+ return array_map ( 'absint ' , (array ) $ param );
924+ },
925+ 'validate_callback ' => 'rest_validate_request_arg ' ,
926+ );
821927 return $ query_params ;
822928 }
823929
0 commit comments