Ticket #15752: WP_Tax_Query.diff

File WP_Tax_Query.diff, 9.5 KB (added by scribu, 2 years ago)
Line 
1Index: wp-includes/taxonomy.php
2===================================================================
3--- wp-includes/taxonomy.php    (revision 16845)
4+++ wp-includes/taxonomy.php    (working copy)
5@@ -527,148 +527,152 @@
6  * @return array
7  */
8 function get_tax_sql( $tax_query, $primary_table, $primary_id_column ) {
9-       global $wpdb;
10+       $tax_query_obj = new WP_Tax_Query( $tax_query );
11+       return $tax_query_obj->get_sql( $primary_table, $primary_id_column );
12+}
13 
14-       $join = '';
15-       $where = array();
16-       $i = 0;
17+class WP_Tax_Query {
18+       var $relation = '';
19+       var $queries = array();
20 
21-       _set_tax_query_defaults( $tax_query );
22+       function __construct( &$tax_query ) {
23+               if ( isset( $tax_query['relation'] ) && strtoupper( $tax_query['relation'] ) == 'OR' ) {
24+                       $this->relation = 'OR';
25+               } else {
26+                       $this->relation = 'AND';
27+               }
28 
29-       if ( strtoupper( $tax_query['relation'] ) == 'OR' ) {
30-               $relation = 'OR';
31-       } else {
32-               $relation = 'AND';
33-       }
34+               $defaults = array(
35+                       'taxonomy' => '',
36+                       'terms' => array(),
37+                       'include_children' => true,
38+                       'field' => 'term_id',
39+                       'operator' => 'IN',
40+               );
41 
42-       foreach ( $tax_query as $query ) {
43-               if ( ! is_array( $query ) )
44-                       continue;
45+               foreach ( $tax_query as $query ) {
46+                       if ( ! is_array( $query ) )
47+                               continue;
48 
49-               extract( $query );
50+                       $query = array_merge( $defaults, $query );
51 
52-               if ( ! taxonomy_exists( $taxonomy ) )
53-                       return array( 'join' => '', 'where' => ' AND 0 = 1');
54+                       $query['terms'] = (array) $query['terms'];
55+                       
56+                       $this->queries[] = $query;
57+               }
58+       }
59 
60-               $terms = array_unique( (array) $terms );
61+       function get_sql( $primary_table, $primary_id_column ) {
62+               global $wpdb;
63 
64-               if ( empty( $terms ) )
65-                       continue;
66+               $join = '';
67+               $where = array();
68+               $i = 0;
69 
70-               if ( is_taxonomy_hierarchical( $taxonomy ) && $include_children ) {
71-                       _transform_terms( $terms, $taxonomy, $field, 'term_id' );
72+               foreach ( $this->queries as $query ) {
73+                       extract( $query );
74 
75-                       $children = array();
76-                       foreach ( $terms as $term ) {
77-                               $children = array_merge( $children, get_term_children( $term, $taxonomy ) );
78-                               $children[] = $term;
79-                       }
80-                       $terms = $children;
81+                       if ( ! taxonomy_exists( $taxonomy ) )
82+                               return array( 'join' => '', 'where' => ' AND 0 = 1');
83 
84-                       _transform_terms( $terms, $taxonomy, 'term_id', 'term_taxonomy_id' );
85-               }
86-               else {
87-                       _transform_terms( $terms, $taxonomy, $field, 'term_taxonomy_id' );
88-               }
89+                       $terms = array_unique( (array) $terms );
90 
91-               if ( 'IN' == $operator ) {
92+                       if ( empty( $terms ) )
93+                               continue;
94 
95-                       if ( empty( $terms ) ) {
96-                               if ( 'OR' == $relation )
97-                                       continue;
98-                               else
99-                                       return array( 'join' => '', 'where' => ' AND 0 = 1' );
100-                       }
101+                       if ( is_taxonomy_hierarchical( $taxonomy ) && $include_children ) {
102+                               $this->_transform_terms( $terms, $taxonomy, $field, 'term_id' );
103 
104-                       $terms = implode( ',', $terms );
105+                               $children = array();
106+                               foreach ( $terms as $term ) {
107+                                       $children = array_merge( $children, get_term_children( $term, $taxonomy ) );
108+                                       $children[] = $term;
109+                               }
110+                               $terms = $children;
111 
112-                       $alias = $i ? 'tt' . $i : $wpdb->term_relationships;
113+                               $this->_transform_terms( $terms, $taxonomy, 'term_id', 'term_taxonomy_id' );
114+                       }
115+                       else {
116+                               $this->_transform_terms( $terms, $taxonomy, $field, 'term_taxonomy_id' );
117+                       }
118 
119-                       $join .= " INNER JOIN $wpdb->term_relationships";
120-                       $join .= $i ? " AS $alias" : '';
121-                       $join .= " ON ($primary_table.$primary_id_column = $alias.object_id)";
122+                       if ( 'IN' == $operator ) {
123 
124-                       $where[] = "$alias.term_taxonomy_id $operator ($terms)";
125-               }
126-               elseif ( 'NOT IN' == $operator ) {
127+                               if ( empty( $terms ) ) {
128+                                       if ( 'OR' == $relation )
129+                                               continue;
130+                                       else
131+                                               return array( 'join' => '', 'where' => ' AND 0 = 1' );
132+                               }
133 
134-                       if ( empty( $terms ) )
135-                               continue;
136+                               $terms = implode( ',', $terms );
137 
138-                       $terms = implode( ',', $terms );
139+                               $alias = $i ? 'tt' . $i : $wpdb->term_relationships;
140 
141-                       $where[] = "$primary_table.$primary_id_column NOT IN (
142-                               SELECT object_id
143-                               FROM $wpdb->term_relationships
144-                               WHERE term_taxonomy_id IN ($terms)
145-                       )";
146-               }
147+                               $join .= " INNER JOIN $wpdb->term_relationships";
148+                               $join .= $i ? " AS $alias" : '';
149+                               $join .= " ON ($primary_table.$primary_id_column = $alias.object_id)";
150 
151-               $i++;
152-       }
153+                               $where[] = "$alias.term_taxonomy_id $operator ($terms)";
154+                       }
155+                       elseif ( 'NOT IN' == $operator ) {
156 
157-       if ( !empty( $where ) )
158-               $where = ' AND ( ' . implode( " $relation ", $where ) . ' )';
159-       else
160-               $where = '';
161+                               if ( empty( $terms ) )
162+                                       continue;
163 
164-       return compact( 'join', 'where' );
165-}
166+                               $terms = implode( ',', $terms );
167 
168-function _set_tax_query_defaults( &$tax_query ) {
169-       if ( ! isset( $tax_query['relation'] ) )
170-               $tax_query['relation'] = 'AND';
171+                               $where[] = "$primary_table.$primary_id_column NOT IN (
172+                                       SELECT object_id
173+                                       FROM $wpdb->term_relationships
174+                                       WHERE term_taxonomy_id IN ($terms)
175+                               )";
176+                       }
177 
178-       $defaults = array(
179-               'taxonomy' => '',
180-               'terms' => array(),
181-               'include_children' => true,
182-               'field' => 'term_id',
183-               'operator' => 'IN',
184-       );
185+                       $i++;
186+               }
187 
188-       foreach ( $tax_query as $i => $query ) {
189-               if ( ! is_array( $query ) )
190-                       continue;
191+               if ( !empty( $where ) )
192+                       $where = ' AND ( ' . implode( " $relation ", $where ) . ' )';
193+               else
194+                       $where = '';
195 
196-               $tax_query[$i] = array_merge( $defaults, $query );
197-
198-               $tax_query[$i]['terms'] = (array) $tax_query[$i]['terms'];
199+               return compact( 'join', 'where' );
200        }
201-}
202 
203-function _transform_terms( &$terms, $taxonomy, $field, $resulting_field ) {
204-       global $wpdb;
205+       function _transform_terms( &$terms, $taxonomy, $field, $resulting_field ) {
206+               global $wpdb;
207 
208-       if ( empty( $terms ) )
209-               return;
210+               if ( empty( $terms ) )
211+                       return;
212 
213-       if ( $field == $resulting_field )
214-               return;
215+               if ( $field == $resulting_field )
216+                       return;
217 
218-       $resulting_field = esc_sql( $resulting_field );
219+               $resulting_field = esc_sql( $resulting_field );
220 
221-       switch ( $field ) {
222-               case 'slug':
223-               case 'name':
224-                       $terms = "'" . implode( "','", array_map( 'sanitize_title_for_query', $terms ) ) . "'";
225-                       $terms = $wpdb->get_col( "
226-                               SELECT $wpdb->term_taxonomy.$resulting_field
227-                               FROM $wpdb->term_taxonomy
228-                               INNER JOIN $wpdb->terms USING (term_id)
229-                               WHERE taxonomy = '$taxonomy'
230-                               AND $wpdb->terms.$field IN ($terms)
231-                       " );
232-                       break;
233+               switch ( $field ) {
234+                       case 'slug':
235+                       case 'name':
236+                               $terms = "'" . implode( "','", array_map( 'sanitize_title_for_query', $terms ) ) . "'";
237+                               $terms = $wpdb->get_col( "
238+                                       SELECT $wpdb->term_taxonomy.$resulting_field
239+                                       FROM $wpdb->term_taxonomy
240+                                       INNER JOIN $wpdb->terms USING (term_id)
241+                                       WHERE taxonomy = '$taxonomy'
242+                                       AND $wpdb->terms.$field IN ($terms)
243+                               " );
244+                               break;
245 
246-               default:
247-                       $terms = implode( ',', array_map( 'intval', $terms ) );
248-                       $terms = $wpdb->get_col( "
249-                               SELECT $resulting_field
250-                               FROM $wpdb->term_taxonomy
251-                               WHERE taxonomy = '$taxonomy'
252-                               AND term_id IN ($terms)
253-                       " );
254+                       default:
255+                               $terms = implode( ',', array_map( 'intval', $terms ) );
256+                               $terms = $wpdb->get_col( "
257+                                       SELECT $resulting_field
258+                                       FROM $wpdb->term_taxonomy
259+                                       WHERE taxonomy = '$taxonomy'
260+                                       AND term_id IN ($terms)
261+                               " );
262+               }
263        }
264 }
265 
266Index: wp-includes/query.php
267===================================================================
268--- wp-includes/query.php       (revision 16844)
269+++ wp-includes/query.php       (working copy)
270@@ -714,9 +714,9 @@
271         *
272         * @since 3.1.0
273         * @access public
274-        * @var array
275+        * @var object WP_Tax_Query
276         */
277-       var $tax_query = array();
278+       var $tax_query;
279 
280        /**
281         * Holds the data for a single object that is queried.
282@@ -1584,12 +1584,9 @@
283                        );
284                }
285 
286-               _set_tax_query_defaults( $tax_query );
287+               $tax_query_obj = new WP_Tax_Query( $tax_query );
288 
289-               foreach ( $tax_query as $query ) {
290-                       if ( ! is_array( $query ) )
291-                               continue;
292-
293+               foreach ( $tax_query_obj->queries as $query ) {
294                        if ( 'IN' == $query['operator'] ) {
295                                switch ( $query['taxonomy'] ) {
296                                        case 'category':
297@@ -1604,7 +1601,7 @@
298                        }
299                }
300 
301-               return $tax_query;
302+               return $tax_query_obj;
303        }
304 
305        /**
306@@ -1942,7 +1939,7 @@
307                if ( $this->is_category || $this->is_tag || $this->is_tax ) {
308                        $this->tax_query = $this->parse_tax_query( $q );
309 
310-                       $clauses = call_user_func_array( 'get_tax_sql', array( $this->tax_query, $wpdb->posts, 'ID', &$this) );
311+                       $clauses = $this->tax_query->get_sql( $wpdb->posts, 'ID' );
312 
313                        $join .= $clauses['join'];
314                        $where .= $clauses['where'];
315@@ -1957,7 +1954,7 @@
316                        }
317 
318                        // Back-compat
319-                       $tax_query_in = wp_list_filter( $this->tax_query, array( 'operator' => 'IN' ) );
320+                       $tax_query_in = wp_list_filter( $this->tax_query->queries, array( 'operator' => 'IN' ) );
321                        if ( !empty( $tax_query_in ) ) {
322                                if ( !isset( $q['taxonomy'] ) ) {
323                                        foreach ( $tax_query_in as $a_tax_query ) {
324@@ -2657,7 +2654,7 @@
325                $this->queried_object = NULL;
326                $this->queried_object_id = 0;
327 
328-               $tax_query_in = wp_list_filter( $this->tax_query, array( 'operator' => 'IN' ) );
329+               $tax_query_in = wp_list_filter( $this->tax_query->queries, array( 'operator' => 'IN' ) );
330                if ( !empty( $tax_query_in ) ) {
331                        $query = reset( $tax_query_in );
332 
333Index: wp-includes/canonical.php
334===================================================================
335--- wp-includes/canonical.php   (revision 16842)
336+++ wp-includes/canonical.php   (working copy)
337@@ -146,7 +146,7 @@
338                } elseif ( is_category() || is_tag() || is_tax() ) { // Terms (Tags/categories)
339 
340                        $term_count = 0;
341-                       foreach ( $wp_query->tax_query as $tax_query )
342+                       foreach ( $wp_query->tax_query->queries as $tax_query )
343                                $term_count += count( $tax_query['terms'] );
344 
345                        $obj = $wp_query->get_queried_object();