WordPress.org

Make WordPress Core

Changeset 38776


Ignore:
Timestamp:
10/11/16 01:55:58 (14 months ago)
Author:
boonebgorges
Message:

Taxonomy: Better error handling when fetching object terms from cache.

Since [37573], get_object_term_cache() has expected term IDs to be
stored in the taxonomy relationship cache. The function would then
reach directly into the 'terms' cache to fetch the data corresponding
to a given term, before returning a WP_Term object. This caused
problems when, for one reason or another, term data was cached
inconsistently:

  • If the 'terms' cache is empty for a given term ID, despite the earlier call to _prime_term_caches(), get_term() would return an error object.
  • If the array of cached term IDs contains an invalid ID, get_term() would return an error object.

We avoid these errors by no longer touching the 'terms' cache directly,
but running term IDs through get_term() and allowing that function to
reference the cache (and database, as needed). If get_term() returns
an error object for any of the cached term IDs, get_object_term_cache()
will return that error object alone. This change ensures that upstream
functions, like get_the_terms(), return WP_Error objects in a
predictable fashion.

Props dd32, michalzuber.
Fixes #37291.

Location:
trunk
Files:
2 edited

Legend:

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

    r38747 r38776  
    30113011 * 
    30123012 * @since 2.3.0 
     3013 * @since 4.6.2 Returns a WP_Error object if get_term() returns an error for 
     3014 *              any of the matched terms. 
    30133015 * 
    30143016 * @param int    $id       Term object ID. 
    30153017 * @param string $taxonomy Taxonomy name. 
    3016  * @return bool|array Array of `WP_Term` objects, if cached False if cache is empty for `$taxonomy` and `$id`. 
     3018 * @return bool|array|WP_Error Array of `WP_Term` objects, if cached. 
     3019 *                             False if cache is empty for `$taxonomy` and `$id`. 
     3020 *                             WP_Error if get_term() returns an error object for any term. 
    30173021 */ 
    30183022function get_object_term_cache( $id, $taxonomy ) { 
     
    30393043    $terms = array(); 
    30403044    foreach ( $term_ids as $term_id ) { 
    3041         $terms[] = wp_cache_get( $term_id, 'terms' ); 
    3042     } 
    3043  
    3044     return array_map( 'get_term', $terms ); 
     3045        $term = get_term( $term_id ); 
     3046        if ( is_wp_error( $term ) ) { 
     3047            return $term; 
     3048        } 
     3049 
     3050        $terms[] = $term; 
     3051    } 
     3052 
     3053    return $terms; 
    30453054} 
    30463055 
  • trunk/tests/phpunit/tests/term/cache.php

    r38677 r38776  
    391391        $this->assertEquals( $num_queries, $wpdb->num_queries ); 
    392392    } 
     393 
     394    /** 
     395     * @ticket 37291 
     396     */ 
     397    public function test_get_object_term_cache_should_return_error_if_any_term_is_an_error() { 
     398        register_taxonomy( 'wptests_tax', 'post' ); 
     399 
     400        $t = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax' ) ); 
     401        $p = self::factory()->post->create(); 
     402        wp_set_object_terms( $p, $t, 'wptests_tax' ); 
     403 
     404        // Prime cache. 
     405        $terms = get_the_terms( $p, 'wptests_tax' ); 
     406        $this->assertEqualSets( array( $t ), wp_list_pluck( $terms, 'term_id' ) ); 
     407 
     408        /* 
     409         * Modify cached array to insert an empty term ID, 
     410         * which will trigger an error in get_term(). 
     411         */ 
     412        $cached_ids = wp_cache_get( $p, 'wptests_tax_relationships' ); 
     413        $cached_ids[] = 0; 
     414        wp_cache_set( $p, $cached_ids, 'wptests_tax_relationships' ); 
     415 
     416        $terms = get_the_terms( $p, 'wptests_tax' ); 
     417        $this->assertWPError( $terms ); 
     418    } 
    393419} 
Note: See TracChangeset for help on using the changeset viewer.