<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[52836] trunk: Taxonomy: Only store term_ids and object_ids in `WP_Term_Query` query caches.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/52836">52836</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/52836","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>spacedmonkey</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2022-03-10 10:56:09 +0000 (Thu, 10 Mar 2022)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Taxonomy: Only store term_ids and object_ids in `WP_Term_Query` query caches.

The query cache currently implemented in `WP_Term_Query` caches the final output of the query, depending on what fields are requested. This is wasteful, as if a user requests `fields` => `all`, then an unlimited array of `WP_Term` objects could be stored in the object cache. Instead of storing the whole WP_Term object, this change only the term_id is stored. To get an array the full WP_Term objects, the `_prime_term_caches` function is called with an array of ids. In instances where a persistent object cache is not in use, then this will result in another SQL query to be run. After `_prime_term_caches` is called if this term is requested again in the same page load, then it will already be loaded into memory.  If a user runs `WP_Term_Query` with the fields param set to `all_with_object_id`, an array of objects containing both the term_id and object_ids are stored in cache. 

This change also improves the logic to load term meta caches. This change ensures that term meta is always primed for all terms loaded in the term query. 

Props Spacedmonkey, boonebgorges, jbpaul17, peterwilsoncc, flixos90, pbearne.
Fixes <a href="https://core.trac.wordpress.org/ticket/37189">#37189</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesclasswptermqueryphp">trunk/src/wp-includes/class-wp-term-query.php</a></li>
<li><a href="#trunktestsphpunitteststermcachephp">trunk/tests/phpunit/tests/term/cache.php</a></li>
<li><a href="#trunktestsphpunitteststermgetTermByphp">trunk/tests/phpunit/tests/term/getTermBy.php</a></li>
<li><a href="#trunktestsphpunitteststermgetTermsphp">trunk/tests/phpunit/tests/term/getTerms.php</a></li>
<li><a href="#trunktestsphpunitteststermisObjectInTermphp">trunk/tests/phpunit/tests/term/isObjectInTerm.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesclasswptermqueryphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-term-query.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-term-query.php     2022-03-10 05:19:50 UTC (rev 52835)
+++ trunk/src/wp-includes/class-wp-term-query.php       2022-03-10 10:56:09 UTC (rev 52836)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -636,33 +636,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $selects = array();
</span><span class="cx" style="display: block; padding: 0 10px">                switch ( $args['fields'] ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'all':
-                       case 'all_with_object_id':
-                       case 'tt_ids':
-                       case 'slugs':
-                               $selects = array( 't.*', 'tt.*' );
-                               if ( 'all_with_object_id' === $args['fields'] && ! empty( $args['object_ids'] ) ) {
-                                       $selects[] = 'tr.object_id';
-                               }
-                               break;
-                       case 'ids':
-                       case 'id=>parent':
-                               $selects = array( 't.term_id', 'tt.parent', 'tt.count', 'tt.taxonomy' );
-                               break;
-                       case 'names':
-                               $selects = array( 't.term_id', 'tt.parent', 'tt.count', 't.name', 'tt.taxonomy' );
-                               break;
</del><span class="cx" style="display: block; padding: 0 10px">                         case 'count':
</span><span class="cx" style="display: block; padding: 0 10px">                                $orderby = '';
</span><span class="cx" style="display: block; padding: 0 10px">                                $order   = '';
</span><span class="cx" style="display: block; padding: 0 10px">                                $selects = array( 'COUNT(*)' );
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'id=>name':
-                               $selects = array( 't.term_id', 't.name', 'tt.parent', 'tt.count', 'tt.taxonomy' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 default:
+                               $selects = array( 't.term_id' );
+                               if ( 'all_with_object_id' === $args['fields'] && ! empty( $args['object_ids'] ) ) {
+                                       $selects[] = 'tr.object_id';
+                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                 break;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'id=>slug':
-                               $selects = array( 't.term_id', 't.slug', 'tt.parent', 'tt.count', 'tt.taxonomy' );
-                               break;
</del><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $_fields = $args['fields'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -688,7 +672,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $join .= " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ( ! empty( $this->query_vars['object_ids'] ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $join .= " INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $join    .= " INNER JOIN {$wpdb->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id";
+                       $distinct = 'DISTINCT';
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $where = implode( ' AND ', $this->sql_clauses['where'] );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -748,8 +733,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $cache_key    = "get_terms:$key:$last_changed";
</span><span class="cx" style="display: block; padding: 0 10px">                $cache        = wp_cache_get( $cache_key, 'terms' );
</span><span class="cx" style="display: block; padding: 0 10px">                if ( false !== $cache ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) {
-                               $cache = $this->populate_terms( $cache );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ( 'ids' === $_fields ) {
+                               $term_ids = wp_list_pluck( $cache, 'term_id' );
+                               $cache    = array_map( 'intval', $term_ids );
+                       } elseif ( 'count' !== $_fields ) {
+                               $term_ids = wp_list_pluck( $cache, 'term_id' );
+                               _prime_term_caches( $term_ids, $args['update_term_meta_cache'] );
+                               $term_objects = $this->populate_terms( $cache );
+                               $cache        = $this->format_terms( $term_objects, $_fields );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->terms = $cache;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -757,33 +748,27 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ( 'count' === $_fields ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $count = $wpdb->get_var( $this->request );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $count = $wpdb->get_var( $this->request ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
</ins><span class="cx" style="display: block; padding: 0 10px">                         wp_cache_set( $cache_key, $count, 'terms' );
</span><span class="cx" style="display: block; padding: 0 10px">                        return $count;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $terms = $wpdb->get_results( $this->request );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $terms = $wpdb->get_results( $this->request ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) {
-                       update_term_cache( $terms );
-               }
-
-               // Prime termmeta cache.
-               if ( $args['update_term_meta_cache'] ) {
-                       $term_ids = wp_list_pluck( $terms, 'term_id' );
-                       update_termmeta_cache( $term_ids );
-               }
-
</del><span class="cx" style="display: block; padding: 0 10px">                 if ( empty( $terms ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        wp_cache_add( $cache_key, array(), 'terms' );
</span><span class="cx" style="display: block; padding: 0 10px">                        return array();
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $term_ids = wp_list_pluck( $terms, 'term_id' );
+               _prime_term_caches( $term_ids, false );
+               $term_objects = $this->populate_terms( $terms );
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ( $child_of ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ( $taxonomies as $_tax ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $children = _get_term_hierarchy( $_tax );
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( ! empty( $children ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $terms = _get_term_children( $child_of, $terms, $_tax );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $term_objects = _get_term_children( $child_of, $term_objects, $_tax );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -791,13 +776,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                // Update term counts to include children.
</span><span class="cx" style="display: block; padding: 0 10px">                if ( $args['pad_counts'] && 'all' === $_fields ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ( $taxonomies as $_tax ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                _pad_term_counts( $terms, $_tax );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         _pad_term_counts( $term_objects, $_tax );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Make sure we show empty categories that have children.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( $hierarchical && $args['hide_empty'] && is_array( $terms ) ) {
-                       foreach ( $terms as $k => $term ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( $hierarchical && $args['hide_empty'] && is_array( $term_objects ) ) {
+                       foreach ( $term_objects as $k => $term ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if ( ! $term->count ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $children = get_term_children( $term->term_id, $term->taxonomy );
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ( is_array( $children ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -810,7 +795,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        // It really is empty.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        unset( $terms[ $k ] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 unset( $term_objects[ $k ] );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -836,56 +821,26 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $terms = $_terms;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $_terms = array();
-               if ( 'id=>parent' === $_fields ) {
-                       foreach ( $terms as $term ) {
-                               $_terms[ $term->term_id ] = $term->parent;
-                       }
-               } elseif ( 'ids' === $_fields ) {
-                       foreach ( $terms as $term ) {
-                               $_terms[] = (int) $term->term_id;
-                       }
-               } elseif ( 'tt_ids' === $_fields ) {
-                       foreach ( $terms as $term ) {
-                               $_terms[] = (int) $term->term_taxonomy_id;
-                       }
-               } elseif ( 'names' === $_fields ) {
-                       foreach ( $terms as $term ) {
-                               $_terms[] = $term->name;
-                       }
-               } elseif ( 'slugs' === $_fields ) {
-                       foreach ( $terms as $term ) {
-                               $_terms[] = $term->slug;
-                       }
-               } elseif ( 'id=>name' === $_fields ) {
-                       foreach ( $terms as $term ) {
-                               $_terms[ $term->term_id ] = $term->name;
-                       }
-               } elseif ( 'id=>slug' === $_fields ) {
-                       foreach ( $terms as $term ) {
-                               $_terms[ $term->term_id ] = $term->slug;
-                       }
-               }
-
-               if ( ! empty( $_terms ) ) {
-                       $terms = $_terms;
-               }
-
</del><span class="cx" style="display: block; padding: 0 10px">                 // Hierarchical queries are not limited, so 'offset' and 'number' must be handled now.
</span><span class="cx" style="display: block; padding: 0 10px">                if ( $hierarchical && $number && is_array( $terms ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( $offset >= count( $terms ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $terms = array();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $terms        = array();
+                               $term_objects = array();
</ins><span class="cx" style="display: block; padding: 0 10px">                         } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $terms = array_slice( $terms, $offset, $number, true );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $terms        = array_slice( $terms, $offset, $number, true );
+                               $term_objects = array_slice( $term_objects, $offset, $number, true );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // Prime termmeta cache.
+               if ( $args['update_term_meta_cache'] ) {
+                       $term_ids = wp_list_pluck( $term_objects, 'term_id' );
+                       update_termmeta_cache( $term_ids );
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 wp_cache_add( $cache_key, $terms, 'terms' );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $terms = $this->format_terms( $term_objects, $_fields );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( 'all' === $_fields || 'all_with_object_id' === $_fields ) {
-                       $terms = $this->populate_terms( $terms );
-               }
-
</del><span class="cx" style="display: block; padding: 0 10px">                 $this->terms = $terms;
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->terms;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -950,6 +905,53 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Format response depending on field requested.
+        *
+        * @since 6.0.0
+        *
+        * @param WP_Term[] $term_objects Array of term objects.
+        * @param string $_fields Field to format.
+        *
+        * @return WP_Term[]|int[]|string[] Array of terms / strings / ints depending on field requested.
+        */
+       protected function format_terms( $term_objects, $_fields ) {
+               $_terms = array();
+               if ( 'id=>parent' === $_fields ) {
+                       foreach ( $term_objects as $term ) {
+                               $_terms[ $term->term_id ] = $term->parent;
+                       }
+               } elseif ( 'ids' === $_fields ) {
+                       foreach ( $term_objects as $term ) {
+                               $_terms[] = (int) $term->term_id;
+                       }
+               } elseif ( 'tt_ids' === $_fields ) {
+                       foreach ( $term_objects as $term ) {
+                               $_terms[] = (int) $term->term_taxonomy_id;
+                       }
+               } elseif ( 'names' === $_fields ) {
+                       foreach ( $term_objects as $term ) {
+                               $_terms[] = $term->name;
+                       }
+               } elseif ( 'slugs' === $_fields ) {
+                       foreach ( $term_objects as $term ) {
+                               $_terms[] = $term->slug;
+                       }
+               } elseif ( 'id=>name' === $_fields ) {
+                       foreach ( $term_objects as $term ) {
+                               $_terms[ $term->term_id ] = $term->name;
+                       }
+               } elseif ( 'id=>slug' === $_fields ) {
+                       foreach ( $term_objects as $term ) {
+                               $_terms[ $term->term_id ] = $term->slug;
+                       }
+               } elseif ( 'all' === $_fields || 'all_with_object_id' === $_fields ) {
+                       $_terms = $term_objects;
+               }
+
+               return $_terms;
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Generate the ORDER BY clause for an 'orderby' param that is potentially related to a meta query.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 4.6.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1053,23 +1055,30 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 4.9.8
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @param array $term_ids Term IDs.
-        * @return array
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * @param Object[]|int[] $terms List of objects or term ids.
+        * @return WP_Term[] Array of `WP_Term` objects.
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        protected function populate_terms( $term_ids ) {
-               $terms = array();
-
-               if ( ! is_array( $term_ids ) ) {
-                       return $terms;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ protected function populate_terms( $terms ) {
+               $term_objects = array();
+               if ( ! is_array( $terms ) ) {
+                       return $term_objects;
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                foreach ( $term_ids as $key => $term_id ) {
-                       $term = get_term( $term_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         foreach ( $terms as $key => $term_data ) {
+                       if ( is_object( $term_data ) && property_exists( $term_data, 'term_id' ) ) {
+                               $term = get_term( $term_data->term_id );
+                               if ( property_exists( $term_data, 'object_id' ) ) {
+                                       $term->object_id = (int) $term_data->object_id;
+                               }
+                       } else {
+                               $term = get_term( $term_data );
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ( $term instanceof WP_Term ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $terms[ $key ] = $term;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $term_objects[ $key ] = $term;
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return $terms;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return $term_objects;
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunitteststermcachephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/term/cache.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/term/cache.php  2022-03-10 05:19:50 UTC (rev 52835)
+++ trunk/tests/phpunit/tests/term/cache.php    2022-03-10 10:56:09 UTC (rev 52836)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -255,8 +255,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                clean_term_cache( $term_id, 'post_tag' );
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $term = get_term_by( 'slug', 'burrito', 'post_tag' );
-               $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $term        = get_term_by( 'slug', 'burrito', 'post_tag' );
+               $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( 'Taco', $term->name );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame( $num_queries, $wpdb->num_queries );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -286,8 +286,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                clean_term_cache( $term_id, 'post_tag' );
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $term = get_term_by( 'slug', 'burrito', 'post_tag' );
-               $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $term        = get_term_by( 'slug', 'burrito', 'post_tag' );
+               $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( 'Taco', $term->name );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame( $num_queries, $wpdb->num_queries );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -301,8 +301,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // This should not hit cache.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $term = get_term_by( 'slug', 'burrito', 'post_tag' );
-               $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $term        = get_term_by( 'slug', 'burrito', 'post_tag' );
+               $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( 'No Taco', $term->name );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame( $num_queries, $wpdb->num_queries );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -325,7 +325,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                get_term_by( 'name', 'Burrito', 'post_tag' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $num_queries, $wpdb->num_queries );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // This should now hit cache.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -354,7 +354,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                get_term_by( 'name', 'Burrito', 'post_tag' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $num_queries, $wpdb->num_queries );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // This should now hit cache.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -367,7 +367,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // This should not hit cache.
</span><span class="cx" style="display: block; padding: 0 10px">                get_term_by( 'name', 'burrito', 'post_tag' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $num_queries, $wpdb->num_queries );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -388,8 +388,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries  = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px">                $last_changed = wp_cache_get( 'last_changed', 'terms' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $term1 = get_term_by( 'name', 'Burrito', 'post_tag' );
-               $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $term1       = get_term_by( 'name', 'Burrito', 'post_tag' );
+               $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Verify the term is cached.
</span><span class="cx" style="display: block; padding: 0 10px">                $term2 = get_term_by( 'name', 'Burrito', 'post_tag' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -431,8 +431,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                clean_term_cache( $term_id, 'post_tag' );
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $term = get_term_by( 'name', 'Burrito', 'post_tag' );
-               $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $term        = get_term_by( 'name', 'Burrito', 'post_tag' );
+               $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertInstanceOf( 'WP_Term', $term );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame( $term_id, $term->term_id );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame( $num_queries, $wpdb->num_queries );
</span></span></pre></div>
<a id="trunktestsphpunitteststermgetTermByphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/term/getTermBy.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/term/getTermBy.php      2022-03-10 05:19:50 UTC (rev 52835)
+++ trunk/tests/phpunit/tests/term/getTermBy.php        2022-03-10 10:56:09 UTC (rev 52836)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5,6 +5,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> class Tests_Term_GetTermBy extends WP_UnitTestCase {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        protected $query = '';
+
</ins><span class="cx" style="display: block; padding: 0 10px">         public function test_get_term_by_slug() {
</span><span class="cx" style="display: block; padding: 0 10px">                $term1 = wp_insert_term( 'Foo', 'category', array( 'slug' => 'foo' ) );
</span><span class="cx" style="display: block; padding: 0 10px">                $term2 = get_term_by( 'slug', 'foo', 'category' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -123,7 +125,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px">                $found       = get_term_by( 'slug', 'foo', 'wptests_tax' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertInstanceOf( 'WP_Term', $found );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame( $t, $found->term_id );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -209,8 +211,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @ticket 21760
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        public function test_query_should_contain_limit_clause() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                global $wpdb;
-
</del><span class="cx" style="display: block; padding: 0 10px">                 $term_id = $this->factory->term->create(
</span><span class="cx" style="display: block; padding: 0 10px">                        array(
</span><span class="cx" style="display: block; padding: 0 10px">                                'name'     => 'burrito',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -217,9 +217,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                'taxonomy' => 'post_tag',
</span><span class="cx" style="display: block; padding: 0 10px">                        )
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $found   = get_term_by( 'name', 'burrito', 'post_tag' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         add_filter( 'terms_pre_query', array( $this, 'get_query_from_filter' ), 10, 2 );
+               $found = get_term_by( 'name', 'burrito', 'post_tag' );
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $term_id, $found->term_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->assertStringContainsString( 'LIMIT 1', $wpdb->last_query );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->assertStringContainsString( 'LIMIT 1', $this->query );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -282,4 +283,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertFalse( $found_by_slug );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertFalse( $found_by_name );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       public function get_query_from_filter( $terms, $wp_term_query ) {
+               $this->query = $wp_term_query->request;
+
+               return $terms;
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunitteststermgetTermsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/term/getTerms.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/term/getTerms.php       2022-03-10 05:19:50 UTC (rev 52835)
+++ trunk/tests/phpunit/tests/term/getTerms.php 2022-03-10 10:56:09 UTC (rev 52836)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -118,7 +118,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertCount( 3, $terms );
</span><span class="cx" style="display: block; padding: 0 10px">                $time1 = wp_cache_get( 'last_changed', 'terms' );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertNotEmpty( $time1 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->assertSame( $num_queries + 1, $wpdb->num_queries );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->assertSame( $num_queries + 2, $wpdb->num_queries );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="trunktestsphpunitteststermisObjectInTermphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/term/isObjectInTerm.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/term/isObjectInTerm.php 2022-03-10 05:19:50 UTC (rev 52835)
+++ trunk/tests/phpunit/tests/term/isObjectInTerm.php   2022-03-10 10:56:09 UTC (rev 52836)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -145,7 +145,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertTrue( is_object_in_term( $o, 'wptests_tax', $terms[0] ) );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $num_queries, $wpdb->num_queries );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertFalse( is_object_in_term( $o, 'wptests_tax', $terms[1] ) );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -166,7 +166,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertTrue( is_object_in_term( $o, 'wptests_tax', $terms[0] ) );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $num_queries, $wpdb->num_queries );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                wp_set_object_terms( $o, $terms[1], 'wptests_tax' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -173,7 +173,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $num_queries = $wpdb->num_queries;
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertTrue( is_object_in_term( $o, 'wptests_tax', $terms[1] ) );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $num_queries++;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $num_queries = $num_queries + 2;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertSame( $num_queries, $wpdb->num_queries );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre>
</div>
</div>

</body>
</html>