diff --git a/src/wp-includes/taxonomy.php b/src/wp-includes/taxonomy.php index 98a50c1ab6..23f8764eb5 100644 --- a/src/wp-includes/taxonomy.php +++ b/src/wp-includes/taxonomy.php @@ -824,55 +824,49 @@ function get_term( $term, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) { * or `$term` was not found. */ function get_term_by( $field, $value, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) { + global $wpdb; // 'term_taxonomy_id' lookups don't require taxonomy checks. if ( 'term_taxonomy_id' !== $field && ! taxonomy_exists( $taxonomy ) ) { return false; } - if ( 'id' === $field || 'term_id' === $field ) { + $tax_clause = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy ); + + if ( 'slug' == $field ) { + $_field = 't.slug'; + $value = sanitize_title($value); + if ( empty($value) ) + return false; + } elseif ( 'name' == $field ) { + // Assume already escaped + $value = wp_unslash($value); + $_field = 't.name'; + } elseif ( 'term_taxonomy_id' == $field ) { + $value = (int) $value; + $_field = 'tt.term_taxonomy_id'; + + // No `taxonomy` clause when searching by 'term_taxonomy_id'. + $tax_clause = ''; + } else { $term = get_term( (int) $value, $taxonomy, $output, $filter ); - if ( is_wp_error( $term ) || null === $term ) { + if ( is_wp_error( $term ) || is_null( $term ) ) { $term = false; } return $term; } - $args = array( - 'get' => 'all', - 'number' => 1, - 'taxonomy' => $taxonomy, - 'update_term_meta_cache' => false, - 'orderby' => 'none', - ); - - switch ( $field ) { - case 'slug' : - $args['slug'] = $value; - break; - case 'name' : - $args['name'] = $value; - break; - case 'term_taxonomy_id' : - $args['term_taxonomy_id'] = $value; - unset( $args[ 'taxonomy' ] ); - break; - default : - return false; - } - - $terms = get_terms( $args ); - if ( is_wp_error( $terms ) || empty( $terms ) ) { + $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 $_field = %s", $value ) . " $tax_clause LIMIT 1" ); + if ( ! $term ) return false; - } - - $term = array_shift( $terms ); // In the case of 'term_taxonomy_id', override the provided `$taxonomy` with whatever we find in the db. if ( 'term_taxonomy_id' === $field ) { $taxonomy = $term->taxonomy; } + wp_cache_add( $term->term_id, $term, 'terms' ); + return get_term( $term, $taxonomy, $output, $filter ); } diff --git a/tests/phpunit/tests/term/cache.php b/tests/phpunit/tests/term/cache.php index fb7a5a84ab..d48b52ba34 100644 --- a/tests/phpunit/tests/term/cache.php +++ b/tests/phpunit/tests/term/cache.php @@ -220,177 +220,6 @@ class Tests_Term_Cache extends WP_UnitTestCase { } } - /** - * @ticket 21760 - */ - function test_get_term_by_slug_cache() { - global $wpdb; - - $term_id = $this->factory->term->create( array( 'slug' => 'burrito', 'name' => 'Taco', 'taxonomy' => 'post_tag' ) ); - - clean_term_cache( $term_id, 'post_tag' ); - $num_queries = $wpdb->num_queries; - - $term = get_term_by( 'slug', 'burrito', 'post_tag' ); - $num_queries++; - $this->assertEquals( 'Taco', $term->name ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - - // This should now hit cache. - $term = get_term_by( 'slug', 'burrito', 'post_tag' ); - $this->assertEquals( 'Taco', $term->name ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - - $this->assertEquals( get_term( $term_id, 'post_tag' ), $term ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - } - - /** - * @ticket 21760 - */ - function test_get_term_by_slug_cache_update() { - global $wpdb; - - $term_id = $this->factory->term->create( array( 'slug' => 'burrito', 'name' => 'Taco', 'taxonomy' => 'post_tag' ) ); - - clean_term_cache( $term_id, 'post_tag' ); - $num_queries = $wpdb->num_queries; - - $term = get_term_by( 'slug', 'burrito', 'post_tag' ); - $num_queries++; - $this->assertEquals( 'Taco', $term->name ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - - // This should now hit cache. - $term = get_term_by( 'slug', 'burrito', 'post_tag' ); - $this->assertEquals( 'Taco', $term->name ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - - // Update the tag which invalidates the cache. - wp_update_term( $term_id, 'post_tag', array( 'name' => 'No Taco' ) ); - $num_queries = $wpdb->num_queries; - - // This should not hit cache. - $term = get_term_by( 'slug', 'burrito', 'post_tag' ); - $num_queries++; - $this->assertEquals( 'No Taco', $term->name ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - } - - /** - * @ticket 21760 - */ - function test_get_term_by_name_cache() { - global $wpdb; - - $term_id = $this->factory->term->create( array( 'name' => 'Burrito', 'slug' => 'noburrito', 'taxonomy' => 'post_tag' ) ); - - clean_term_cache( $term_id, 'post_tag' ); - $num_queries = $wpdb->num_queries; - - get_term_by( 'name', 'Burrito', 'post_tag' ); - $num_queries++; - $this->assertEquals( $num_queries, $wpdb->num_queries ); - - // This should now hit cache. - $term = get_term_by( 'name', 'Burrito', 'post_tag' ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - - $this->assertEquals( get_term( $term_id, 'post_tag' ), $term ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - } - - /** - * @ticket 21760 - */ - function test_get_term_by_name_cache_update() { - global $wpdb; - - $term_id = $this->factory->term->create( array( 'name' => 'Burrito', 'slug' => 'noburrito', 'taxonomy' => 'post_tag' ) ); - - clean_term_cache( $term_id, 'post_tag' ); - $num_queries = $wpdb->num_queries; - - get_term_by( 'name', 'Burrito', 'post_tag' ); - $num_queries++; - $this->assertEquals( $num_queries, $wpdb->num_queries ); - - // This should now hit cache. - get_term_by( 'name', 'Burrito', 'post_tag' ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - - // Update the tag which invalidates the cache. - wp_update_term( $term_id, 'post_tag', array( 'slug' => 'taco' ) ); - $num_queries = $wpdb->num_queries; - - // This should not hit cache. - get_term_by( 'name', 'burrito', 'post_tag' ); - $num_queries++; - $this->assertEquals( $num_queries, $wpdb->num_queries ); - } - - /** - * @ticket 21760 - */ - function test_invalidating_term_caches_should_fail_when_invalidation_is_suspended() { - global $wpdb; - - $term_id = $this->factory->term->create( array( 'name' => 'Burrito', 'taxonomy' => 'post_tag' ) ); - - clean_term_cache( $term_id, 'post_tag' ); - $num_queries = $wpdb->num_queries; - $last_changed = wp_cache_get( 'last_changed', 'terms' ); - - $term1 = get_term_by( 'name', 'Burrito', 'post_tag' ); - $num_queries++; - - // Verify the term is cached. - $term2 = get_term_by( 'name', 'Burrito', 'post_tag' ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - $this->assertEquals( $term1, $term2 ); - - $suspend = wp_suspend_cache_invalidation(); - - // Update the tag. - wp_update_term( $term_id, 'post_tag', array( 'name' => 'Taco' ) ); - $num_queries = $wpdb->num_queries; - - // Verify that the cached term still matches the initial cached term. - $term3 = get_term_by( 'name', 'Burrito', 'post_tag' ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - $this->assertEquals( $term1, $term3 ); - - // Verify that last changed has not been updated as part of an invalidation routine. - $this->assertSame( $last_changed, wp_cache_get( 'last_changed', 'terms' ) ); - - // Clean up. - wp_suspend_cache_invalidation( $suspend ); - } - - /** - * @ticket 21760 - */ - public function test_get_term_by_does_not_prime_term_meta_cache() { - global $wpdb; - - $term_id = $this->factory->term->create( array( 'name' => 'Burrito', 'taxonomy' => 'post_tag' ) ); - add_term_meta( $term_id, 'foo', 'bar' ); - - clean_term_cache( $term_id, 'post_tag' ); - $num_queries = $wpdb->num_queries; - - $term = get_term_by( 'name', 'Burrito', 'post_tag' ); - $num_queries++; - $this->assertTrue( $term instanceof WP_Term ); - $this->assertSame( $term_id, $term->term_id ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - - $term_meta = get_term_meta( $term_id, 'foo', true ); - $num_queries++; - $this->assertSame( $term_meta, 'bar' ); - $this->assertEquals( $num_queries, $wpdb->num_queries ); - } - /** * @ticket 37291 */