Make WordPress Core


Ignore:
Timestamp:
11/05/2015 04:44:59 PM (9 years ago)
Author:
boonebgorges
Message:

Make get_term() behave more consistently in the context of shared terms.

When WP_Term was introduced in [34997], the $taxonomy parameter for
get_term() was made optional. This meant that, when the optional param was
omitted, get_term() had no way of determining which term was intended when
the term_id was shared between multiple taxonomies. As a (somewhat sneaky) way
of fixing things, get_term() split any shared terms it found. But this could
cause problems with developer expectations: it's not clear why requesting a
term should result in a database update, much less a potential change in the
ID of a term.

In place of this technique, this changeset introduces a number of changes that
make the handling of shared terms a bit less insane:

  • When a taxonomy is provided to get_term(), and a cached term is found matching the term_id, make sure the taxonomy also matches before returning it.
  • When a taxonomy is not provided, ensure that the term is not shared before adding it to the cache.
  • When a term is shared between taxonomies and no taxonomy is provided, return a WP_Error rather than splitting the term.
  • When a term is shared between taxonomies, only one of which is valid, return the term from that taxonomy.

Props boonebgorges, dlh.
Fixes #34533.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-term.php

    r35269 r35537  
    116116     * @global wpdb $wpdb WordPress database abstraction object.
    117117     *
    118      * @param int $term_id Term ID.
    119      * @return WP_Term|false Term object, false otherwise.
    120      */
    121     public static function get_instance( $term_id ) {
     118     * @param int    $term_id  Term ID.
     119     * @param string $taxonomy Optional. Limit matched terms to those matching `$taxonomy`. Only used for
     120     *                         disambiguating potentially shared terms.
     121     * @return WP_Term|WP_Error|false Term object, if found. WP_Error if `$term_id` is shared between taxonomies and
     122     *                                there's insufficient data to distinguish which term is intended.
     123     *                                False for other failures.
     124     */
     125    public static function get_instance( $term_id, $taxonomy = null ) {
    122126        global $wpdb;
    123127
     
    130134
    131135        // If there isn't a cached version, hit the database.
    132         if ( ! $_term ) {
    133             $_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.term_id = %d LIMIT 1", $term_id ) );
     136        if ( ! $_term || ( $taxonomy && $taxonomy !== $_term->taxonomy ) ) {
     137            // Grab all matching terms, in case any are shared between taxonomies.
     138            $terms = $wpdb->get_results( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.term_id = %d", $term_id ) );
     139            if ( ! $terms ) {
     140                return false;
     141            }
     142
     143            // If a taxonomy was specified, find a match.
     144            if ( $taxonomy ) {
     145                foreach ( $terms as $match ) {
     146                    if ( $taxonomy === $match->taxonomy ) {
     147                        $_term = $match;
     148                        break;
     149                    }
     150                }
     151
     152            // If only one match was found, it's the one we want.
     153            } elseif ( 1 === count( $terms ) ) {
     154                $_term = reset( $terms );
     155
     156            // Otherwise, the term must be shared between taxonomies.
     157            } else {
     158                // If the term is shared only with invalid taxonomies, return the one valid term.
     159                foreach ( $terms as $t ) {
     160                    if ( ! taxonomy_exists( $t->taxonomy ) ) {
     161                        continue;
     162                    }
     163
     164                    // Only hit if we've already identified a term in a valid taxonomy.
     165                    if ( $_term ) {
     166                        return new WP_Error( 'ambiguous_term_id', __( 'Term ID is shared between multiple taxonomies' ), $term_id );
     167                    }
     168
     169                    $_term = $t;
     170                }
     171            }
     172
    134173            if ( ! $_term ) {
    135174                return false;
    136175            }
    137176
     177            // Don't return terms from invalid taxonomies.
     178            if ( ! taxonomy_exists( $_term->taxonomy ) ) {
     179                return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy' ) );
     180            }
     181
    138182            $_term = sanitize_term( $_term, $_term->taxonomy, 'raw' );
    139             wp_cache_add( $term_id, $_term, 'terms' );
     183
     184            // Don't cache terms that are shared between taxonomies.
     185            if ( 1 === count( $terms ) ) {
     186                wp_cache_add( $term_id, $_term, 'terms' );
     187            }
    140188        }
    141189
Note: See TracChangeset for help on using the changeset viewer.