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;
	}