Make WordPress Core

Changeset 38974


Ignore:
Timestamp:
10/27/2016 01:41:08 AM (5 years ago)
Author:
boonebgorges
Message:

REST API: Use wp_get_object_terms() when fetching terms for a post object.

The WP-API plugin originally used a custom method for fetching object
terms in a way that supported the object cache and also accepted all
parameters for get_terms(). In [38667], the internals of
wp_get_object_terms() were modified to use WP_Term_Query, thus
delivering in a native fashion the features that the API had
previously achieved bespokely.

Fixes #38504.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php

    r38960 r38974  
    190190
    191191        if ( ! empty( $prepared_args['post'] )  ) {
    192             $query_result = $this->get_terms_for_post( $prepared_args );
    193             $total_terms = $this->total_terms;
     192            $query_result = wp_get_object_terms( $prepared_args['post'], $this->taxonomy, $prepared_args );
     193
     194            // Used when calling wp_count_terms() below.
     195            $prepared_args['object_ids'] = $prepared_args['post'];
    194196        } else {
    195197            $query_result = get_terms( $this->taxonomy, $prepared_args );
    196 
    197             $count_args = $prepared_args;
    198             unset( $count_args['number'], $count_args['offset'] );
    199             $total_terms = wp_count_terms( $this->taxonomy, $count_args );
    200 
    201             // wp_count_terms can return a falsy value when the term has no children
    202             if ( ! $total_terms ) {
    203                 $total_terms = 0;
    204             }
    205         }
     198        }
     199
     200        $count_args = $prepared_args;
     201        unset( $count_args['number'], $count_args['offset'] );
     202        $total_terms = wp_count_terms( $this->taxonomy, $count_args );
     203
     204        // wp_count_terms can return a falsy value when the term has no children
     205        if ( ! $total_terms ) {
     206            $total_terms = 0;
     207        }
     208
    206209        $response = array();
    207210        foreach ( $query_result as $term ) {
     
    236239
    237240        return $response;
    238     }
    239 
    240     /**
    241      * Gets the terms attached to a post.
    242      *
    243      * This is an alternative to get_terms() that uses get_the_terms()
    244      * instead, which hits the object cache. There are a few things not
    245      * supported, notably `include`, `exclude`. In `self::get_items()` these
    246      * are instead treated as a full query.
    247      *
    248      * @param array $prepared_args Arguments for get_terms().
    249      * @return array List of term objects. (Total count in `$this->total_terms`)
    250      */
    251     protected function get_terms_for_post( $prepared_args ) {
    252         $query_result = get_the_terms( $prepared_args['post'], $this->taxonomy );
    253         if ( empty( $query_result ) ) {
    254             $this->total_terms = 0;
    255             return array();
    256         }
    257 
    258         /*
    259          * get_items() verifies that we don't have `include` set, and default
    260          * ordering is by `name`.
    261          */
    262         if ( ! in_array( $prepared_args['orderby'], array( 'name', 'none', 'include' ), true ) ) {
    263             switch ( $prepared_args['orderby'] ) {
    264                 case 'id':
    265                     $this->sort_column = 'term_id';
    266                     break;
    267 
    268                 case 'slug':
    269                 case 'term_group':
    270                 case 'description':
    271                 case 'count':
    272                     $this->sort_column = $prepared_args['orderby'];
    273                     break;
    274             }
    275             usort( $query_result, array( $this, 'compare_terms' ) );
    276         }
    277         if ( strtolower( $prepared_args['order'] ) !== 'asc' ) {
    278             $query_result = array_reverse( $query_result );
    279         }
    280 
    281         // Pagination.
    282         $this->total_terms = count( $query_result );
    283         $query_result = array_slice( $query_result, $prepared_args['offset'], $prepared_args['number'] );
    284 
    285         return $query_result;
    286     }
    287 
    288     /**
    289      * Comparison function for sorting terms by a column.
    290      *
    291      * Uses `$this->sort_column` to determine field to sort by.
    292      *
    293      * @access protected
    294      *
    295      * @param stdClass $left Term object.
    296      * @param stdClass $right Term object.
    297      * @return int <0 if left is higher "priority" than right, 0 if equal, >0 if right is higher "priority" than left.
    298      */
    299     protected function compare_terms( $left, $right ) {
    300         $col = $this->sort_column;
    301         $left_val = $left->$col;
    302         $right_val = $right->$col;
    303 
    304         if ( is_int( $left_val ) && is_int( $right_val ) ) {
    305             return $left_val - $right_val;
    306         }
    307 
    308         return strcmp( $left_val, $right_val );
    309241    }
    310242
  • trunk/tests/phpunit/tests/rest-api/rest-tags-controller.php

    r38960 r38974  
    771771    }
    772772
     773    /**
     774     * @ticket 38504
     775     */
     776    public function test_object_term_queries_are_cached() {
     777        global $wpdb;
     778
     779        $tags = $this->factory->tag->create_many( 2 );
     780        $p = $this->factory->post->create();
     781        wp_set_object_terms( $p, $tags[0], 'post_tag' );
     782
     783        $request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
     784        $request->set_param( 'post', $p );
     785        $response = $this->server->dispatch( $request );
     786        $found_1 = wp_list_pluck( $response->data, 'id' );
     787
     788        unset( $request, $response );
     789
     790        $num_queries = $wpdb->num_queries;
     791
     792        $request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
     793        $request->set_param( 'post', $p );
     794        $response = $this->server->dispatch( $request );
     795        $found_2 = wp_list_pluck( $response->data, 'id' );
     796
     797        $this->assertEqualSets( $found_1, $found_2 );
     798        $this->assertSame( $num_queries, $wpdb->num_queries );
     799    }
     800
    773801    public function additional_field_get_callback( $object, $request ) {
    774802        return 123;
Note: See TracChangeset for help on using the changeset viewer.