@@ -819,17 +819,54 @@ public function add_ignore() {
819819 }
820820
821821 global $ wpdb ;
822- $ table_name = $ wpdb ->prefix . 'accessibility_checker ' ;
823- $ raw_ids = isset ( $ _REQUEST ['ids ' ] ) ? (array ) wp_unslash ( $ _REQUEST ['ids ' ] ) : []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitization handled below.
824- $ ids = array_map (
822+ $ table_name = $ wpdb ->prefix . 'accessibility_checker ' ;
823+ $ raw_ids = isset ( $ _REQUEST ['ids ' ] ) ? (array ) wp_unslash ( $ _REQUEST ['ids ' ] ) : []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitization handled below.
824+ $ ids = array_map (
825825 function ( $ value ) {
826826 return (int ) $ value ;
827827 },
828828 $ raw_ids
829829 ); // Sanitizing array elements to integers.
830- $ action = isset ( $ _REQUEST ['ignore_action ' ] ) ? sanitize_text_field ( wp_unslash ( $ _REQUEST ['ignore_action ' ] ) ) : '' ;
831- $ type = isset ( $ _REQUEST ['ignore_type ' ] ) ? sanitize_text_field ( wp_unslash ( $ _REQUEST ['ignore_type ' ] ) ) : '' ;
832- $ siteid = get_current_blog_id ();
830+ $ action = isset ( $ _REQUEST ['ignore_action ' ] ) ? sanitize_text_field ( wp_unslash ( $ _REQUEST ['ignore_action ' ] ) ) : '' ;
831+ $ type = isset ( $ _REQUEST ['ignore_type ' ] ) ? sanitize_text_field ( wp_unslash ( $ _REQUEST ['ignore_type ' ] ) ) : '' ;
832+ $ siteid = get_current_blog_id ();
833+
834+ // Capability check: verify edit_post on every post affected by this request.
835+ $ batch_object = null ;
836+ $ first_id = reset ( $ ids );
837+ $ valid_table = edac_get_valid_table_name ( $ table_name );
838+
839+ if ( ! $ first_id || ! $ valid_table ) {
840+ wp_send_json_error ( new \WP_Error ( '-2 ' , __ ( 'No ignore data to return ' , 'accessibility-checker ' ) ) );
841+ }
842+
843+ if ( isset ( $ _REQUEST ['largeBatch ' ] ) && 'true ' === $ _REQUEST ['largeBatch ' ] ) {
844+ // largeBatch updates every row sharing the same object string across the site;
845+ // collect all distinct postids that would be affected and check each one.
846+ // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Permission check requires direct lookup.
847+ $ batch_object = $ wpdb ->get_var ( $ wpdb ->prepare ( 'SELECT object FROM %i WHERE id = %d ' , $ valid_table , $ first_id ) );
848+ if ( ! $ batch_object ) {
849+ wp_send_json_error ( new \WP_Error ( '-2 ' , __ ( 'No ignore data to return ' , 'accessibility-checker ' ) ) );
850+ }
851+ // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Permission check requires direct lookup.
852+ $ affected_post_ids = $ wpdb ->get_col ( $ wpdb ->prepare ( 'SELECT DISTINCT postid FROM %i WHERE siteid = %d AND object = %s ' , $ valid_table , $ siteid , $ batch_object ) );
853+ } else {
854+ // Small batch: look up the post for every supplied ID in one query.
855+ $ id_placeholders = implode ( ', ' , array_fill ( 0 , count ( $ ids ), '%d ' ) );
856+ $ query_args = array_merge ( [ $ valid_table ], $ ids );
857+ $ affected_post_ids = $ wpdb ->get_col ( $ wpdb ->prepare ( "SELECT DISTINCT postid FROM %i WHERE id IN ( {$ id_placeholders }) " , $ query_args ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnquotedComplexPlaceholder -- Permission check requires direct lookup.
858+ }
859+
860+ if ( empty ( $ affected_post_ids ) ) {
861+ wp_send_json_error ( new \WP_Error ( '-2 ' , __ ( 'No ignore data to return ' , 'accessibility-checker ' ) ) );
862+ }
863+
864+ foreach ( $ affected_post_ids as $ affected_post_id ) {
865+ if ( ! current_user_can ( 'edit_post ' , (int ) $ affected_post_id ) ) {
866+ wp_send_json_error ( new \WP_Error ( '-5 ' , __ ( 'Permission Denied ' , 'accessibility-checker ' ) ) );
867+ }
868+ }
869+
833870 $ ignre = ( 'enable ' === $ action ) ? 1 : 0 ;
834871 $ ignre_user = ( 'enable ' === $ action ) ? get_current_user_id () : null ;
835872 $ ignre_user_info = ( 'enable ' === $ action ) ? get_userdata ( $ ignre_user ) : '' ;
@@ -844,14 +881,8 @@ function ( $value ) {
844881 // instead of IDs. It is a much less efficient query than by IDs - but many IDs run
845882 // into request size limits which caused this to not function at all.
846883 if ( isset ( $ _REQUEST ['largeBatch ' ] ) && 'true ' === $ _REQUEST ['largeBatch ' ] ) {
847- // Get the 'object' from the first id.
848- $ first_id = $ ids [0 ];
849- // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- We need to get the latest value, not a cached value.
850- $ object = $ wpdb ->get_var ( $ wpdb ->prepare ( 'SELECT object FROM %i WHERE id = %d ' , $ table_name , $ first_id ) );
851-
852- if ( ! $ object ) {
853- wp_send_json_error ( new \WP_Error ( '-2 ' , __ ( 'No ignore data to return ' , 'accessibility-checker ' ) ) );
854- }
884+ // $batch_object was already resolved during the capability check above.
885+ $ object = $ batch_object ;
855886 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Safe variable used for table name, caching not required for one time operation.
856887 $ wpdb ->query ( $ wpdb ->prepare ( 'UPDATE %i SET ignre = %d, ignre_user = %d, ignre_date = %s, ignre_comment = %s, ignre_reason = %s, ignre_global = %d WHERE siteid = %d and object = %s ' , $ table_name , $ ignre , $ ignre_user , $ ignre_date , $ ignre_comment , $ ignre_reason , $ ignore_global , $ siteid , $ object ) );
857888 } else {
0 commit comments