diff --git a/wp-includes/functions.php b/wp-includes/functions.php index c19e0dd07d..ab34f2e937 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -4629,3 +4629,21 @@ function wp_validate_boolean( $var ) { return (bool) $var; } + +/** + * Helper function to retrieve an incrementer identified by $group + * + * @since 4.1.0 + * + * @param string $group The cache group for the incrementer. + * @param bool $force Whether or not to generate a new incrementor. + * @return int The timestamp representing 'last_changed'. + */ +function wp_get_last_changed( $group, $force = false ) { + $last_changed = wp_cache_get( 'last_changed', $group ); + if ( ! $last_changed || true === $force ) { + $last_changed = microtime(); + wp_cache_set( 'last_changed', $last_changed, $group ); + } + return $last_changed; +} \ No newline at end of file diff --git a/wp-includes/taxonomy.php b/wp-includes/taxonomy.php index 7d40701686..63b505417f 100644 --- a/wp-includes/taxonomy.php +++ b/wp-includes/taxonomy.php @@ -1291,8 +1291,11 @@ function get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') { return $error; } + $group = $taxonomy . ':' . wp_get_last_changed( 'terms' ); if ( is_object($term) && empty($term->filter) ) { - wp_cache_add($term->term_id, $term, $taxonomy); + wp_cache_add( $term->term_id, $term, $taxonomy ); + wp_cache_add( "slug:{$term->slug}", $term->term_id, $group ); + wp_cache_add( "name:" . md5( $term->name ), $term->term_id, $group ); $_term = $term; } else { if ( is_object($term) ) @@ -1303,7 +1306,9 @@ function get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') { $_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) ); if ( ! $_term ) return null; - wp_cache_add($term, $_term, $taxonomy); + wp_cache_add( $term, $_term, $taxonomy ); + wp_cache_add( "slug:{$_term->slug}", $term, $group ); + wp_cache_add( "name:" . md5( $_term->name ), $term, $group ); } } @@ -1375,31 +1380,47 @@ function get_term_by($field, $value, $taxonomy, $output = OBJECT, $filter = 'raw if ( ! taxonomy_exists($taxonomy) ) return false; + $cache = false; + $group = $taxonomy . ':' . wp_get_last_changed( 'terms' ); if ( 'slug' == $field ) { $field = 't.slug'; $value = sanitize_title($value); if ( empty($value) ) return false; + + $term_id = wp_cache_get( "slug:{$value}", $group ); + if ( $term_id ) { + $value = $term_id; + $cache = true; + } } else if ( 'name' == $field ) { // Assume already escaped $value = wp_unslash($value); $field = 't.name'; + $term_id = wp_cache_get( "name:" . md5( $value ), $group ); + if ( $term_id ) { + $value = $term_id; + $cache = true; + } } else if ( 'term_taxonomy_id' == $field ) { $value = (int) $value; $field = 'tt.term_taxonomy_id'; } else { - $term = get_term( (int) $value, $taxonomy, $output, $filter); - if ( is_wp_error( $term ) ) - $term = false; - return $term; + $cache = true; + } + + if ( $cache ) { + $term = get_term( (int) $value, $taxonomy, $output, $filter); + if ( is_wp_error( $term ) ) { + $term = false; + } + } else { + $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) ); } - $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) ); if ( !$term ) return false; - wp_cache_add($term->term_id, $term, $taxonomy); - /** This filter is documented in wp-includes/taxonomy.php */ $term = apply_filters( 'get_term', $term, $taxonomy ); @@ -1408,6 +1429,10 @@ function get_term_by($field, $value, $taxonomy, $output = OBJECT, $filter = 'raw $term = sanitize_term($term, $taxonomy, $filter); + wp_cache_add( $term->term_id, $term, $taxonomy ); + wp_cache_add( "slug:{$term->slug}", $term->term_id, $group ); + wp_cache_add( "name:" . md5( $term->name ), $term->term_id, $group ); + if ( $output == OBJECT ) { return $term; } elseif ( $output == ARRAY_A ) { @@ -1890,9 +1915,6 @@ function get_terms( $taxonomies, $args = '' ) { } $terms = $wpdb->get_results($query); - if ( 'all' == $_fields ) { - update_term_cache($terms); - } if ( empty($terms) ) { wp_cache_add( $cache_key, array(), 'terms', DAY_IN_SECONDS ); @@ -3584,7 +3606,11 @@ function clean_object_term_cache($object_ids, $object_type) { * @param bool $clean_taxonomy Whether to clean taxonomy wide caches (true), or just individual term object caches (false). Default is true. */ function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) { - global $wpdb; + global $_wp_suspend_cache_invalidation, $wpdb; + + if ( ! empty( $_wp_suspend_cache_invalidation ) ) { + return; + } if ( !is_array($ids) ) $ids = array($ids); @@ -3631,7 +3657,7 @@ function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) { do_action( 'clean_term_cache', $ids, $taxonomy ); } - wp_cache_set( 'last_changed', microtime(), 'terms' ); + wp_get_last_changed( 'terms', true ); } /** @@ -3726,12 +3752,21 @@ function update_object_term_cache($object_ids, $object_type) { * @param string $taxonomy Optional. Update Term to this taxonomy in cache */ function update_term_cache($terms, $taxonomy = '') { + global $_wp_suspend_cache_invalidation; + + if ( ! empty( $_wp_suspend_cache_invalidation ) ) { + return; + } + foreach ( (array) $terms as $term ) { $term_taxonomy = $taxonomy; if ( empty($term_taxonomy) ) $term_taxonomy = $term->taxonomy; - wp_cache_add($term->term_id, $term, $term_taxonomy); + wp_cache_add( $term->term_id, $term, $term_taxonomy ); + $group = $term_taxonomy . ':' . wp_get_last_changed( 'terms', true ); + wp_cache_add( "slug:{$term->slug}", $term->term_id, $group ); + wp_cache_add( "name:" . md5( $term->name ), $term->term_id, $group ); } }