wp/wp-includes/class-wp-meta-query.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
--- a/wp/wp-includes/class-wp-meta-query.php	Thu Sep 29 08:06:27 2022 +0200
+++ b/wp/wp-includes/class-wp-meta-query.php	Fri Sep 05 18:40:08 2025 +0200
@@ -19,6 +19,7 @@
  *
  * @since 3.2.0
  */
+#[AllowDynamicProperties]
 class WP_Meta_Query {
 	/**
 	 * Array of metadata queries.
@@ -122,7 +123,7 @@
 	 *                                            - 'NOT IN'
 	 *                                            - 'REGEXP'
 	 *                                            - 'NOT REGEXP'
-	 *                                            - 'RLIKE',
+	 *                                            - 'RLIKE'
 	 *                                            - 'EXISTS' (alias of '=')
 	 *                                            - 'NOT EXISTS' (alias of '!=')
 	 *                                            Default is 'IN' when `$key` is an array, '=' otherwise.
@@ -131,7 +132,7 @@
 	 *                                            comparisons. Default is ''.
 	 *         @type string|string[] $value       Meta value or values to filter by.
 	 *         @type string          $compare     MySQL operator used for comparing the $value. Accepts:
-	 *                                            - '=',
+	 *                                            - '='
 	 *                                            - '!='
 	 *                                            - '>'
 	 *                                            - '>='
@@ -179,7 +180,7 @@
 	}
 
 	/**
-	 * Ensure the 'meta_query' argument passed to the class constructor is well-formed.
+	 * Ensures the 'meta_query' argument passed to the class constructor is well-formed.
 	 *
 	 * Eliminates empty items and ensures that a 'relation' is set.
 	 *
@@ -246,7 +247,7 @@
 	}
 
 	/**
-	 * Determine whether a query clause is first-order.
+	 * Determines whether a query clause is first-order.
 	 *
 	 * A first-order meta query clause is one that has either a 'key' or
 	 * a 'value' array key.
@@ -265,7 +266,7 @@
 	 *
 	 * @since 3.2.0
 	 *
-	 * @param array $qv The query variables
+	 * @param array $qv The query variables.
 	 */
 	public function parse_query_vars( $qv ) {
 		$meta_query = array();
@@ -308,7 +309,7 @@
 	}
 
 	/**
-	 * Return the appropriate alias for the given meta type if applicable.
+	 * Returns the appropriate alias for the given meta type if applicable.
 	 *
 	 * @since 3.7.0
 	 *
@@ -344,6 +345,7 @@
 	 * @param string $primary_id_column ID column for the filtered object in $primary_table.
 	 * @param object $context           Optional. The main query object that corresponds to the type, for
 	 *                                  example a `WP_Query`, `WP_User_Query`, or `WP_Site_Query`.
+	 *                                  Default null.
 	 * @return string[]|false {
 	 *     Array containing JOIN and WHERE SQL clauses to append to the main query,
 	 *     or false if no table exists for the requested meta type.
@@ -372,7 +374,7 @@
 		 * If any JOINs are LEFT JOINs (as in the case of NOT EXISTS), then all JOINs should
 		 * be LEFT. Otherwise posts with no metadata will be excluded from results.
 		 */
-		if ( false !== strpos( $sql['join'], 'LEFT JOIN' ) ) {
+		if ( str_contains( $sql['join'], 'LEFT JOIN' ) ) {
 			$sql['join'] = str_replace( 'INNER JOIN', 'LEFT JOIN', $sql['join'] );
 		}
 
@@ -394,7 +396,7 @@
 	}
 
 	/**
-	 * Generate SQL clauses to be appended to a main query.
+	 * Generates SQL clauses to be appended to a main query.
 	 *
 	 * Called by the public WP_Meta_Query::get_sql(), this method is abstracted
 	 * out to maintain parity with the other Query classes.
@@ -424,7 +426,7 @@
 	}
 
 	/**
-	 * Generate SQL clauses for a single query array.
+	 * Generates SQL clauses for a single query array.
 	 *
 	 * If nested subqueries are found, this method recurses the tree to
 	 * produce the properly nested SQL.
@@ -508,7 +510,7 @@
 	}
 
 	/**
-	 * Generate SQL JOIN and WHERE clauses for a first-order query clause.
+	 * Generates SQL JOIN and WHERE clauses for a first-order query clause.
 	 *
 	 * "First-order" means that it's an array with a 'key' or 'value'.
 	 *
@@ -520,11 +522,12 @@
 	 * @param array  $parent_query Parent query array.
 	 * @param string $clause_key   Optional. The array key used to name the clause in the original `$meta_query`
 	 *                             parameters. If not provided, a key will be generated automatically.
-	 * @return string[] {
+	 *                             Default empty string.
+	 * @return array {
 	 *     Array containing JOIN and WHERE SQL clauses to append to a first-order query.
 	 *
-	 *     @type string $join  SQL fragment to append to the main JOIN clause.
-	 *     @type string $where SQL fragment to append to the main WHERE clause.
+	 *     @type string[] $join  Array of SQL fragments to append to the main JOIN clause.
+	 *     @type string[] $where Array of SQL fragments to append to the main WHERE clause.
 	 * }
 	 */
 	public function get_sql_for_clause( &$clause, $parent_query, $clause_key = '' ) {
@@ -630,7 +633,7 @@
 		$clause_key_base = $clause_key;
 		while ( isset( $this->clauses[ $clause_key ] ) ) {
 			$clause_key = $clause_key_base . '-' . $iterator;
-			$iterator++;
+			++$iterator;
 		}
 
 		// Store the clause in our flat array.
@@ -679,11 +682,13 @@
 					case 'REGEXP':
 						$operator = $meta_compare_key;
 						if ( isset( $clause['type_key'] ) && 'BINARY' === strtoupper( $clause['type_key'] ) ) {
-							$cast = 'BINARY';
+							$cast     = 'BINARY';
+							$meta_key = "CAST($alias.meta_key AS BINARY)";
 						} else {
-							$cast = '';
+							$cast     = '';
+							$meta_key = "$alias.meta_key";
 						}
-						$where = $wpdb->prepare( "$alias.meta_key $operator $cast %s", trim( $clause['key'] ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+						$where = $wpdb->prepare( "$meta_key $operator $cast %s", trim( $clause['key'] ) ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
 						break;
 
 					case '!=':
@@ -705,12 +710,14 @@
 					case 'NOT REGEXP':
 						$operator = $meta_compare_key;
 						if ( isset( $clause['type_key'] ) && 'BINARY' === strtoupper( $clause['type_key'] ) ) {
-							$cast = 'BINARY';
+							$cast     = 'BINARY';
+							$meta_key = "CAST($subquery_alias.meta_key AS BINARY)";
 						} else {
-							$cast = '';
+							$cast     = '';
+							$meta_key = "$subquery_alias.meta_key";
 						}
 
-						$meta_compare_string = $meta_compare_string_start . "AND $subquery_alias.meta_key REGEXP $cast %s " . $meta_compare_string_end;
+						$meta_compare_string = $meta_compare_string_start . "AND $meta_key REGEXP $cast %s " . $meta_compare_string_end;
 						$where               = $wpdb->prepare( $meta_compare_string, $clause['key'] ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
 						break;
 				}
@@ -787,7 +794,7 @@
 	}
 
 	/**
-	 * Get a flattened list of sanitized meta clauses.
+	 * Gets a flattened list of sanitized meta clauses.
 	 *
 	 * This array should be used for clause lookup, as when the table alias and CAST type must be determined for
 	 * a value of 'orderby' corresponding to a meta clause.
@@ -801,7 +808,7 @@
 	}
 
 	/**
-	 * Identify an existing table alias that is compatible with the current
+	 * Identifies an existing table alias that is compatible with the current
 	 * query clause.
 	 *
 	 * We avoid unnecessary table joins by allowing each clause to look for