posts/$wpdb->postmeta, not user input; {$placeholders} is a dynamically-built but fixed-count "%s,%s,..." list phpcs can't statically count, real args supplied via $post_types just below. $sql = "SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p" . " INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID" . " WHERE p.post_status = 'publish' AND p.post_type IN ({$placeholders})" . " AND ( ( pm.meta_key = '_abds_seo_noindex' AND pm.meta_value = '1' ) OR ( pm.meta_key = '_abds_seo_nofollow' AND pm.meta_value = '1' ) )"; // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- $sql is prepared just below; this runs once per ACTIVATION_VERSION (gated above), its result cached in PENDING_COUNT_OPTION, not on every request. return (int) $wpdb->get_var( $wpdb->prepare( $sql, $post_types ) ); } /** * The affected posts themselves, paginated, for the review screen. * * @param int $paged Current page, 1-indexed. * @return WP_Query */ public static function affected_posts_query( int $paged = 1 ): WP_Query { $post_types = array_keys( ABDS_SEO_Taxonomy_Helper::public_post_types() ); return new WP_Query( array( 'post_type' => array() !== $post_types ? $post_types : array( 'post' ), 'post_status' => 'publish', 'posts_per_page' => 20, 'paged' => max( 1, $paged ), 'orderby' => 'title', 'order' => 'ASC', 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- one-time review screen for a bounded, already-migrated dataset, not a hot path. 'relation' => 'OR', array( 'key' => '_abds_seo_noindex', 'value' => '1', ), array( 'key' => '_abds_seo_nofollow', 'value' => '1', ), ), ) ); } }