WordPress.org

Make WordPress Core

Ticket #37289: patch.diff

File patch.diff, 21.5 KB (added by michalzuber, 5 years ago)
  • wp-includes/category-template.php

    diff --git a/wp-includes/category-template.php b/wp-includes/category-template.php
    index a8d7941..a425b5d 100644
    a b function get_the_category_list( $separator = '', $parents='', $post_id = false ) 
    219219        } else {
    220220                $i = 0;
    221221                foreach ( $categories as $category ) {
     222            if ( ! is_object( $category ) )
     223                continue;
     224
    222225                        if ( 0 < $i )
    223226                                $thelist .= $separator;
    224227                        switch ( strtolower( $parents ) ) {
    function get_the_tag_list( $before = '', $sep = '', $after = '', $id = 0 ) { 
    10951098function the_tags( $before = null, $sep = ', ', $after = '' ) {
    10961099        if ( null === $before )
    10971100                $before = __('Tags: ');
    1098         echo get_the_tag_list($before, $sep, $after);
     1101        $tags = get_the_tag_list($before, $sep, $after);
     1102    echo is_wp_error( $tags ) ? '' : $tags;
    10991103}
    11001104
    11011105/**
  • wp-includes/taxonomy.php

    diff --git a/wp-includes/taxonomy.php b/wp-includes/taxonomy.php
    index 4328a36..fdf7297 100644
    a b function get_tax_sql( $tax_query, $primary_table, $primary_id_column ) { 
    654654}
    655655
    656656/**
    657  * Class for generating SQL clauses that filter a primary query according to object taxonomy terms.
    658  *
    659  * `WP_Tax_Query` is a helper that allows primary query classes, such as WP_Query, to filter
    660  * their results by object metadata, by generating `JOIN` and `WHERE` subclauses to be attached
    661  * to the primary SQL query string.
    662  *
    663  * @since 3.1.0
    664  */
    665 class WP_Tax_Query {
    666 
    667         /**
    668          * Array of taxonomy queries.
    669          *
    670          * See {@see WP_Tax_Query::__construct()} for information on tax query arguments.
    671          *
    672          * @since 3.1.0
    673          * @access public
    674          * @var array
    675          */
    676         public $queries = array();
    677 
    678         /**
    679          * The relation between the queries. Can be one of 'AND' or 'OR'.
    680          *
    681          * @since 3.1.0
    682          * @access public
    683          * @var string
    684          */
    685         public $relation;
    686 
    687         /**
    688          * Standard response when the query should not return any rows.
    689          *
    690          * @since 3.2.0
    691          *
    692          * @static
    693          * @access private
    694          * @var string
    695          */
    696         private static $no_results = array( 'join' => array( '' ), 'where' => array( '0 = 1' ) );
    697 
    698         /**
    699          * A flat list of table aliases used in the JOIN clauses.
    700          *
    701          * @since 4.1.0
    702          * @access protected
    703          * @var array
    704          */
    705         protected $table_aliases = array();
    706 
    707         /**
    708          * Terms and taxonomies fetched by this query.
    709          *
    710          * We store this data in a flat array because they are referenced in a
    711          * number of places by WP_Query.
    712          *
    713          * @since 4.1.0
    714          * @access public
    715          * @var array
    716          */
    717         public $queried_terms = array();
    718 
    719         /**
    720          * Database table that where the metadata's objects are stored (eg $wpdb->users).
    721          *
    722          * @since 4.1.0
    723          * @access public
    724          * @var string
    725          */
    726         public $primary_table;
    727 
    728         /**
    729          * Column in 'primary_table' that represents the ID of the object.
    730          *
    731          * @since 4.1.0
    732          * @access public
    733          * @var string
    734          */
    735         public $primary_id_column;
    736 
    737         /**
    738          * Constructor.
    739          *
    740          * @since 3.1.0
    741          * @since 4.1.0 Added support for `$operator` 'NOT EXISTS' and 'EXISTS' values.
    742          * @access public
    743          *
    744          * @param array $tax_query {
    745          *     Array of taxonomy query clauses.
    746          *
    747          *     @type string $relation Optional. The MySQL keyword used to join
    748          *                            the clauses of the query. Accepts 'AND', or 'OR'. Default 'AND'.
    749          *     @type array {
    750          *         Optional. An array of first-order clause parameters, or another fully-formed tax query.
    751          *
    752          *         @type string           $taxonomy         Taxonomy being queried. Optional when field=term_taxonomy_id.
    753          *         @type string|int|array $terms            Term or terms to filter by.
    754          *         @type string           $field            Field to match $terms against. Accepts 'term_id', 'slug',
    755          *                                                 'name', or 'term_taxonomy_id'. Default: 'term_id'.
    756          *         @type string           $operator         MySQL operator to be used with $terms in the WHERE clause.
    757          *                                                  Accepts 'AND', 'IN', 'NOT IN', 'EXISTS', 'NOT EXISTS'.
    758          *                                                  Default: 'IN'.
    759          *         @type bool             $include_children Optional. Whether to include child terms.
    760          *                                                  Requires a $taxonomy. Default: true.
    761          *     }
    762          * }
    763          */
    764         public function __construct( $tax_query ) {
    765                 if ( isset( $tax_query['relation'] ) ) {
    766                         $this->relation = $this->sanitize_relation( $tax_query['relation'] );
    767                 } else {
    768                         $this->relation = 'AND';
    769                 }
    770 
    771                 $this->queries = $this->sanitize_query( $tax_query );
    772         }
    773 
    774         /**
    775          * Ensure the 'tax_query' argument passed to the class constructor is well-formed.
    776          *
    777          * Ensures that each query-level clause has a 'relation' key, and that
    778          * each first-order clause contains all the necessary keys from `$defaults`.
    779          *
    780          * @since 4.1.0
    781          * @access public
    782          *
    783          * @param array $queries Array of queries clauses.
    784          * @return array Sanitized array of query clauses.
    785          */
    786         public function sanitize_query( $queries ) {
    787                 $cleaned_query = array();
    788 
    789                 $defaults = array(
    790                         'taxonomy' => '',
    791                         'terms' => array(),
    792                         'field' => 'term_id',
    793                         'operator' => 'IN',
    794                         'include_children' => true,
    795                 );
    796 
    797                 foreach ( $queries as $key => $query ) {
    798                         if ( 'relation' === $key ) {
    799                                 $cleaned_query['relation'] = $this->sanitize_relation( $query );
    800 
    801                         // First-order clause.
    802                         } elseif ( self::is_first_order_clause( $query ) ) {
    803 
    804                                 $cleaned_clause = array_merge( $defaults, $query );
    805                                 $cleaned_clause['terms'] = (array) $cleaned_clause['terms'];
    806                                 $cleaned_query[] = $cleaned_clause;
    807 
    808                                 /*
    809                                  * Keep a copy of the clause in the flate
    810                                  * $queried_terms array, for use in WP_Query.
    811                                  */
    812                                 if ( ! empty( $cleaned_clause['taxonomy'] ) && 'NOT IN' !== $cleaned_clause['operator'] ) {
    813                                         $taxonomy = $cleaned_clause['taxonomy'];
    814                                         if ( ! isset( $this->queried_terms[ $taxonomy ] ) ) {
    815                                                 $this->queried_terms[ $taxonomy ] = array();
    816                                         }
    817 
    818                                         /*
    819                                          * Backward compatibility: Only store the first
    820                                          * 'terms' and 'field' found for a given taxonomy.
    821                                          */
    822                                         if ( ! empty( $cleaned_clause['terms'] ) && ! isset( $this->queried_terms[ $taxonomy ]['terms'] ) ) {
    823                                                 $this->queried_terms[ $taxonomy ]['terms'] = $cleaned_clause['terms'];
    824                                         }
    825 
    826                                         if ( ! empty( $cleaned_clause['field'] ) && ! isset( $this->queried_terms[ $taxonomy ]['field'] ) ) {
    827                                                 $this->queried_terms[ $taxonomy ]['field'] = $cleaned_clause['field'];
    828                                         }
    829                                 }
    830 
    831                         // Otherwise, it's a nested query, so we recurse.
    832                         } elseif ( is_array( $query ) ) {
    833                                 $cleaned_subquery = $this->sanitize_query( $query );
    834 
    835                                 if ( ! empty( $cleaned_subquery ) ) {
    836                                         // All queries with children must have a relation.
    837                                         if ( ! isset( $cleaned_subquery['relation'] ) ) {
    838                                                 $cleaned_subquery['relation'] = 'AND';
    839                                         }
    840 
    841                                         $cleaned_query[] = $cleaned_subquery;
    842                                 }
    843                         }
    844                 }
    845 
    846                 return $cleaned_query;
    847         }
    848 
    849         /**
    850          * Sanitize a 'relation' operator.
    851          *
    852          * @since 4.1.0
    853          * @access public
    854          *
    855          * @param string $relation Raw relation key from the query argument.
    856          * @return string Sanitized relation ('AND' or 'OR').
    857          */
    858         public function sanitize_relation( $relation ) {
    859                 if ( 'OR' === strtoupper( $relation ) ) {
    860                         return 'OR';
    861                 } else {
    862                         return 'AND';
    863                 }
    864         }
    865 
    866         /**
    867          * Determine whether a clause is first-order.
    868          *
    869          * A "first-order" clause is one that contains any of the first-order
    870          * clause keys ('terms', 'taxonomy', 'include_children', 'field',
    871          * 'operator'). An empty clause also counts as a first-order clause,
    872          * for backward compatibility. Any clause that doesn't meet this is
    873          * determined, by process of elimination, to be a higher-order query.
    874          *
    875          * @since 4.1.0
    876          *
    877          * @static
    878          * @access protected
    879          *
    880          * @param array $query Tax query arguments.
    881          * @return bool Whether the query clause is a first-order clause.
    882          */
    883         protected static function is_first_order_clause( $query ) {
    884                 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 ) );
    885         }
    886 
    887         /**
    888          * Generates SQL clauses to be appended to a main query.
    889          *
    890          * @since 3.1.0
    891          *
    892          * @static
    893          * @access public
    894          *
    895          * @param string $primary_table     Database table where the object being filtered is stored (eg wp_users).
    896          * @param string $primary_id_column ID column for the filtered object in $primary_table.
    897          * @return array {
    898          *     Array containing JOIN and WHERE SQL clauses to append to the main query.
    899          *
    900          *     @type string $join  SQL fragment to append to the main JOIN clause.
    901          *     @type string $where SQL fragment to append to the main WHERE clause.
    902          * }
    903          */
    904         public function get_sql( $primary_table, $primary_id_column ) {
    905                 $this->primary_table = $primary_table;
    906                 $this->primary_id_column = $primary_id_column;
    907 
    908                 return $this->get_sql_clauses();
    909         }
    910 
    911         /**
    912          * Generate SQL clauses to be appended to a main query.
    913          *
    914          * Called by the public WP_Tax_Query::get_sql(), this method
    915          * is abstracted out to maintain parity with the other Query classes.
    916          *
    917          * @since 4.1.0
    918          * @access protected
    919          *
    920          * @return array {
    921          *     Array containing JOIN and WHERE SQL clauses to append to the main query.
    922          *
    923          *     @type string $join  SQL fragment to append to the main JOIN clause.
    924          *     @type string $where SQL fragment to append to the main WHERE clause.
    925          * }
    926          */
    927         protected function get_sql_clauses() {
    928                 /*
    929                  * $queries are passed by reference to get_sql_for_query() for recursion.
    930                  * To keep $this->queries unaltered, pass a copy.
    931                  */
    932                 $queries = $this->queries;
    933                 $sql = $this->get_sql_for_query( $queries );
    934 
    935                 if ( ! empty( $sql['where'] ) ) {
    936                         $sql['where'] = ' AND ' . $sql['where'];
    937                 }
    938 
    939                 return $sql;
    940         }
    941 
    942         /**
    943          * Generate SQL clauses for a single query array.
    944          *
    945          * If nested subqueries are found, this method recurses the tree to
    946          * produce the properly nested SQL.
    947          *
    948          * @since 4.1.0
    949          * @access protected
    950          *
    951          * @param array $query Query to parse, passed by reference.
    952          * @param int   $depth Optional. Number of tree levels deep we currently are.
    953          *                     Used to calculate indentation. Default 0.
    954          * @return array {
    955          *     Array containing JOIN and WHERE SQL clauses to append to a single query array.
    956          *
    957          *     @type string $join  SQL fragment to append to the main JOIN clause.
    958          *     @type string $where SQL fragment to append to the main WHERE clause.
    959          * }
    960          */
    961         protected function get_sql_for_query( &$query, $depth = 0 ) {
    962                 $sql_chunks = array(
    963                         'join'  => array(),
    964                         'where' => array(),
    965                 );
    966 
    967                 $sql = array(
    968                         'join'  => '',
    969                         'where' => '',
    970                 );
    971 
    972                 $indent = '';
    973                 for ( $i = 0; $i < $depth; $i++ ) {
    974                         $indent .= "  ";
    975                 }
    976 
    977                 foreach ( $query as $key => &$clause ) {
    978                         if ( 'relation' === $key ) {
    979                                 $relation = $query['relation'];
    980                         } elseif ( is_array( $clause ) ) {
    981 
    982                                 // This is a first-order clause.
    983                                 if ( $this->is_first_order_clause( $clause ) ) {
    984                                         $clause_sql = $this->get_sql_for_clause( $clause, $query );
    985 
    986                                         $where_count = count( $clause_sql['where'] );
    987                                         if ( ! $where_count ) {
    988                                                 $sql_chunks['where'][] = '';
    989                                         } elseif ( 1 === $where_count ) {
    990                                                 $sql_chunks['where'][] = $clause_sql['where'][0];
    991                                         } else {
    992                                                 $sql_chunks['where'][] = '( ' . implode( ' AND ', $clause_sql['where'] ) . ' )';
    993                                         }
    994 
    995                                         $sql_chunks['join'] = array_merge( $sql_chunks['join'], $clause_sql['join'] );
    996                                 // This is a subquery, so we recurse.
    997                                 } else {
    998                                         $clause_sql = $this->get_sql_for_query( $clause, $depth + 1 );
    999 
    1000                                         $sql_chunks['where'][] = $clause_sql['where'];
    1001                                         $sql_chunks['join'][]  = $clause_sql['join'];
    1002                                 }
    1003                         }
    1004                 }
    1005 
    1006                 // Filter to remove empties.
    1007                 $sql_chunks['join']  = array_filter( $sql_chunks['join'] );
    1008                 $sql_chunks['where'] = array_filter( $sql_chunks['where'] );
    1009 
    1010                 if ( empty( $relation ) ) {
    1011                         $relation = 'AND';
    1012                 }
    1013 
    1014                 // Filter duplicate JOIN clauses and combine into a single string.
    1015                 if ( ! empty( $sql_chunks['join'] ) ) {
    1016                         $sql['join'] = implode( ' ', array_unique( $sql_chunks['join'] ) );
    1017                 }
    1018 
    1019                 // Generate a single WHERE clause with proper brackets and indentation.
    1020                 if ( ! empty( $sql_chunks['where'] ) ) {
    1021                         $sql['where'] = '( ' . "\n  " . $indent . implode( ' ' . "\n  " . $indent . $relation . ' ' . "\n  " . $indent, $sql_chunks['where'] ) . "\n" . $indent . ')';
    1022                 }
    1023 
    1024                 return $sql;
    1025         }
    1026 
    1027         /**
    1028          * Generate SQL JOIN and WHERE clauses for a "first-order" query clause.
    1029          *
    1030          * @since 4.1.0
    1031          * @access public
    1032          *
    1033          * @global wpdb $wpdb The WordPress database abstraction object.
    1034          *
    1035          * @param array $clause       Query clause, passed by reference.
    1036          * @param array $parent_query Parent query array.
    1037          * @return array {
    1038          *     Array containing JOIN and WHERE SQL clauses to append to a first-order query.
    1039          *
    1040          *     @type string $join  SQL fragment to append to the main JOIN clause.
    1041          *     @type string $where SQL fragment to append to the main WHERE clause.
    1042          * }
    1043          */
    1044         public function get_sql_for_clause( &$clause, $parent_query ) {
    1045                 global $wpdb;
    1046 
    1047                 $sql = array(
    1048                         'where' => array(),
    1049                         'join'  => array(),
    1050                 );
    1051 
    1052                 $join = $where = '';
    1053 
    1054                 $this->clean_query( $clause );
    1055 
    1056                 if ( is_wp_error( $clause ) ) {
    1057                         return self::$no_results;
    1058                 }
    1059 
    1060                 $terms = $clause['terms'];
    1061                 $operator = strtoupper( $clause['operator'] );
    1062 
    1063                 if ( 'IN' == $operator ) {
    1064 
    1065                         if ( empty( $terms ) ) {
    1066                                 return self::$no_results;
    1067                         }
    1068 
    1069                         $terms = implode( ',', $terms );
    1070 
    1071                         /*
    1072                          * Before creating another table join, see if this clause has a
    1073                          * sibling with an existing join that can be shared.
    1074                          */
    1075                         $alias = $this->find_compatible_table_alias( $clause, $parent_query );
    1076                         if ( false === $alias ) {
    1077                                 $i = count( $this->table_aliases );
    1078                                 $alias = $i ? 'tt' . $i : $wpdb->term_relationships;
    1079 
    1080                                 // Store the alias as part of a flat array to build future iterators.
    1081                                 $this->table_aliases[] = $alias;
    1082 
    1083                                 // Store the alias with this clause, so later siblings can use it.
    1084                                 $clause['alias'] = $alias;
    1085 
    1086                                 $join .= " INNER JOIN $wpdb->term_relationships";
    1087                                 $join .= $i ? " AS $alias" : '';
    1088                                 $join .= " ON ($this->primary_table.$this->primary_id_column = $alias.object_id)";
    1089                         }
    1090 
    1091 
    1092                         $where = "$alias.term_taxonomy_id $operator ($terms)";
    1093 
    1094                 } elseif ( 'NOT IN' == $operator ) {
    1095 
    1096                         if ( empty( $terms ) ) {
    1097                                 return $sql;
    1098                         }
    1099 
    1100                         $terms = implode( ',', $terms );
    1101 
    1102                         $where = "$this->primary_table.$this->primary_id_column NOT IN (
    1103                                 SELECT object_id
    1104                                 FROM $wpdb->term_relationships
    1105                                 WHERE term_taxonomy_id IN ($terms)
    1106                         )";
    1107 
    1108                 } elseif ( 'AND' == $operator ) {
    1109 
    1110                         if ( empty( $terms ) ) {
    1111                                 return $sql;
    1112                         }
    1113 
    1114                         $num_terms = count( $terms );
    1115 
    1116                         $terms = implode( ',', $terms );
    1117 
    1118                         $where = "(
    1119                                 SELECT COUNT(1)
    1120                                 FROM $wpdb->term_relationships
    1121                                 WHERE term_taxonomy_id IN ($terms)
    1122                                 AND object_id = $this->primary_table.$this->primary_id_column
    1123                         ) = $num_terms";
    1124 
    1125                 } elseif ( 'NOT EXISTS' === $operator || 'EXISTS' === $operator ) {
    1126 
    1127                         $where = $wpdb->prepare( "$operator (
    1128                                 SELECT 1
    1129                                 FROM $wpdb->term_relationships
    1130                                 INNER JOIN $wpdb->term_taxonomy
    1131                                 ON $wpdb->term_taxonomy.term_taxonomy_id = $wpdb->term_relationships.term_taxonomy_id
    1132                                 WHERE $wpdb->term_taxonomy.taxonomy = %s
    1133                                 AND $wpdb->term_relationships.object_id = $this->primary_table.$this->primary_id_column
    1134                         )", $clause['taxonomy'] );
    1135 
    1136                 }
    1137 
    1138                 $sql['join'][]  = $join;
    1139                 $sql['where'][] = $where;
    1140                 return $sql;
    1141         }
    1142 
    1143         /**
    1144          * Identify an existing table alias that is compatible with the current query clause.
    1145          *
    1146          * We avoid unnecessary table joins by allowing each clause to look for
    1147          * an existing table alias that is compatible with the query that it
    1148          * needs to perform.
    1149          *
    1150          * An existing alias is compatible if (a) it is a sibling of `$clause`
    1151          * (ie, it's under the scope of the same relation), and (b) the combination
    1152          * of operator and relation between the clauses allows for a shared table
    1153          * join. In the case of WP_Tax_Query, this only applies to 'IN'
    1154          * clauses that are connected by the relation 'OR'.
    1155          *
    1156          * @since 4.1.0
    1157          * @access protected
    1158          *
    1159          * @param array       $clause       Query clause.
    1160          * @param array       $parent_query Parent query of $clause.
    1161          * @return string|false Table alias if found, otherwise false.
    1162          */
    1163         protected function find_compatible_table_alias( $clause, $parent_query ) {
    1164                 $alias = false;
    1165 
    1166                 // Sanity check. Only IN queries use the JOIN syntax .
    1167                 if ( ! isset( $clause['operator'] ) || 'IN' !== $clause['operator'] ) {
    1168                         return $alias;
    1169                 }
    1170 
    1171                 // Since we're only checking IN queries, we're only concerned with OR relations.
    1172                 if ( ! isset( $parent_query['relation'] ) || 'OR' !== $parent_query['relation'] ) {
    1173                         return $alias;
    1174                 }
    1175 
    1176                 $compatible_operators = array( 'IN' );
    1177 
    1178                 foreach ( $parent_query as $sibling ) {
    1179                         if ( ! is_array( $sibling ) || ! $this->is_first_order_clause( $sibling ) ) {
    1180                                 continue;
    1181                         }
    1182 
    1183                         if ( empty( $sibling['alias'] ) || empty( $sibling['operator'] ) ) {
    1184                                 continue;
    1185                         }
    1186 
    1187                         // The sibling must both have compatible operator to share its alias.
    1188                         if ( in_array( strtoupper( $sibling['operator'] ), $compatible_operators ) ) {
    1189                                 $alias = $sibling['alias'];
    1190                                 break;
    1191                         }
    1192                 }
    1193 
    1194                 return $alias;
    1195         }
    1196 
    1197         /**
    1198          * Validates a single query.
    1199          *
    1200          * @since 3.2.0
    1201          * @access private
    1202          *
    1203          * @param array &$query The single query.
    1204          */
    1205         private function clean_query( &$query ) {
    1206                 if ( empty( $query['taxonomy'] ) ) {
    1207                         if ( 'term_taxonomy_id' !== $query['field'] ) {
    1208                                 $query = new WP_Error( 'Invalid taxonomy' );
    1209                                 return;
    1210                         }
    1211 
    1212                         // so long as there are shared terms, include_children requires that a taxonomy is set
    1213                         $query['include_children'] = false;
    1214                 } elseif ( ! taxonomy_exists( $query['taxonomy'] ) ) {
    1215                         $query = new WP_Error( 'Invalid taxonomy' );
    1216                         return;
    1217                 }
    1218 
    1219                 $query['terms'] = array_unique( (array) $query['terms'] );
    1220 
    1221                 if ( is_taxonomy_hierarchical( $query['taxonomy'] ) && $query['include_children'] ) {
    1222                         $this->transform_query( $query, 'term_id' );
    1223 
    1224                         if ( is_wp_error( $query ) )
    1225                                 return;
    1226 
    1227                         $children = array();
    1228                         foreach ( $query['terms'] as $term ) {
    1229                                 $children = array_merge( $children, get_term_children( $term, $query['taxonomy'] ) );
    1230                                 $children[] = $term;
    1231                         }
    1232                         $query['terms'] = $children;
    1233                 }
    1234 
    1235                 $this->transform_query( $query, 'term_taxonomy_id' );
    1236         }
    1237 
    1238         /**
    1239          * Transforms a single query, from one field to another.
    1240          *
    1241          * @since 3.2.0
    1242          *
    1243          * @global wpdb $wpdb The WordPress database abstraction object.
    1244          *
    1245          * @param array  &$query          The single query.
    1246          * @param string $resulting_field The resulting field. Accepts 'slug', 'name', 'term_taxonomy_id',
    1247          *                                or 'term_id'. Default 'term_id'.
    1248          */
    1249         public function transform_query( &$query, $resulting_field ) {
    1250                 global $wpdb;
    1251 
    1252                 if ( empty( $query['terms'] ) )
    1253                         return;
    1254 
    1255                 if ( $query['field'] == $resulting_field )
    1256                         return;
    1257 
    1258                 $resulting_field = sanitize_key( $resulting_field );
    1259 
    1260                 switch ( $query['field'] ) {
    1261                         case 'slug':
    1262                         case 'name':
    1263                                 foreach ( $query['terms'] as &$term ) {
    1264                                         /*
    1265                                          * 0 is the $term_id parameter. We don't have a term ID yet, but it doesn't
    1266                                          * matter because `sanitize_term_field()` ignores the $term_id param when the
    1267                                          * context is 'db'.
    1268                                          */
    1269                                         $term = "'" . esc_sql( sanitize_term_field( $query['field'], $term, 0, $query['taxonomy'], 'db' ) ) . "'";
    1270                                 }
    1271 
    1272                                 $terms = implode( ",", $query['terms'] );
    1273 
    1274                                 $terms = $wpdb->get_col( "
    1275                                         SELECT $wpdb->term_taxonomy.$resulting_field
    1276                                         FROM $wpdb->term_taxonomy
    1277                                         INNER JOIN $wpdb->terms USING (term_id)
    1278                                         WHERE taxonomy = '{$query['taxonomy']}'
    1279                                         AND $wpdb->terms.{$query['field']} IN ($terms)
    1280                                 " );
    1281                                 break;
    1282                         case 'term_taxonomy_id':
    1283                                 $terms = implode( ',', array_map( 'intval', $query['terms'] ) );
    1284                                 $terms = $wpdb->get_col( "
    1285                                         SELECT $resulting_field
    1286                                         FROM $wpdb->term_taxonomy
    1287                                         WHERE term_taxonomy_id IN ($terms)
    1288                                 " );
    1289                                 break;
    1290                         default:
    1291                                 $terms = implode( ',', array_map( 'intval', $query['terms'] ) );
    1292                                 $terms = $wpdb->get_col( "
    1293                                         SELECT $resulting_field
    1294                                         FROM $wpdb->term_taxonomy
    1295                                         WHERE taxonomy = '{$query['taxonomy']}'
    1296                                         AND term_id IN ($terms)
    1297                                 " );
    1298                 }
    1299 
    1300                 if ( 'AND' == $query['operator'] && count( $terms ) < count( $query['terms'] ) ) {
    1301                         $query = new WP_Error( 'Inexistent terms' );
    1302                         return;
    1303                 }
    1304 
    1305                 $query['terms'] = $terms;
    1306                 $query['field'] = $resulting_field;
    1307         }
    1308 }
    1309 
    1310 /**
    1311657 * Get all Term data from database by Term ID.
    1312658 *
    1313659 * The usage of the get_term function is to apply filters to a term object. It
    class WP_Tax_Query { 
    1346692 * @return object|array|null|WP_Error Term Row from database. Will return null if $term is empty. If taxonomy does not
    1347693 * exist then WP_Error will be returned.
    1348694 */
    1349 function get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') {
     695function get_term( $term, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) {
    1350696        global $wpdb;
    1351697
    1352698        if ( empty( $term ) ) {
    1353699                return new WP_Error( 'invalid_term', __( 'Empty Term' ) );
    1354700        }
    1355701
    1356         if ( ! taxonomy_exists( $taxonomy ) ) {
     702        if ( $taxonomy && ! taxonomy_exists( $taxonomy ) ) {
    1357703                return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy' ) );
    1358704        }
    1359705