[wp-trac] [WordPress Trac] #31174: The get_terms() argument "fields" renders "get_terms_fields" & "terms_clauses" filter callbacks useless

WordPress Trac noreply at wordpress.org
Thu Jan 29 10:58:26 UTC 2015


#31174: The get_terms() argument "fields" renders "get_terms_fields" &
"terms_clauses" filter callbacks useless
--------------------------+-----------------------------
 Reporter:  F J Kaiser    |      Owner:
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  Taxonomy      |    Version:  4.1
 Severity:  normal        |   Keywords:
  Focuses:                |
--------------------------+-----------------------------
 The `get_terms( $tax, [ args ] );` function accepts an argument named
 `fields`. This allows to chose which columns should be fetched from either
 the `wp_terms` or `wp_term_taxonomy` table. Example:

 {{{
 $terms = get_terms( 'example_tax', [ 'fields' => 'names', ] );
 var_dump( $names );
 /* Result:
 array (size=1)
   0 => string 'Code Review' (length=11)
 */
 }}}

 In this case, the resulting query inside the function would be the
 following:

 {{{
 SELECT t.term_id, tt.parent, tt.count, t.name
 FROM wp_terms AS t
 INNER JOIN wp_term_taxonomy AS tt
     ON t.term_id = tt.term_id
 WHERE tt.taxonomy IN ('project_type')
 ORDER BY t.name ASC
 }}}

 In fact, `fields` does not really any combination of fields, but allows to
 chose from a list:

 * `all` : `$selects = array( 't.*', 'tt.*' )`
 * `ids` : `$selects = array( 't.term_id', 'tt.parent', 'tt.count' )`
 * `id=>parent` : `$selects = array( 't.term_id', 'tt.parent', 'tt.count'
 )` (the same as above)
 * `names` : `$selects = array( 't.term_id', 'tt.parent', 'tt.count',
 't.name' )`
 * `count` : `$selects = array( 'COUNT(*)' )`
 * `id=>name` : `$selects = array( 't.term_id', 't.name', 'tt.count' )`
 * `id=>slug` : `$selects = array( 't.term_id', 't.slug', 'tt.count' )`

 After this preselection ran, there are two filters available to alter the
 list:

 {{{
 $fields = implode( ', ', apply_filters( 'get_terms_fields', $selects,
 $args, $taxonomies ) );
 $pieces = array( 'fields', 'join', 'where', 'orderby', 'order', 'limits'
 );
 }}}

 But no matter if you attached an filter to either of those or not: The
 result stays the same. This is due to the following filtering done in a
 final loop through all results:

 * `ids` : `$_terms[] = $term->term_id`
 * `id=>parent` : `$_terms[$term->term_id] = $term->parent`
 * `names` : `$_terms[] = $term->name`
 * `id=>name` : `$_terms[$term->term_id] = $term->name`
 * `id=>slug` : `$_terms[$term->term_id] = $term->slug`

 And that renders callbacks to both attached filters useless. The only
 cases where this does not happen are the argument values `all` and
 `count`.

 I'm not sure if this should be called an "undocumented feature" or if this
 actually needs a patch. I'm in for later if there is support for changing
 this awkward behavior as this is not clear until one jumps and dumps in
 core.

 Proposed fix: Only run the final filter-loop if ...

 {{{
 if ( ! (
     has_filter( 'get_terms_fields' ) or has_filter( 'terms_clauses' )
 ) )
     // do final filtering
 }}}

--
Ticket URL: <https://core.trac.wordpress.org/ticket/31174>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list