| @@ -1125,9 +1125,9 @@ | ||
| 1125 | 1125 | // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query string is built dynamically above based on conditions. |
| 1126 | 1126 | $query = $wpdb->prepare( $query, $params ); |
| 1127 | 1127 | } |
| 1128 | 1128 | |
| 1129 | - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- Custom table query with dynamic preparation, caching not applicable for dynamic queries. | |
| 1129 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom table query with dynamic preparation; table name internal, not user input; caching not applicable for dynamic queries. | |
| 1130 | 1130 | $results = $wpdb->get_results( $query, ARRAY_A ); |
| 1131 | 1131 | |
| 1132 | 1132 | return is_array( $results ) ? $results : []; |
| 1133 | 1133 | } |
| @@ -1182,9 +1182,9 @@ | ||
| 1182 | 1182 | // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query string is built dynamically above based on conditions. |
| 1183 | 1183 | $query = $wpdb->prepare( $query, $params ); |
| 1184 | 1184 | } |
| 1185 | 1185 | |
| 1186 | - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- Custom table query with dynamic preparation, caching not applicable for count operations. | |
| 1186 | + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom table query with dynamic preparation; table name internal, not user input; caching not applicable for count operations. | |
| 1187 | 1187 | $result = $wpdb->get_var( $query ); |
| 1188 | 1188 | |
| 1189 | 1189 | return absint( $result ); |
| 1190 | 1190 | } |
| @@ -1284,12 +1284,42 @@ | ||
| 1284 | 1284 | } |
| 1285 | 1285 | |
| 1286 | 1286 | $column = $condition['key']; |
| 1287 | 1287 | |
| 1288 | - if ( in_array( $operator, [ 'IN', 'NOT IN' ], true ) && is_array( $condition['value'] ) ) { | |
| 1288 | + if ( in_array( $operator, [ 'IN', 'NOT IN' ], true ) ) { | |
| 1289 | + if ( ! is_array( $condition['value'] ) ) { | |
| 1290 | + // A scalar used to fall through to the else branch and emit | |
| 1291 | + // `col IN %s`, which is a syntax error that fails the whole | |
| 1292 | + // query. Base::prepare_where_clauses() reports this and drops | |
| 1293 | + // the condition; do the same rather than leave the two builders | |
| 1294 | + // disagreeing on malformed input. | |
| 1295 | + _doing_it_wrong( | |
| 1296 | + __METHOD__, | |
| 1297 | + esc_html( "{$operator} requires an array value, received " . gettype( $condition['value'] ) . '.' ), | |
| 1298 | + '2.12.7' | |
| 1299 | + ); | |
| 1300 | + continue; | |
| 1301 | + } | |
| 1302 | + | |
| 1289 | 1303 | $ids = array_map( 'absint', $condition['value'] ); |
| 1290 | - if ( empty( $ids ) ) { | |
| 1291 | - $ids = [ 0 ]; | |
| 1304 | + if ( [] === $ids ) { | |
| 1305 | + // Same empty-list handling as Base::prepare_where_clauses(), so | |
| 1306 | + // the two builders cannot disagree. An empty IN matches nothing. | |
| 1307 | + // An empty NOT IN excludes nothing, and is dropped rather than | |
| 1308 | + // written as a literal, because a literal true would make an | |
| 1309 | + // enclosing OR group match every row. | |
| 1310 | + // | |
| 1311 | + // This builder serves the manage_options-gated admin payments | |
| 1312 | + // listing only, through get_all_main_payments() and | |
| 1313 | + // get_total_main_payments_by_status(). The payment-history | |
| 1314 | + // shortcode's customer filter is compiled by | |
| 1315 | + // Base::prepare_where_clauses() via Payments::get_all() -- that | |
| 1316 | + // group is where an OR fail-open would actually leak, and it is | |
| 1317 | + // covered by the change in base.php. | |
| 1318 | + if ( 'IN' === $operator ) { | |
| 1319 | + $sub_clauses[] = '1 = 0'; | |
| 1320 | + } | |
| 1321 | + continue; | |
| 1292 | 1322 | } |
| 1293 | 1323 | $placeholders = implode( ',', array_fill( 0, count( $ids ), '%d' ) ); |
| 1294 | 1324 | $sub_clauses[] = "{$column} {$operator} ({$placeholders})"; |
| 1295 | 1325 | foreach ( $ids as $id ) { |