WordPress.org

Make WordPress Core

Ticket #21760: 21760.2.patch

File 21760.2.patch, 10.5 KB (added by boonebgorges, 6 years ago)
  • src/wp-includes/functions.php

    diff --git src/wp-includes/functions.php src/wp-includes/functions.php
    index c19e0dd..ae15ca2 100644
    function wp_validate_boolean( $var ) { 
    46294629
    46304630        return (bool) $var;
    46314631}
     4632
     4633/**
     4634 * Helper function to retrieve an incrementer identified by $group
     4635 *
     4636 * @since 4.0.0
     4637 *
     4638 * @param string $group The cache group for the incrementer.
     4639 * @param bool $force Whether or not to generate a new incrementor.
     4640 * @return int The timestamp representing 'last_changed'.
     4641 */
     4642function wp_get_last_changed( $group, $force = false ) {
     4643        $last_changed = wp_cache_get( 'last_changed', $group );
     4644        if ( ! $last_changed || true === $force ) {
     4645                $last_changed = microtime();
     4646                wp_cache_set( 'last_changed', $last_changed, $group );
     4647        }
     4648        return $last_changed;
     4649}
     4650 No newline at end of file
  • src/wp-includes/taxonomy.php

    diff --git src/wp-includes/taxonomy.php src/wp-includes/taxonomy.php
    index 013c3d3..f0a112a 100644
    function get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') { 
    963963                return $error;
    964964        }
    965965
     966        $group = $taxonomy . ':' . wp_get_last_changed( 'terms' );
    966967        if ( is_object($term) && empty($term->filter) ) {
    967                 wp_cache_add($term->term_id, $term, $taxonomy);
     968                wp_cache_add( $term->term_id, $term, $taxonomy );
     969                wp_cache_add( "slug:{$term->slug}", $term->term_id, $group );
     970                wp_cache_add( "name:" . md5( $term->name ), $term->term_id, $group );
    968971                $_term = $term;
    969972        } else {
    970973                if ( is_object($term) )
    function get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') { 
    975978                        $_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 tt.taxonomy = %s AND t.term_id = %d LIMIT 1", $taxonomy, $term) );
    976979                        if ( ! $_term )
    977980                                return null;
    978                         wp_cache_add($term, $_term, $taxonomy);
     981                        wp_cache_add( $term, $_term, $taxonomy );
     982                        wp_cache_add( "slug:{$_term->slug}", $term, $group );
     983                        wp_cache_add( "name:" . md5( $_term->name ), $term, $group );
    979984                }
    980985        }
    981986
    function get_term_by($field, $value, $taxonomy, $output = OBJECT, $filter = 'raw 
    10471052        if ( ! taxonomy_exists($taxonomy) )
    10481053                return false;
    10491054
     1055        $cache = false;
     1056        $group = $taxonomy . ':' . wp_get_last_changed( 'terms' );
    10501057        if ( 'slug' == $field ) {
    10511058                $field = 't.slug';
    10521059                $value = sanitize_title($value);
    10531060                if ( empty($value) )
    10541061                        return false;
     1062
     1063                $term_id = wp_cache_get( "slug:{$value}", $group );
     1064                if ( $term_id ) {
     1065                        $value = $term_id;
     1066                        $cache = true;
     1067                }
    10551068        } else if ( 'name' == $field ) {
    10561069                // Assume already escaped
    10571070                $value = wp_unslash($value);
    10581071                $field = 't.name';
     1072                $term_id = wp_cache_get( "name:" . md5( $value ), $group );
     1073                if ( $term_id ) {
     1074                        $value = $term_id;
     1075                        $cache = true;
     1076                }
    10591077        } else if ( 'term_taxonomy_id' == $field ) {
    10601078                $value = (int) $value;
    10611079                $field = 'tt.term_taxonomy_id';
    10621080        } else {
     1081                $cache = true;
     1082        }
     1083
     1084        if ( $cache ) {
    10631085                $term = get_term( (int) $value, $taxonomy, $output, $filter);
    1064                 if ( is_wp_error( $term ) )
     1086                if ( is_wp_error( $term ) ) {
    10651087                        $term = false;
    1066                 return $term;
     1088                }
     1089        } else {
     1090                $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 tt.taxonomy = %s AND $field = %s LIMIT 1", $taxonomy, $value) );
    10671091        }
    10681092
    1069         $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 tt.taxonomy = %s AND $field = %s LIMIT 1", $taxonomy, $value) );
    10701093        if ( !$term )
    10711094                return false;
    10721095
    1073         wp_cache_add($term->term_id, $term, $taxonomy);
    1074 
    10751096        /** This filter is documented in wp-includes/taxonomy.php */
    10761097        $term = apply_filters( 'get_term', $term, $taxonomy );
    10771098
    function get_term_by($field, $value, $taxonomy, $output = OBJECT, $filter = 'raw 
    10801101
    10811102        $term = sanitize_term($term, $taxonomy, $filter);
    10821103
     1104        wp_cache_add( $term->term_id, $term, $taxonomy );
     1105        wp_cache_add( "slug:{$term->slug}", $term->term_id, $group );
     1106        wp_cache_add( "name:" . md5( $term->name ), $term->term_id, $group );
     1107
    10831108        if ( $output == OBJECT ) {
    10841109                return $term;
    10851110        } elseif ( $output == ARRAY_A ) {
    function get_terms( $taxonomies, $args = '' ) { 
    15621587        }
    15631588
    15641589        $terms = $wpdb->get_results($query);
    1565         if ( 'all' == $_fields ) {
    1566                 update_term_cache($terms);
    1567         }
    15681590
    15691591        if ( empty($terms) ) {
    15701592                wp_cache_add( $cache_key, array(), 'terms', DAY_IN_SECONDS );
    function clean_object_term_cache($object_ids, $object_type) { 
    32563278 * @param bool $clean_taxonomy Whether to clean taxonomy wide caches (true), or just individual term object caches (false). Default is true.
    32573279 */
    32583280function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) {
    3259         global $wpdb;
     3281        global $_wp_suspend_cache_invalidation, $wpdb;
     3282
     3283        if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
     3284                return;
     3285        }
    32603286
    32613287        if ( !is_array($ids) )
    32623288                $ids = array($ids);
    function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) { 
    33033329                do_action( 'clean_term_cache', $ids, $taxonomy );
    33043330        }
    33053331
    3306         wp_cache_set( 'last_changed', microtime(), 'terms' );
     3332        wp_get_last_changed( 'terms', true );
    33073333}
    33083334
    33093335/**
    function update_object_term_cache($object_ids, $object_type) { 
    33983424 * @param string $taxonomy Optional. Update Term to this taxonomy in cache
    33993425 */
    34003426function update_term_cache($terms, $taxonomy = '') {
     3427        global $_wp_suspend_cache_invalidation;
     3428
     3429        if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
     3430                return;
     3431        }
     3432
    34013433        foreach ( (array) $terms as $term ) {
    34023434                $term_taxonomy = $taxonomy;
    34033435                if ( empty($term_taxonomy) )
    34043436                        $term_taxonomy = $term->taxonomy;
    34053437
    3406                 wp_cache_add($term->term_id, $term, $term_taxonomy);
     3438                wp_cache_add( $term->term_id, $term, $term_taxonomy );
     3439                $group = $term_taxonomy . ':' . wp_get_last_changed( 'terms', true );
     3440                wp_cache_add( "slug:{$term->slug}", $term->term_id, $group );
     3441                wp_cache_add( "name:" . md5( $term->name ), $term->term_id, $group );
    34073442        }
    34083443}
    34093444
  • tests/phpunit/tests/term/cache.php

    diff --git tests/phpunit/tests/term/cache.php tests/phpunit/tests/term/cache.php
    index a63f30f..0c7f1b5 100644
    class Tests_Term_Cache extends WP_UnitTestCase { 
    9393
    9494                _unregister_taxonomy( $tax );
    9595        }
     96
     97        /**
     98         * @ticket 21760
     99         */
     100        function test_get_term_by_slug_cache() {
     101                global $wpdb;
     102                $term_id = $this->factory->term->create( array( 'slug' => 'burrito', 'taxonomy' => 'post_tag' ) );
     103
     104                $queries = $wpdb->num_queries;
     105                get_term_by( 'slug', 'burrito', 'post_tag' );
     106                $initial = $queries + 1;
     107                $this->assertEquals( $initial, $wpdb->num_queries );
     108                $term = get_term_by( 'slug', 'burrito', 'post_tag' );
     109                $this->assertEquals( $initial, $wpdb->num_queries );
     110
     111                $this->assertEquals( $term, wp_cache_get( $term_id, 'post_tag' ) );
     112
     113                $this->assertEquals( get_term( $term_id, 'post_tag' ), $term );
     114                $this->assertEquals( $initial, $wpdb->num_queries );
     115        }
     116
     117        /**
     118         * @ticket 21760
     119         */
     120        function test_get_term_by_slug_cache_update() {
     121                global $wpdb;
     122                $term_id = $this->factory->term->create( array( 'slug' => 'burrito', 'taxonomy' => 'post_tag' ) );
     123
     124                $queries = $wpdb->num_queries;
     125                get_term_by( 'slug', 'burrito', 'post_tag' );
     126                $initial = $queries + 1;
     127                $this->assertEquals( $initial, $wpdb->num_queries );
     128                $term = get_term_by( 'slug', 'burrito', 'post_tag' );
     129                $this->assertEquals( $initial, $wpdb->num_queries );
     130
     131                $this->assertEquals( $term, wp_cache_get( $term_id, 'post_tag' ) );
     132
     133                wp_update_term( $term_id, 'post_tag', array( 'name' => 'Taco' ) );
     134                $this->assertNotEquals( $term, get_term( $term_id, 'post_tag' ) );
     135                $after_queries = $wpdb->num_queries;
     136                get_term_by( 'slug', 'burrito', 'post_tag' );
     137                $this->assertEquals( $after_queries, $wpdb->num_queries );
     138        }
     139
     140        /**
     141         * @ticket 21760
     142         */
     143        function test_get_term_by_name_cache() {
     144                global $wpdb;
     145                $term_id = $this->factory->term->create( array( 'name' => 'burrito', 'taxonomy' => 'post_tag' ) );
     146
     147                $queries = $wpdb->num_queries;
     148                get_term_by( 'name', 'burrito', 'post_tag' );
     149                $initial = $queries + 1;
     150                $this->assertEquals( $initial, $wpdb->num_queries );
     151                $term = get_term_by( 'name', 'burrito', 'post_tag' );
     152                $this->assertEquals( $initial, $wpdb->num_queries );
     153
     154                $this->assertEquals( get_term( $term_id, 'post_tag' ), $term );
     155                $this->assertEquals( $initial, $wpdb->num_queries );
     156        }
     157
     158        /**
     159         * @ticket 21760
     160         */
     161        function test_get_term_by_name_cache_update() {
     162                global $wpdb;
     163                $term_id = $this->factory->term->create( array( 'name' => 'burrito', 'taxonomy' => 'post_tag' ) );
     164
     165                $queries = $wpdb->num_queries;
     166                get_term_by( 'name', 'burrito', 'post_tag' );
     167                $initial = $queries + 1;
     168                $this->assertEquals( $initial, $wpdb->num_queries );
     169                $term = get_term_by( 'name', 'burrito', 'post_tag' );
     170                $this->assertEquals( $initial, $wpdb->num_queries );
     171
     172                wp_update_term( $term_id, 'post_tag', array( 'slug' => 'Taco' ) );
     173                $this->assertNotEquals( $term, get_term( $term_id, 'post_tag' ) );
     174                $after_queries = $wpdb->num_queries;
     175                get_term_by( 'name', 'burrito', 'post_tag' );
     176                $this->assertEquals( $after_queries, $wpdb->num_queries );
     177        }
     178
     179        /**
     180         * @ticket 21760
     181         */
     182        function test_invalidating_term_caches_should_fail_when_invalidation_is_suspended() {
     183                $slug = 'taco';
     184                $name = 'Taco';
     185                $taxonomy = 'post_tag';
     186                $cache_key_slug = 'slug:' . $slug;
     187                $cache_key_name = 'name:' . md5( $name );
     188
     189                $term_id = $this->factory->term->create( array( 'slug' => $slug, 'name' => $name, 'taxonomy' => $taxonomy ) );
     190
     191                $last_changed = wp_get_last_changed( 'terms' );
     192                $group = $taxonomy . ':' . $last_changed;
     193
     194                $term = get_term_by( 'slug', $slug, $taxonomy );
     195
     196                // Verify the term is cached by ID, slug and name
     197                $this->assertEquals( $term, wp_cache_get( $term_id, $taxonomy ) );
     198                $this->assertEquals( $term_id, wp_cache_get( $cache_key_slug, $group ) );
     199                $this->assertEquals( $term_id, wp_cache_get( $cache_key_name, $group ) );
     200
     201                wp_suspend_cache_invalidation();
     202                clean_term_cache( $term_id, $taxonomy );
     203
     204                // Verify that the cached value still matches the correct value
     205                $this->assertEquals( $term, wp_cache_get( $term_id, $taxonomy ) );
     206                $this->assertEquals( $term_id, wp_cache_get( $cache_key_slug, $group ) );
     207                $this->assertEquals( $term_id, wp_cache_get( $cache_key_name, $group ) );
     208
     209                // Verify that last changed has not been updated as part of an invalidation routine
     210                $this->assertEquals( $last_changed, wp_get_last_changed( 'terms' ) );
     211        }
    96212}
     213 No newline at end of file