WordPress.org

Make WordPress Core

Ticket #43446: 43446.2.diff

File 43446.2.diff, 5.2 KB (added by soulseekah, 20 months ago)

!=, NOT LIKE, IN, NOT IN, EXISTS, NOT EXISTS, REGEXP, NOT REGEXP, RLIKE

  • src/wp-includes/class-wp-meta-query.php

    diff --git src/wp-includes/class-wp-meta-query.php src/wp-includes/class-wp-meta-query.php
    index d9234c2..b48c58f 100644
    class WP_Meta_Query { 
    239239                 * the rest of the meta_query).
    240240                 */
    241241                $primary_meta_query = array();
    242                 foreach ( array( 'key', 'compare', 'type', 'compare_key' ) as $key ) {
     242                foreach ( array( 'key', 'compare', 'type', 'compare_key', 'type_key' ) as $key ) {
    243243                        if ( ! empty( $qv[ "meta_$key" ] ) ) {
    244244                                $primary_meta_query[ $key ] = $qv[ "meta_$key" ];
    245245                        }
    class WP_Meta_Query { 
    521521                        $clause['compare'] = '=';
    522522                }
    523523
    524                 if ( isset( $clause['compare_key'] ) && 'LIKE' === strtoupper( $clause['compare_key'] ) ) {
     524                if ( isset( $clause['compare_key'] ) ) {
    525525                        $clause['compare_key'] = strtoupper( $clause['compare_key'] );
    526526                } else {
     527                        $clause['compare_key'] = isset( $clause['key'] ) && is_array( $clause['key'] ) ? 'IN' : '=';
     528                }
     529
     530                if ( ! in_array(
     531                        $clause['compare_key'], array(
     532                                '=',
     533                                '!=',
     534                                'LIKE',
     535                                'NOT LIKE',
     536                                'IN',
     537                                'NOT IN',
     538                                'EXISTS',
     539                                'NOT EXISTS',
     540                                'RLIKE',
     541                                'REGEXP',
     542                                'NOT REGEXP',
     543                        )
     544                ) ) {
    527545                        $clause['compare_key'] = '=';
    528546                }
    529547
    class WP_Meta_Query { 
    592610                        if ( 'NOT EXISTS' === $meta_compare ) {
    593611                                $sql_chunks['where'][] = $alias . '.' . $this->meta_id_column . ' IS NULL';
    594612                        } else {
    595                                 if ( 'LIKE' === $meta_compare_key ) {
    596                                         $sql_chunks['where'][] = $wpdb->prepare( "$alias.meta_key LIKE %s", '%' . $wpdb->esc_like( trim( $clause['key'] ) ) . '%' );
    597                                 } else {
    598                                         $sql_chunks['where'][] = $wpdb->prepare( "$alias.meta_key = %s", trim( $clause['key'] ) );
     613                                /**
     614                                 * Reusable clauses for negative operators.
     615                                 */
     616                                if ( in_array( $meta_compare_key, array( '!=', 'NOT IN', 'NOT LIKE', 'NOT EXISTS', 'NOT REGEXP' ) ) ) {
     617                                        $i     = count( $this->table_aliases );
     618                                        $subquery_alias = $i ? 'mt' . $i : $this->meta_table;
     619                                        $this->table_aliases[] = $subquery_alias;
     620
     621                                        $meta_compare_string_start = "NOT EXISTS (";
     622                                        $meta_compare_string_start    .= "SELECT 1 FROM $wpdb->postmeta $subquery_alias ";
     623                                        $meta_compare_string_start    .= "WHERE $subquery_alias.post_ID = $alias.post_ID ";
     624                                        // Subquery operator clause goes here
     625                                        $meta_compare_string_end       = 'LIMIT 1';
     626                                        $meta_compare_string_end   .= ")";
    599627                                }
     628
     629                                switch ( $meta_compare_key ) {
     630                                        case '=':
     631                                        case 'EXISTS':
     632                                                $where = $wpdb->prepare( "$alias.meta_key = %s", trim( $clause['key'] ) );
     633                                                break;
     634                                        case 'LIKE':
     635                                                $meta_compare_value = '%' . $wpdb->esc_like( trim( $clause['key'] ) ) . '%';
     636                                                $where = $wpdb->prepare( "$alias.meta_key LIKE %s", $meta_compare_value );
     637                                                break;
     638                                        case 'IN':
     639                                                $operator = $meta_compare_key;
     640                                                $meta_compare_string = "$alias.meta_key $operator (" . substr( str_repeat( ',%s', count( $clause['key'] ) ), 1 ) . ')';
     641                                                $where = $wpdb->prepare( $meta_compare_string, $clause['key'] );
     642                                                break;
     643                                        case 'RLIKE':
     644                                        case 'REGEXP':
     645                                                $operator = $meta_compare_key;
     646                                                if ( isset( $clause['type_key'] ) && strtoupper( $clause['type_key'] ) == 'BINARY' ) {
     647                                                        $cast = 'BINARY';
     648                                                } else {
     649                                                        $cast = '';
     650                                                }
     651                                                $where = $wpdb->prepare( "$alias.meta_key $operator $cast %s", trim( $clause['key'] ) );
     652                                                break;
     653
     654                                        /**
     655                                         * In joined clauses negative operators have to be nested
     656                                         * into a NOT EXISTS clause and flipped. Otherwise, non-matching results
     657                                         * containing the post_IDs will be returned, rendering the
     658                                         * operator ineffective.
     659                                         */
     660                                        case '!=':
     661                                        case 'NOT EXISTS':
     662                                                $meta_compare_string = $meta_compare_string_start
     663                                                                     . "AND $subquery_alias.meta_key = %s "
     664                                                                     . $meta_compare_string_end;
     665                                                $where = $wpdb->prepare( $meta_compare_string, $clause['key'] );
     666                                                break;
     667                                        case 'NOT LIKE':
     668                                                $meta_compare_string = $meta_compare_string_start
     669                                                                     . "AND $subquery_alias.meta_key LIKE %s "
     670                                                                     . $meta_compare_string_end;
     671
     672                                                $meta_compare_value = '%' . $wpdb->esc_like( trim( $clause['key'] ) ) . '%';
     673                                                $where = $wpdb->prepare( $meta_compare_string, $meta_compare_value );
     674                                                break;
     675                                        case 'NOT IN':
     676                                                $meta_compare_string = $meta_compare_string_start
     677                                                                     . "AND $subquery_alias.meta_key IN "
     678                                                                     . '(' . substr( str_repeat( ',%s', count( $clause['key'] ) ), 1 ) . ') '
     679                                                                     . $meta_compare_string_end;
     680
     681                                                $where = $wpdb->prepare( $meta_compare_string, $clause['key'] );
     682                                                break;
     683                                        case 'NOT REGEXP':
     684                                                $operator = $meta_compare_key;
     685                                                if ( isset( $clause['type_key'] ) && strtoupper( $clause['type_key'] ) == 'BINARY' ) {
     686                                                        $cast = 'BINARY';
     687                                                } else {
     688                                                        $cast = '';
     689                                                }
     690
     691                                                $meta_compare_string = $meta_compare_string_start
     692                                                                     . "AND $subquery_alias.meta_key REGEXP $cast %s "
     693                                                                     . $meta_compare_string_end;
     694
     695                                                $where = $wpdb->prepare( $meta_compare_string, $clause['key'] );
     696                                                break;
     697                                }
     698
     699                                $sql_chunks['where'][] = $where;
    600700                        }
    601701                }
    602702