Tribe__Repository::where_multi( $fields, $compare, $value, $where_relation = 'OR', $value_relation = 'OR' )
{@inheritDoc}
Source
File: src/Tribe/Repository.php
public function where_multi( array $fields, $compare, $value, $where_relation = 'OR', $value_relation = 'OR' ) {
$compare = strtoupper( trim( $compare ) );
// Check each value is compatible with the comparison operator.
$values = (array) $value;
foreach ( $values as $v ) {
$this->validate_operator_and_values( $compare, 'where_multi', $v );
}
global $wpdb;
if ( in_array( $compare, [ 'LIKE', 'NOT LIKE' ], true ) ) {
$values = $this->prepare_like_string( $values );
}
$where_relation = strtoupper( trim( $where_relation ) );
$this->validate_relation( $where_relation );
$value_relation = strtoupper( trim( $value_relation ) );
$this->validate_relation( $value_relation );
$post_fields = [];
$taxonomies = [];
foreach ( $fields as $field ) {
if ( $this->is_a_post_field( $field ) ) {
$post_fields[] = $field;
} elseif ( array_key_exists( $field, $this->simple_tax_schema ) ) {
// Handle simple tax schema aliases.
$schema = $this->simple_tax_schema[ $field ]['taxonomy'];
if ( ! is_array( $schema ) ) {
$taxonomies[] = $schema;
continue;
}
// If doing an AND where relation, pass all taxonomies in to be grouped with OR.
if ( 'AND' === $where_relation ) {
$this->where_multi( $schema, $compare, $value, 'OR', $value_relation );
continue;
}
foreach ( $schema as $taxonomy ) {
$taxonomies[] = $taxonomy;
}
} elseif ( array_key_exists( $field, $this->simple_meta_schema ) ) {
// Handle simple meta schema aliases.
$schema = $this->simple_meta_schema[ $field ]['meta_key'];
if ( ! is_array( $schema ) ) {
$custom_fields[] = $schema;
continue;
}
// If doing an AND where relation, pass all meta keys in to be grouped with OR.
if ( 'AND' === $where_relation ) {
$this->where_multi( $schema, $compare, $value, 'OR', $value_relation );
continue;
}
foreach ( $schema as $meta_key ) {
$custom_fields[] = $meta_key;
}
} elseif ( $this->is_a_taxonomy( $field ) ) {
$taxonomies[] = $field;
} else {
$custom_fields[] = $field;
}
}
$value_formats = [];
foreach ( $values as $v ) {
$value_format = '%d';
if ( is_string( $v ) ) {
$value_format = '%s';
} elseif ( (int) $v !== (float) $v ) {
$value_format = '%f';
}
$value_formats[] = $value_format;
}
// If the value formats differ then treat all of them as strings.
if ( count( array_unique( $value_formats ) ) > 1 ) {
$value_format = '%s';
} else {
$value_format = reset( $value_formats );
}
$where = [];
if ( ! empty( $post_fields ) ) {
$post_fields = array_map( static function ( $post_field ) use ( $wpdb ) {
return "{$wpdb->posts}.$post_field";
}, $post_fields );
$post_fields_where = $this->build_fields_where_clause(
$post_fields,
$compare,
$values,
$value_format,
$where_relation,
$value_relation
);
$wheres[] = $post_fields_where;
}
if ( ! empty( $taxonomies ) ) {
$all_matching_term_ids = [];
$taxonomy_values = $values;
if ( in_array( $compare, [ 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ], true ) ) {
// We can use multiple values in the same query.
$taxonomy_values = [ $values ];
}
foreach ( $taxonomy_values as $taxonomy_value ){
$matching_term_ids = $this->fetch_taxonomy_terms_matches(
$taxonomies,
$compare,
$taxonomy_value,
$where_relation,
$value_format
);
if ( empty( $matching_term_ids ) ) {
if ( 'AND' === $value_relation ) {
// No reason to waste any more time.
$this->void_query = true;
return $this;
}
continue;
}
$all_matching_term_ids[] = $matching_term_ids;
}
$intersection = count( $all_matching_term_ids ) > 1
? array_intersect( ...$all_matching_term_ids )
: reset( $all_matching_term_ids );
if ( 'AND' === $where_relation && 0 === count( $intersection ) ) {
// Let's not waste any more time.
$this->void_query = true;
return $this;
}
$merge = count( $all_matching_term_ids ) > 1
? array_unique( array_merge( ...$all_matching_term_ids ) )
: (array) reset( $all_matching_term_ids );
$matching_term_ids = $where_relation === 'OR' ? array_filter( $merge ) : array_filter( $intersection );
if ( 'AND' === $where_relation || ! empty( $matching_term_ids ) ) {
// Let's not add WHERE and JOIN clauses if there is nothing to add.
$tt_alias = 'tribe_tt_' . self::$alias_counter ++;
$this->filter_query->join(
"JOIN {$wpdb->term_relationships} {$tt_alias} ON {$wpdb->posts}.ID = {$tt_alias}.object_id"
);
$matching_term_ids_interval = implode( ',', $matching_term_ids );
$wheres[] = "{$tt_alias}.term_taxonomy_id IN ({$matching_term_ids_interval})";
}
}
if ( ! empty( $custom_fields ) ) {
$meta_alias = 'tribe_meta_' . self::$alias_counter ++;
$custom_fields = array_map( static function ( $custom_field ) use ( $wpdb, $meta_alias ) {
return $wpdb->prepare(
"{$meta_alias}.meta_key = %s AND {$meta_alias}.meta_value",
$custom_field
);
}, $custom_fields );
$meta_where = $this->build_fields_where_clause(
$custom_fields,
$compare,
$values,
$value_format,
$where_relation,
$value_relation
);
$this->filter_query->join(
"JOIN {$wpdb->postmeta} {$meta_alias} ON {$wpdb->posts}.ID = {$meta_alias}.post_id"
);
$wheres[] = $meta_where;
}
$this->filter_query->where( implode( " {$where_relation} ", $wheres ) );
return $this;
}