Edit File by line
/home/zeestwma/richards.../wp-inclu...
File: class-wp-tax-query.php
<?php
[0] Fix | Delete
/**
[1] Fix | Delete
* Taxonomy API: WP_Tax_Query class
[2] Fix | Delete
*
[3] Fix | Delete
* @package WordPress
[4] Fix | Delete
* @subpackage Taxonomy
[5] Fix | Delete
* @since 4.4.0
[6] Fix | Delete
*/
[7] Fix | Delete
[8] Fix | Delete
/**
[9] Fix | Delete
* Core class used to implement taxonomy queries for the Taxonomy API.
[10] Fix | Delete
*
[11] Fix | Delete
* Used for generating SQL clauses that filter a primary query according to object
[12] Fix | Delete
* taxonomy terms.
[13] Fix | Delete
*
[14] Fix | Delete
* WP_Tax_Query is a helper that allows primary query classes, such as WP_Query, to filter
[15] Fix | Delete
* their results by object metadata, by generating `JOIN` and `WHERE` subclauses to be
[16] Fix | Delete
* attached to the primary SQL query string.
[17] Fix | Delete
*
[18] Fix | Delete
* @since 3.1.0
[19] Fix | Delete
*/
[20] Fix | Delete
#[AllowDynamicProperties]
[21] Fix | Delete
class WP_Tax_Query {
[22] Fix | Delete
[23] Fix | Delete
/**
[24] Fix | Delete
* Array of taxonomy queries.
[25] Fix | Delete
*
[26] Fix | Delete
* See WP_Tax_Query::__construct() for information on tax query arguments.
[27] Fix | Delete
*
[28] Fix | Delete
* @since 3.1.0
[29] Fix | Delete
* @var array
[30] Fix | Delete
*/
[31] Fix | Delete
public $queries = array();
[32] Fix | Delete
[33] Fix | Delete
/**
[34] Fix | Delete
* The relation between the queries. Can be one of 'AND' or 'OR'.
[35] Fix | Delete
*
[36] Fix | Delete
* @since 3.1.0
[37] Fix | Delete
* @var string
[38] Fix | Delete
*/
[39] Fix | Delete
public $relation;
[40] Fix | Delete
[41] Fix | Delete
/**
[42] Fix | Delete
* Standard response when the query should not return any rows.
[43] Fix | Delete
*
[44] Fix | Delete
* @since 3.2.0
[45] Fix | Delete
* @var string
[46] Fix | Delete
*/
[47] Fix | Delete
private static $no_results = array(
[48] Fix | Delete
'join' => array( '' ),
[49] Fix | Delete
'where' => array( '0 = 1' ),
[50] Fix | Delete
);
[51] Fix | Delete
[52] Fix | Delete
/**
[53] Fix | Delete
* A flat list of table aliases used in the JOIN clauses.
[54] Fix | Delete
*
[55] Fix | Delete
* @since 4.1.0
[56] Fix | Delete
* @var array
[57] Fix | Delete
*/
[58] Fix | Delete
protected $table_aliases = array();
[59] Fix | Delete
[60] Fix | Delete
/**
[61] Fix | Delete
* Terms and taxonomies fetched by this query.
[62] Fix | Delete
*
[63] Fix | Delete
* We store this data in a flat array because they are referenced in a
[64] Fix | Delete
* number of places by WP_Query.
[65] Fix | Delete
*
[66] Fix | Delete
* @since 4.1.0
[67] Fix | Delete
* @var array
[68] Fix | Delete
*/
[69] Fix | Delete
public $queried_terms = array();
[70] Fix | Delete
[71] Fix | Delete
/**
[72] Fix | Delete
* Database table that where the metadata's objects are stored (eg $wpdb->users).
[73] Fix | Delete
*
[74] Fix | Delete
* @since 4.1.0
[75] Fix | Delete
* @var string
[76] Fix | Delete
*/
[77] Fix | Delete
public $primary_table;
[78] Fix | Delete
[79] Fix | Delete
/**
[80] Fix | Delete
* Column in 'primary_table' that represents the ID of the object.
[81] Fix | Delete
*
[82] Fix | Delete
* @since 4.1.0
[83] Fix | Delete
* @var string
[84] Fix | Delete
*/
[85] Fix | Delete
public $primary_id_column;
[86] Fix | Delete
[87] Fix | Delete
/**
[88] Fix | Delete
* Constructor.
[89] Fix | Delete
*
[90] Fix | Delete
* @since 3.1.0
[91] Fix | Delete
* @since 4.1.0 Added support for `$operator` 'NOT EXISTS' and 'EXISTS' values.
[92] Fix | Delete
*
[93] Fix | Delete
* @param array $tax_query {
[94] Fix | Delete
* Array of taxonomy query clauses.
[95] Fix | Delete
*
[96] Fix | Delete
* @type string $relation Optional. The MySQL keyword used to join
[97] Fix | Delete
* the clauses of the query. Accepts 'AND', or 'OR'. Default 'AND'.
[98] Fix | Delete
* @type array ...$0 {
[99] Fix | Delete
* An array of first-order clause parameters, or another fully-formed tax query.
[100] Fix | Delete
*
[101] Fix | Delete
* @type string $taxonomy Taxonomy being queried. Optional when field=term_taxonomy_id.
[102] Fix | Delete
* @type string|int|array $terms Term or terms to filter by.
[103] Fix | Delete
* @type string $field Field to match $terms against. Accepts 'term_id', 'slug',
[104] Fix | Delete
* 'name', or 'term_taxonomy_id'. Default: 'term_id'.
[105] Fix | Delete
* @type string $operator MySQL operator to be used with $terms in the WHERE clause.
[106] Fix | Delete
* Accepts 'AND', 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS'.
[107] Fix | Delete
* Default: 'IN'.
[108] Fix | Delete
* @type bool $include_children Optional. Whether to include child terms.
[109] Fix | Delete
* Requires a $taxonomy. Default: true.
[110] Fix | Delete
* }
[111] Fix | Delete
* }
[112] Fix | Delete
*/
[113] Fix | Delete
public function __construct( $tax_query ) {
[114] Fix | Delete
if ( isset( $tax_query['relation'] ) ) {
[115] Fix | Delete
$this->relation = $this->sanitize_relation( $tax_query['relation'] );
[116] Fix | Delete
} else {
[117] Fix | Delete
$this->relation = 'AND';
[118] Fix | Delete
}
[119] Fix | Delete
[120] Fix | Delete
$this->queries = $this->sanitize_query( $tax_query );
[121] Fix | Delete
}
[122] Fix | Delete
[123] Fix | Delete
/**
[124] Fix | Delete
* Ensures the 'tax_query' argument passed to the class constructor is well-formed.
[125] Fix | Delete
*
[126] Fix | Delete
* Ensures that each query-level clause has a 'relation' key, and that
[127] Fix | Delete
* each first-order clause contains all the necessary keys from `$defaults`.
[128] Fix | Delete
*
[129] Fix | Delete
* @since 4.1.0
[130] Fix | Delete
*
[131] Fix | Delete
* @param array $queries Array of queries clauses.
[132] Fix | Delete
* @return array Sanitized array of query clauses.
[133] Fix | Delete
*/
[134] Fix | Delete
public function sanitize_query( $queries ) {
[135] Fix | Delete
$cleaned_query = array();
[136] Fix | Delete
[137] Fix | Delete
$defaults = array(
[138] Fix | Delete
'taxonomy' => '',
[139] Fix | Delete
'terms' => array(),
[140] Fix | Delete
'field' => 'term_id',
[141] Fix | Delete
'operator' => 'IN',
[142] Fix | Delete
'include_children' => true,
[143] Fix | Delete
);
[144] Fix | Delete
[145] Fix | Delete
foreach ( $queries as $key => $query ) {
[146] Fix | Delete
if ( 'relation' === $key ) {
[147] Fix | Delete
$cleaned_query['relation'] = $this->sanitize_relation( $query );
[148] Fix | Delete
[149] Fix | Delete
// First-order clause.
[150] Fix | Delete
} elseif ( self::is_first_order_clause( $query ) ) {
[151] Fix | Delete
[152] Fix | Delete
$cleaned_clause = array_merge( $defaults, $query );
[153] Fix | Delete
$cleaned_clause['terms'] = (array) $cleaned_clause['terms'];
[154] Fix | Delete
$cleaned_query[] = $cleaned_clause;
[155] Fix | Delete
[156] Fix | Delete
/*
[157] Fix | Delete
* Keep a copy of the clause in the flate
[158] Fix | Delete
* $queried_terms array, for use in WP_Query.
[159] Fix | Delete
*/
[160] Fix | Delete
if ( ! empty( $cleaned_clause['taxonomy'] ) && 'NOT IN' !== $cleaned_clause['operator'] ) {
[161] Fix | Delete
$taxonomy = $cleaned_clause['taxonomy'];
[162] Fix | Delete
if ( ! isset( $this->queried_terms[ $taxonomy ] ) ) {
[163] Fix | Delete
$this->queried_terms[ $taxonomy ] = array();
[164] Fix | Delete
}
[165] Fix | Delete
[166] Fix | Delete
/*
[167] Fix | Delete
* Backward compatibility: Only store the first
[168] Fix | Delete
* 'terms' and 'field' found for a given taxonomy.
[169] Fix | Delete
*/
[170] Fix | Delete
if ( ! empty( $cleaned_clause['terms'] ) && ! isset( $this->queried_terms[ $taxonomy ]['terms'] ) ) {
[171] Fix | Delete
$this->queried_terms[ $taxonomy ]['terms'] = $cleaned_clause['terms'];
[172] Fix | Delete
}
[173] Fix | Delete
[174] Fix | Delete
if ( ! empty( $cleaned_clause['field'] ) && ! isset( $this->queried_terms[ $taxonomy ]['field'] ) ) {
[175] Fix | Delete
$this->queried_terms[ $taxonomy ]['field'] = $cleaned_clause['field'];
[176] Fix | Delete
}
[177] Fix | Delete
}
[178] Fix | Delete
[179] Fix | Delete
// Otherwise, it's a nested query, so we recurse.
[180] Fix | Delete
} elseif ( is_array( $query ) ) {
[181] Fix | Delete
$cleaned_subquery = $this->sanitize_query( $query );
[182] Fix | Delete
[183] Fix | Delete
if ( ! empty( $cleaned_subquery ) ) {
[184] Fix | Delete
// All queries with children must have a relation.
[185] Fix | Delete
if ( ! isset( $cleaned_subquery['relation'] ) ) {
[186] Fix | Delete
$cleaned_subquery['relation'] = 'AND';
[187] Fix | Delete
}
[188] Fix | Delete
[189] Fix | Delete
$cleaned_query[] = $cleaned_subquery;
[190] Fix | Delete
}
[191] Fix | Delete
}
[192] Fix | Delete
}
[193] Fix | Delete
[194] Fix | Delete
return $cleaned_query;
[195] Fix | Delete
}
[196] Fix | Delete
[197] Fix | Delete
/**
[198] Fix | Delete
* Sanitizes a 'relation' operator.
[199] Fix | Delete
*
[200] Fix | Delete
* @since 4.1.0
[201] Fix | Delete
*
[202] Fix | Delete
* @param string $relation Raw relation key from the query argument.
[203] Fix | Delete
* @return string Sanitized relation. Either 'AND' or 'OR'.
[204] Fix | Delete
*/
[205] Fix | Delete
public function sanitize_relation( $relation ) {
[206] Fix | Delete
if ( 'OR' === strtoupper( $relation ) ) {
[207] Fix | Delete
return 'OR';
[208] Fix | Delete
} else {
[209] Fix | Delete
return 'AND';
[210] Fix | Delete
}
[211] Fix | Delete
}
[212] Fix | Delete
[213] Fix | Delete
/**
[214] Fix | Delete
* Determines whether a clause is first-order.
[215] Fix | Delete
*
[216] Fix | Delete
* A "first-order" clause is one that contains any of the first-order
[217] Fix | Delete
* clause keys ('terms', 'taxonomy', 'include_children', 'field',
[218] Fix | Delete
* 'operator'). An empty clause also counts as a first-order clause,
[219] Fix | Delete
* for backward compatibility. Any clause that doesn't meet this is
[220] Fix | Delete
* determined, by process of elimination, to be a higher-order query.
[221] Fix | Delete
*
[222] Fix | Delete
* @since 4.1.0
[223] Fix | Delete
*
[224] Fix | Delete
* @param array $query Tax query arguments.
[225] Fix | Delete
* @return bool Whether the query clause is a first-order clause.
[226] Fix | Delete
*/
[227] Fix | Delete
protected static function is_first_order_clause( $query ) {
[228] Fix | Delete
return is_array( $query ) && ( empty( $query ) || array_key_exists( 'terms', $query ) || array_key_exists( 'taxonomy', $query ) || array_key_exists( 'include_children', $query ) || array_key_exists( 'field', $query ) || array_key_exists( 'operator', $query ) );
[229] Fix | Delete
}
[230] Fix | Delete
[231] Fix | Delete
/**
[232] Fix | Delete
* Generates SQL clauses to be appended to a main query.
[233] Fix | Delete
*
[234] Fix | Delete
* @since 3.1.0
[235] Fix | Delete
*
[236] Fix | Delete
* @param string $primary_table Database table where the object being filtered is stored (eg wp_users).
[237] Fix | Delete
* @param string $primary_id_column ID column for the filtered object in $primary_table.
[238] Fix | Delete
* @return string[] {
[239] Fix | Delete
* Array containing JOIN and WHERE SQL clauses to append to the main query.
[240] Fix | Delete
*
[241] Fix | Delete
* @type string $join SQL fragment to append to the main JOIN clause.
[242] Fix | Delete
* @type string $where SQL fragment to append to the main WHERE clause.
[243] Fix | Delete
* }
[244] Fix | Delete
*/
[245] Fix | Delete
public function get_sql( $primary_table, $primary_id_column ) {
[246] Fix | Delete
$this->primary_table = $primary_table;
[247] Fix | Delete
$this->primary_id_column = $primary_id_column;
[248] Fix | Delete
[249] Fix | Delete
return $this->get_sql_clauses();
[250] Fix | Delete
}
[251] Fix | Delete
[252] Fix | Delete
/**
[253] Fix | Delete
* Generates SQL clauses to be appended to a main query.
[254] Fix | Delete
*
[255] Fix | Delete
* Called by the public WP_Tax_Query::get_sql(), this method
[256] Fix | Delete
* is abstracted out to maintain parity with the other Query classes.
[257] Fix | Delete
*
[258] Fix | Delete
* @since 4.1.0
[259] Fix | Delete
*
[260] Fix | Delete
* @return string[] {
[261] Fix | Delete
* Array containing JOIN and WHERE SQL clauses to append to the main query.
[262] Fix | Delete
*
[263] Fix | Delete
* @type string $join SQL fragment to append to the main JOIN clause.
[264] Fix | Delete
* @type string $where SQL fragment to append to the main WHERE clause.
[265] Fix | Delete
* }
[266] Fix | Delete
*/
[267] Fix | Delete
protected function get_sql_clauses() {
[268] Fix | Delete
/*
[269] Fix | Delete
* $queries are passed by reference to get_sql_for_query() for recursion.
[270] Fix | Delete
* To keep $this->queries unaltered, pass a copy.
[271] Fix | Delete
*/
[272] Fix | Delete
$queries = $this->queries;
[273] Fix | Delete
$sql = $this->get_sql_for_query( $queries );
[274] Fix | Delete
[275] Fix | Delete
if ( ! empty( $sql['where'] ) ) {
[276] Fix | Delete
$sql['where'] = ' AND ' . $sql['where'];
[277] Fix | Delete
}
[278] Fix | Delete
[279] Fix | Delete
return $sql;
[280] Fix | Delete
}
[281] Fix | Delete
[282] Fix | Delete
/**
[283] Fix | Delete
* Generates SQL clauses for a single query array.
[284] Fix | Delete
*
[285] Fix | Delete
* If nested subqueries are found, this method recurses the tree to
[286] Fix | Delete
* produce the properly nested SQL.
[287] Fix | Delete
*
[288] Fix | Delete
* @since 4.1.0
[289] Fix | Delete
*
[290] Fix | Delete
* @param array $query Query to parse (passed by reference).
[291] Fix | Delete
* @param int $depth Optional. Number of tree levels deep we currently are.
[292] Fix | Delete
* Used to calculate indentation. Default 0.
[293] Fix | Delete
* @return string[] {
[294] Fix | Delete
* Array containing JOIN and WHERE SQL clauses to append to a single query array.
[295] Fix | Delete
*
[296] Fix | Delete
* @type string $join SQL fragment to append to the main JOIN clause.
[297] Fix | Delete
* @type string $where SQL fragment to append to the main WHERE clause.
[298] Fix | Delete
* }
[299] Fix | Delete
*/
[300] Fix | Delete
protected function get_sql_for_query( &$query, $depth = 0 ) {
[301] Fix | Delete
$sql_chunks = array(
[302] Fix | Delete
'join' => array(),
[303] Fix | Delete
'where' => array(),
[304] Fix | Delete
);
[305] Fix | Delete
[306] Fix | Delete
$sql = array(
[307] Fix | Delete
'join' => '',
[308] Fix | Delete
'where' => '',
[309] Fix | Delete
);
[310] Fix | Delete
[311] Fix | Delete
$indent = '';
[312] Fix | Delete
for ( $i = 0; $i < $depth; $i++ ) {
[313] Fix | Delete
$indent .= ' ';
[314] Fix | Delete
}
[315] Fix | Delete
[316] Fix | Delete
foreach ( $query as $key => &$clause ) {
[317] Fix | Delete
if ( 'relation' === $key ) {
[318] Fix | Delete
$relation = $query['relation'];
[319] Fix | Delete
} elseif ( is_array( $clause ) ) {
[320] Fix | Delete
[321] Fix | Delete
// This is a first-order clause.
[322] Fix | Delete
if ( $this->is_first_order_clause( $clause ) ) {
[323] Fix | Delete
$clause_sql = $this->get_sql_for_clause( $clause, $query );
[324] Fix | Delete
[325] Fix | Delete
$where_count = count( $clause_sql['where'] );
[326] Fix | Delete
if ( ! $where_count ) {
[327] Fix | Delete
$sql_chunks['where'][] = '';
[328] Fix | Delete
} elseif ( 1 === $where_count ) {
[329] Fix | Delete
$sql_chunks['where'][] = $clause_sql['where'][0];
[330] Fix | Delete
} else {
[331] Fix | Delete
$sql_chunks['where'][] = '( ' . implode( ' AND ', $clause_sql['where'] ) . ' )';
[332] Fix | Delete
}
[333] Fix | Delete
[334] Fix | Delete
$sql_chunks['join'] = array_merge( $sql_chunks['join'], $clause_sql['join'] );
[335] Fix | Delete
// This is a subquery, so we recurse.
[336] Fix | Delete
} else {
[337] Fix | Delete
$clause_sql = $this->get_sql_for_query( $clause, $depth + 1 );
[338] Fix | Delete
[339] Fix | Delete
$sql_chunks['where'][] = $clause_sql['where'];
[340] Fix | Delete
$sql_chunks['join'][] = $clause_sql['join'];
[341] Fix | Delete
}
[342] Fix | Delete
}
[343] Fix | Delete
}
[344] Fix | Delete
[345] Fix | Delete
// Filter to remove empties.
[346] Fix | Delete
$sql_chunks['join'] = array_filter( $sql_chunks['join'] );
[347] Fix | Delete
$sql_chunks['where'] = array_filter( $sql_chunks['where'] );
[348] Fix | Delete
[349] Fix | Delete
if ( empty( $relation ) ) {
[350] Fix | Delete
$relation = 'AND';
[351] Fix | Delete
}
[352] Fix | Delete
[353] Fix | Delete
// Filter duplicate JOIN clauses and combine into a single string.
[354] Fix | Delete
if ( ! empty( $sql_chunks['join'] ) ) {
[355] Fix | Delete
$sql['join'] = implode( ' ', array_unique( $sql_chunks['join'] ) );
[356] Fix | Delete
}
[357] Fix | Delete
[358] Fix | Delete
// Generate a single WHERE clause with proper brackets and indentation.
[359] Fix | Delete
if ( ! empty( $sql_chunks['where'] ) ) {
[360] Fix | Delete
$sql['where'] = '( ' . "\n " . $indent . implode( ' ' . "\n " . $indent . $relation . ' ' . "\n " . $indent, $sql_chunks['where'] ) . "\n" . $indent . ')';
[361] Fix | Delete
}
[362] Fix | Delete
[363] Fix | Delete
return $sql;
[364] Fix | Delete
}
[365] Fix | Delete
[366] Fix | Delete
/**
[367] Fix | Delete
* Generates SQL JOIN and WHERE clauses for a "first-order" query clause.
[368] Fix | Delete
*
[369] Fix | Delete
* @since 4.1.0
[370] Fix | Delete
*
[371] Fix | Delete
* @global wpdb $wpdb The WordPress database abstraction object.
[372] Fix | Delete
*
[373] Fix | Delete
* @param array $clause Query clause (passed by reference).
[374] Fix | Delete
* @param array $parent_query Parent query array.
[375] Fix | Delete
* @return array {
[376] Fix | Delete
* Array containing JOIN and WHERE SQL clauses to append to a first-order query.
[377] Fix | Delete
*
[378] Fix | Delete
* @type string[] $join Array of SQL fragments to append to the main JOIN clause.
[379] Fix | Delete
* @type string[] $where Array of SQL fragments to append to the main WHERE clause.
[380] Fix | Delete
* }
[381] Fix | Delete
*/
[382] Fix | Delete
public function get_sql_for_clause( &$clause, $parent_query ) {
[383] Fix | Delete
global $wpdb;
[384] Fix | Delete
[385] Fix | Delete
$sql = array(
[386] Fix | Delete
'where' => array(),
[387] Fix | Delete
'join' => array(),
[388] Fix | Delete
);
[389] Fix | Delete
[390] Fix | Delete
$join = '';
[391] Fix | Delete
$where = '';
[392] Fix | Delete
[393] Fix | Delete
$this->clean_query( $clause );
[394] Fix | Delete
[395] Fix | Delete
if ( is_wp_error( $clause ) ) {
[396] Fix | Delete
return self::$no_results;
[397] Fix | Delete
}
[398] Fix | Delete
[399] Fix | Delete
$terms = $clause['terms'];
[400] Fix | Delete
$operator = strtoupper( $clause['operator'] );
[401] Fix | Delete
[402] Fix | Delete
if ( 'IN' === $operator ) {
[403] Fix | Delete
[404] Fix | Delete
if ( empty( $terms ) ) {
[405] Fix | Delete
return self::$no_results;
[406] Fix | Delete
}
[407] Fix | Delete
[408] Fix | Delete
$terms = implode( ',', $terms );
[409] Fix | Delete
[410] Fix | Delete
/*
[411] Fix | Delete
* Before creating another table join, see if this clause has a
[412] Fix | Delete
* sibling with an existing join that can be shared.
[413] Fix | Delete
*/
[414] Fix | Delete
$alias = $this->find_compatible_table_alias( $clause, $parent_query );
[415] Fix | Delete
if ( false === $alias ) {
[416] Fix | Delete
$i = count( $this->table_aliases );
[417] Fix | Delete
$alias = $i ? 'tt' . $i : $wpdb->term_relationships;
[418] Fix | Delete
[419] Fix | Delete
// Store the alias as part of a flat array to build future iterators.
[420] Fix | Delete
$this->table_aliases[] = $alias;
[421] Fix | Delete
[422] Fix | Delete
// Store the alias with this clause, so later siblings can use it.
[423] Fix | Delete
$clause['alias'] = $alias;
[424] Fix | Delete
[425] Fix | Delete
$join .= " LEFT JOIN $wpdb->term_relationships";
[426] Fix | Delete
$join .= $i ? " AS $alias" : '';
[427] Fix | Delete
$join .= " ON ($this->primary_table.$this->primary_id_column = $alias.object_id)";
[428] Fix | Delete
}
[429] Fix | Delete
[430] Fix | Delete
$where = "$alias.term_taxonomy_id $operator ($terms)";
[431] Fix | Delete
[432] Fix | Delete
} elseif ( 'NOT IN' === $operator ) {
[433] Fix | Delete
[434] Fix | Delete
if ( empty( $terms ) ) {
[435] Fix | Delete
return $sql;
[436] Fix | Delete
}
[437] Fix | Delete
[438] Fix | Delete
$terms = implode( ',', $terms );
[439] Fix | Delete
[440] Fix | Delete
$where = "$this->primary_table.$this->primary_id_column NOT IN (
[441] Fix | Delete
SELECT object_id
[442] Fix | Delete
FROM $wpdb->term_relationships
[443] Fix | Delete
WHERE term_taxonomy_id IN ($terms)
[444] Fix | Delete
)";
[445] Fix | Delete
[446] Fix | Delete
} elseif ( 'AND' === $operator ) {
[447] Fix | Delete
[448] Fix | Delete
if ( empty( $terms ) ) {
[449] Fix | Delete
return $sql;
[450] Fix | Delete
}
[451] Fix | Delete
[452] Fix | Delete
$num_terms = count( $terms );
[453] Fix | Delete
[454] Fix | Delete
$terms = implode( ',', $terms );
[455] Fix | Delete
[456] Fix | Delete
$where = "(
[457] Fix | Delete
SELECT COUNT(1)
[458] Fix | Delete
FROM $wpdb->term_relationships
[459] Fix | Delete
WHERE term_taxonomy_id IN ($terms)
[460] Fix | Delete
AND object_id = $this->primary_table.$this->primary_id_column
[461] Fix | Delete
) = $num_terms";
[462] Fix | Delete
[463] Fix | Delete
} elseif ( 'NOT EXISTS' === $operator || 'EXISTS' === $operator ) {
[464] Fix | Delete
[465] Fix | Delete
$where = $wpdb->prepare(
[466] Fix | Delete
"$operator (
[467] Fix | Delete
SELECT 1
[468] Fix | Delete
FROM $wpdb->term_relationships
[469] Fix | Delete
INNER JOIN $wpdb->term_taxonomy
[470] Fix | Delete
ON $wpdb->term_taxonomy.term_taxonomy_id = $wpdb->term_relationships.term_taxonomy_id
[471] Fix | Delete
WHERE $wpdb->term_taxonomy.taxonomy = %s
[472] Fix | Delete
AND $wpdb->term_relationships.object_id = $this->primary_table.$this->primary_id_column
[473] Fix | Delete
)",
[474] Fix | Delete
$clause['taxonomy']
[475] Fix | Delete
);
[476] Fix | Delete
[477] Fix | Delete
}
[478] Fix | Delete
[479] Fix | Delete
$sql['join'][] = $join;
[480] Fix | Delete
$sql['where'][] = $where;
[481] Fix | Delete
return $sql;
[482] Fix | Delete
}
[483] Fix | Delete
[484] Fix | Delete
/**
[485] Fix | Delete
* Identifies an existing table alias that is compatible with the current query clause.
[486] Fix | Delete
*
[487] Fix | Delete
* We avoid unnecessary table joins by allowing each clause to look for
[488] Fix | Delete
* an existing table alias that is compatible with the query that it
[489] Fix | Delete
* needs to perform.
[490] Fix | Delete
*
[491] Fix | Delete
* An existing alias is compatible if (a) it is a sibling of `$clause`
[492] Fix | Delete
* (ie, it's under the scope of the same relation), and (b) the combination
[493] Fix | Delete
* of operator and relation between the clauses allows for a shared table
[494] Fix | Delete
* join. In the case of WP_Tax_Query, this only applies to 'IN'
[495] Fix | Delete
* clauses that are connected by the relation 'OR'.
[496] Fix | Delete
*
[497] Fix | Delete
* @since 4.1.0
[498] Fix | Delete
*
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function