Skip to:
Content

BuddyPress.org

Ticket #6978: 6978.2.patch

File 6978.2.patch, 21.3 KB (added by dcavins, 5 years ago)

Cache friendship objects separately from a user's friendships.

  • src/bp-friends/bp-friends-cache.php

    diff --git src/bp-friends/bp-friends-cache.php src/bp-friends/bp-friends-cache.php
    index 5fb11a5..819f817 100644
    add_action( 'friends_friendship_accepted', 'friends_clear_friend_object_cache' ) 
    3535add_action( 'friends_friendship_deleted',  'friends_clear_friend_object_cache' );
    3636
    3737/**
     38 * Clear friendship caches on friendship changes.
     39 *
     40 * @since 2.7.0
     41 *
     42 * @param int $friendship_id     ID of the friendship that has changed.
     43 * @param int $initiator_user_id ID of the first user.
     44 * @param int $friend_user_id    ID of the second user.
     45 * @return bool
     46 */
     47function bp_friends_clear_bp_friends_friendships_cache( $friendship_id, $initiator_user_id, $friend_user_id ) {
     48        // Clear friendship ID cache for each user.
     49        wp_cache_delete( $initiator_user_id, 'bp_friends_friendships_for_user' );
     50        wp_cache_delete( $friend_user_id,    'bp_friends_friendships_for_user' );
     51
     52        // Clear the friendship object cache.
     53        wp_cache_delete( $friendship_id, 'bp_friends_friendships' );
     54}
     55add_action( 'friends_friendship_requested', 'bp_friends_clear_bp_friends_friendships_cache', 10, 3 );
     56add_action( 'friends_friendship_accepted',  'bp_friends_clear_bp_friends_friendships_cache', 10, 3 );
     57add_action( 'friends_friendship_deleted',   'bp_friends_clear_bp_friends_friendships_cache', 10, 3 );
     58
     59/**
     60 * Clear friendship caches on friendship changes.
     61 *
     62 * @since 2.7.0
     63 *
     64 * @param int                   $friendship_id The friendship ID.
     65 * @param BP_Friends_Friendship $friendship Friendship object.
     66 */
     67function bp_friends_clear_bp_friends_friendships_cache_remove( $friendship_id, BP_Friends_Friendship $friendship ) {
     68        // Clear friendship ID cache for each user.
     69        wp_cache_delete( $friendship->initiator_user_id, 'bp_friends_friendships_for_user' );
     70        wp_cache_delete( $friendship->friend_user_id,    'bp_friends_friendships_for_user' );
     71
     72        // Clear the friendship object cache.
     73        wp_cache_delete( $friendship_id, 'bp_friends_friendships' );
     74}
     75add_action( 'friends_friendship_withdrawn', 'bp_friends_clear_bp_friends_friendships_cache_remove', 10, 2 );
     76add_action( 'friends_friendship_rejected',  'bp_friends_clear_bp_friends_friendships_cache_remove', 10, 2 );
     77
     78/**
    3879 * Clear the friend request cache for the user not initiating the friendship.
    3980 *
    4081 * @since 2.0.0
  • src/bp-friends/bp-friends-filters.php

    diff --git src/bp-friends/bp-friends-filters.php src/bp-friends/bp-friends-filters.php
    index 3a06422..9513b47 100644
    function bp_friends_filter_user_query_populate_extras( BP_User_Query $user_query 
    2828        global $wpdb;
    2929
    3030        // Stop if user isn't logged in.
    31         if ( ! is_user_logged_in() ) {
     31        if ( ! $user_id = bp_loggedin_user_id() ) {
    3232                return;
    3333        }
    3434
    35         $bp = buddypress();
     35        $maybe_friend_ids = wp_parse_id_list( $user_ids_sql );
    3636
    37         // Fetch whether or not the user is a friend of the current user.
    38         $friend_status = $wpdb->get_results( $wpdb->prepare( "SELECT initiator_user_id, friend_user_id, is_confirmed FROM {$bp->friends->table_name} WHERE (initiator_user_id = %d AND friend_user_id IN ( {$user_ids_sql} ) ) OR (initiator_user_id IN ( {$user_ids_sql} ) AND friend_user_id = %d )", bp_loggedin_user_id(), bp_loggedin_user_id() ) );
    39 
    40         // Keep track of members that have a friendship status with the current user.
    41         $friend_user_ids = array();
    42 
    43         // The "friend" is the user ID in the pair who is *not* the logged in user.
    44         foreach ( (array) $friend_status as $fs ) {
    45                 $friend_id = bp_loggedin_user_id() == $fs->initiator_user_id ? $fs->friend_user_id : $fs->initiator_user_id;
    46                 $friend_user_ids[] = $friend_id;
    47 
    48                 if ( isset( $user_query->results[ $friend_id ] ) ) {
    49                         if ( 0 == $fs->is_confirmed ) {
    50                                 $status = $fs->initiator_user_id == bp_loggedin_user_id() ? 'pending' : 'awaiting_response';
    51                         } else {
    52                                 $status = 'is_friend';
    53                         }
    54 
    55                         $user_query->results[ $friend_id ]->is_friend         = $fs->is_confirmed;
    56                         $user_query->results[ $friend_id ]->friendship_status = $status;
    57                 }
    58         }
    59 
    60         // The rest are not friends with the current user, so set status accordingly.
    61         $not_friends = array_diff( $user_query->user_ids, $friend_user_ids );
    62         foreach ( (array) $not_friends as $nf ) {
    63                 if ( bp_loggedin_user_id() == $nf ) {
    64                         continue;
    65                 }
    66 
    67                 if ( isset( $user_query->results[ $nf ] ) ) {
    68                         $user_query->results[ $nf ]->friendship_status = 'not_friends';
     37        foreach ( $maybe_friend_ids as $friend_id ) {
     38                $status = BP_Friends_Friendship::check_is_friend( $user_id, $friend_id );
     39                $user_query->results[ $friend_id ]->friendship_status = $status;
     40                if ( 'is_friend' == $status ) {
     41                        $user_query->results[ $friend_id ]->is_friend = 1;
    6942                }
    7043        }
    7144
  • src/bp-friends/classes/class-bp-friends-component.php

    diff --git src/bp-friends/classes/class-bp-friends-component.php src/bp-friends/classes/class-bp-friends-component.php
    index e066898..d6e357b 100644
    class BP_Friends_Component extends BP_Component { 
    288288
    289289                // Global groups.
    290290                wp_cache_add_global_groups( array(
    291                         'bp_friends_requests'
     291                        'bp_friends_requests',
     292                        'bp_friends_friendships', // Individual friendship objects are cached here by ID.
     293                        'bp_friends_friendships_for_user' // All friendship IDs for a single user.
    292294                ) );
    293295
    294296                parent::setup_cache_groups();
  • src/bp-friends/classes/class-bp-friends-friendship.php

    diff --git src/bp-friends/classes/class-bp-friends-friendship.php src/bp-friends/classes/class-bp-friends-friendship.php
    index e607215..430a9e7 100644
    class BP_Friends_Friendship { 
    206206        /** Static Methods ********************************************************/
    207207
    208208        /**
     209         * Get the friendships for a given user.
     210         *
     211         * @since 2.6.0
     212         *
     213         * @param int   $user_id              ID of the user whose friends are being retrieved.
     214         * @param array $args {
     215         *        Optional. Filter parameters.
     216         *        @type int    $id                ID of specific friendship to retrieve.
     217         *        @type int    $initiator_user_id ID of friendship initiator.
     218         *        @type int    $friend_user_id    ID of specific friendship to retrieve.
     219         *        @type int    $is_confirmed      Whether the friendship has been accepted.
     220         *        @type int    $is_limited        Whether the friendship is limited.
     221         *        @type string $order_by          Column name to order by.
     222         *        @type string $sort_order        ASC or DESC. Default DESC.
     223         * }
     224         * @param string $operator            Optional. Operator to use in `wp_list_filter()`.
     225         *
     226         * @return array $friendships Array of friendship objects.
     227         */
     228        public static function get_friendships( $user_id, $args = array(), $operator = 'AND' ) {
     229
     230                if ( empty( $user_id ) ) {
     231                        $user_id = bp_loggedin_user_id();
     232                }
     233
     234                $r = bp_parse_args( $args, array(
     235                        'id'                => null,
     236                        'initiator_user_id' => null,
     237                        'friend_user_id'    => null,
     238                        'is_confirmed'      => null,
     239                        'is_limited'        => null,
     240                        'order_by'          => 'date_created',
     241                        'sort_order'        => 'DESC',
     242                        'page'              => null,
     243                        'per_page'          => null
     244                ), 'bp_get_user_friendships' );
     245
     246                // First, we get all friendships that involve the user.
     247                $friendship_ids = wp_cache_get( $user_id, 'bp_friends_friendships_for_user' );
     248                if ( false === $friendship_ids ) {
     249                        $friendship_ids = self::get_friendship_ids_for_user( $user_id );
     250                        wp_cache_set( $user_id, $friendship_ids, 'bp_friends_friendships_for_user' );
     251                }
     252
     253                // Prime the membership cache.
     254                $uncached_friendship_ids = bp_get_non_cached_ids( $friendship_ids, 'bp_friends_friendships' );
     255                if ( ! empty( $uncached_friendship_ids ) ) {
     256                        $uncached_friendships = self::get_friendships_by_id( $uncached_friendship_ids );
     257
     258                        foreach ( $uncached_friendships as $uncached_friendship ) {
     259                                wp_cache_set( $uncached_friendship->id, $uncached_friendship, 'bp_friends_friendships' );
     260                        }
     261                }
     262
     263                // Assemble filter array.
     264                $filters = wp_array_slice_assoc( $r, array( 'id', 'initiator_user_id', 'friend_user_id', 'is_confirmed', 'is_limited' ) );
     265                foreach ( $filters as $filter_name => $filter_value ) {
     266                        if ( is_null( $filter_value ) ) {
     267                                unset( $filters[ $filter_name ] );
     268                        }
     269                }
     270
     271                // Populate friendship array from cache, and normalize.
     272                $friendships = array();
     273                $int_keys    = array( 'id', 'initiator_user_id', 'friend_user_id' );
     274                $bool_keys   = array( 'is_confirmed', 'is_limited' );
     275                foreach ( $friendship_ids as $friendship_id ) {
     276                        $friendship = wp_cache_get( $friendship_id, 'bp_friends_friendships' );
     277
     278                        // Sanity check.
     279                        if ( ! isset( $friendship->id ) ) {
     280                                continue;
     281                        }
     282
     283                        // Integer values.
     284                        foreach ( $int_keys as $index ) {
     285                                $friendship->{$index} = intval( $friendship->{$index} );
     286                        }
     287
     288                        // Boolean values.
     289                        foreach ( $bool_keys as $index ) {
     290                                $friendship->{$index} = (bool) $friendship->{$index};
     291                        }
     292
     293                        // We need to support the same operators as wp_list_filter().
     294                        if ( 'OR' == $operator || 'NOT' == $operator ) {
     295                                $matched = 0;
     296
     297                                foreach ( $filters as $filter_name => $filter_value ) {
     298                                        if ( isset( $friendship->{$filter_name} ) && $filter_value == $friendship->{$filter_name} ) {
     299                                                $matched++;
     300                                        }
     301                                }
     302
     303                                if ( ( 'OR' == $operator && $matched > 0 )
     304                                  || ( 'NOT' == $operator && 0 == $matched ) ) {
     305                                        $friendships[ $friendship->id ] = $friendship;
     306                                }
     307
     308                        } else {
     309                                /*
     310                                 * This is the more typical 'AND' style of filter.
     311                                 * If any of the filters miss, we move on.
     312                                 */
     313                                foreach ( $filters as $filter_name => $filter_value ) {
     314                                        if ( ! isset( $friendship->{$filter_name} ) || $filter_value != $friendship->{$filter_name} ) {
     315                                                continue 2;
     316                                        }
     317                                }
     318                                $friendships[ $friendship->id ] = $friendship;
     319                        }
     320
     321                }
     322
     323                // Sort the results on a column name.
     324                if ( in_array( $r['order_by'], array( 'id', 'initiator_user_id', 'friend_user_id' ) ) ) {
     325                        // @TODO: use the "preserve_keys" argument here when available.
     326                        $friendships = bp_sort_by_key( $friendships, $r['order_by'] );
     327                }
     328
     329                // Adjust the sort direction of the results.
     330                if ( 'ASC' === strtoupper( $r['sort_order'] ) ) {
     331                        // `true` to preserve keys.
     332                        $friendships = array_reverse( $friendships, true );
     333                }
     334
     335                // Paginate the results.
     336                if ( $r['per_page'] && $r['page'] ) {
     337                        $start       = ( $r['page'] - 1 ) * ( $r['per_page'] );
     338                        $friendships = array_slice( $friendships, $start, $r['per_page'] );
     339                }
     340
     341                return $friendships;
     342        }
     343
     344        /**
     345         * Get all friendship IDs for a user.
     346         *
     347         * @since 2.7.0
     348         *
     349         * @param int $user_id ID of the user.
     350         * @return array
     351         */
     352        public static function get_friendship_ids_for_user( $user_id ) {
     353                global $wpdb;
     354
     355                $bp = buddypress();
     356
     357                $friendship_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id FROM {$bp->friends->table_name} WHERE (initiator_user_id = %d OR friend_user_id = %d) ORDER BY date_created DESC", $user_id, $user_id ) );
     358
     359                return $friendship_ids;
     360        }
     361
     362        /**
    209363         * Get the IDs of a given user's friends.
    210364         *
    211365         * @since 1.0.0
    class BP_Friends_Friendship { 
    221375        public static function get_friend_user_ids( $user_id, $friend_requests_only = false, $assoc_arr = false ) {
    222376                global $wpdb;
    223377
    224                 if ( !empty( $friend_requests_only ) ) {
    225                         $oc_sql = 'AND is_confirmed = 0';
    226                         $friend_sql = $wpdb->prepare( " WHERE friend_user_id = %d", $user_id );
     378                if ( ! empty( $friend_requests_only ) ) {
     379                        $args = array(
     380                                'is_confirmed' => 0,
     381                                'friend_user_id' => $user_id
     382                        );
    227383                } else {
    228                         $oc_sql = 'AND is_confirmed = 1';
    229                         $friend_sql = $wpdb->prepare( " WHERE (initiator_user_id = %d OR friend_user_id = %d)", $user_id, $user_id );
     384                        $args = array(
     385                                'is_confirmed' => 1,
     386                        );
    230387                }
    231388
    232                 $bp = buddypress();
    233                 $friends = $wpdb->get_results( "SELECT friend_user_id, initiator_user_id FROM {$bp->friends->table_name} {$friend_sql} {$oc_sql} ORDER BY date_created DESC" );
    234                 $fids = array();
     389                $friendships = self::get_friendships( $user_id, $args );
    235390
    236                 for ( $i = 0, $count = count( $friends ); $i < $count; ++$i ) {
    237                         if ( !empty( $assoc_arr ) ) {
    238                                 $fids[] = array( 'user_id' => ( $friends[$i]->friend_user_id == $user_id ) ? $friends[$i]->initiator_user_id : $friends[$i]->friend_user_id );
     391                $fids = array();
     392                foreach ( $friendships as $friendship ) {
     393                        if ( ! empty( $assoc_arr ) ) {
     394                                $fids[] = array( 'user_id' => ( $friendship->friend_user_id == $user_id ) ? $friendship->initiator_user_id : $friendship->friend_user_id );
    239395                        } else {
    240                                 $fids[] = ( $friends[$i]->friend_user_id == $user_id ) ? $friends[$i]->initiator_user_id : $friends[$i]->friend_user_id;
     396                                $fids[] = ( $friendship->friend_user_id == $user_id ) ? $friendship->initiator_user_id : $friendship->friend_user_id;
    241397                        }
    242398                }
    243399
    class BP_Friends_Friendship { 
    254410         * @return int|null The ID of the friendship object if found, otherwise null.
    255411         */
    256412        public static function get_friendship_id( $user_id, $friend_id ) {
    257                 global $wpdb;
    258 
    259                 $bp = buddypress();
     413                $friendship_id = null;
    260414
    261                 $query = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->friends->table_name} WHERE ( initiator_user_id = %d AND friend_user_id = %d ) OR ( initiator_user_id = %d AND friend_user_id = %d ) AND is_confirmed = 1", $user_id, $friend_id, $friend_id, $user_id ) );
     415                // Can't friend yourself.
     416                if ( $user_id == $friend_id ) {
     417                        return $friendship_id;
     418                }
    262419
    263                 return is_numeric( $query ) ? (int) $query : $query;
     420                /*
     421                 * Find friendships where the possible_friend_userid is the
     422                 * initiator or friend.
     423                 */
     424                $args = array(
     425                        'initiator_user_id' => $friend_id,
     426                        'friend_user_id'    => $friend_id
     427                );
     428                $result = self::get_friendships( $user_id, $args, 'OR' );
     429                if ( $result ) {
     430                        $friendship_id = current( $result )->id;
     431                }
     432                return $friendship_id;
    264433        }
    265434
    266435        /**
    class BP_Friends_Friendship { 
    276445                $friend_requests = wp_cache_get( $user_id, 'bp_friends_requests' );
    277446
    278447                if ( false === $friend_requests ) {
    279                         global $wpdb;
    280 
    281                         $bp = buddypress();
    282 
    283                         $friend_requests = $wpdb->get_col( $wpdb->prepare( "SELECT initiator_user_id FROM {$bp->friends->table_name} WHERE friend_user_id = %d AND is_confirmed = 0", $user_id ) );
     448                        //@TODO: this uses already cached data, so maybe `bp_friends_requests` should go away?
     449                        $friend_requests = self::get_friend_user_ids( $user_id, true );
    284450
    285451                        wp_cache_set( $user_id, $friend_requests, 'bp_friends_requests' );
    286452                }
    class BP_Friends_Friendship { 
    306472        public static function total_friend_count( $user_id = 0 ) {
    307473                global $wpdb;
    308474
    309                 if ( empty( $user_id ) )
     475                if ( empty( $user_id ) ) {
    310476                        $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
    311 
    312                 $bp = buddypress();
     477                }
    313478
    314479                /*
    315480                 * This is stored in 'total_friend_count' usermeta.
    316481                 * This function will recalculate, update and return.
    317482                 */
    318483
    319                 $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->friends->table_name} WHERE (initiator_user_id = %d OR friend_user_id = %d) AND is_confirmed = 1", $user_id, $user_id ) );
     484                $args = array(
     485                                'is_confirmed' => 1,
     486                );
     487                $friendships = self::get_friendships( $user_id, $args );
     488                $count       = count( $friendships );
    320489
    321490                // Do not update meta if user has never had friends.
    322                 if ( empty( $count ) && !bp_get_user_meta( $user_id, 'total_friend_count', true ) )
     491                if ( ! $count && ! bp_get_user_meta( $user_id, 'total_friend_count', true ) ) {
    323492                        return 0;
     493                }
    324494
    325495                bp_update_user_meta( $user_id, 'total_friend_count', (int) $count );
    326496
    class BP_Friends_Friendship { 
    415585                        return false;
    416586                }
    417587
    418                 $bp = buddypress();
    419 
    420                 $result = $wpdb->get_results( $wpdb->prepare( "SELECT id, initiator_user_id, is_confirmed FROM {$bp->friends->table_name} WHERE (initiator_user_id = %d AND friend_user_id = %d) OR (initiator_user_id = %d AND friend_user_id = %d)", $initiator_userid, $possible_friend_userid, $possible_friend_userid, $initiator_userid ) );
     588                // Can't friend yourself.
     589                if ( $initiator_userid == $possible_friend_userid ) {
     590                        return 'not_friends';
     591                }
    421592
    422                 if ( ! empty( $result ) ) {
    423                         if ( 0 == (int) $result[0]->is_confirmed ) {
    424                                 $status = $initiator_userid == $result[0]->initiator_user_id ? 'pending' : 'awaiting_response';
     593                /*
     594                 * Find friendships where the possible_friend_userid is the
     595                 * initiator or friend.
     596                 */
     597                $args = array(
     598                        'initiator_user_id' => $possible_friend_userid,
     599                        'friend_user_id'    => $possible_friend_userid
     600                );
     601                $result = self::get_friendships( $initiator_userid, $args, 'OR' );
     602
     603                if ( $result ) {
     604                        $friendship = current( $result );
     605                        if ( ! $friendship->is_confirmed ) {
     606                                $status = $initiator_userid == $friendship->initiator_user_id ? 'pending' : 'awaiting_response';
    425607                        } else {
    426608                                $status = 'is_friend';
    427609                        }
    class BP_Friends_Friendship { 
    699881        }
    700882
    701883        /**
     884         * Get friendship objects by ID (or an array of IDs).
     885         *
     886         * @since 2.7.0
     887         *
     888         * @param int|string|array $friendship_ids Single friendship ID or comma-separated/array list of friendship IDs.
     889         * @return array
     890         */
     891        public static function get_friendships_by_id( $friendship_ids ) {
     892                global $wpdb;
     893
     894                $bp = buddypress();
     895
     896                $friendship_ids = implode( ',', wp_parse_id_list( $friendship_ids ) );
     897                return $wpdb->get_results( "SELECT * FROM {$bp->friends->table_name} WHERE id IN ({$friendship_ids})" );
     898        }
     899
     900        /**
    702901         * Get the friend user IDs for a given friendship.
    703902         *
    704903         * @since 1.0.0
    class BP_Friends_Friendship { 
    726925
    727926                $bp = buddypress();
    728927
    729                 // Get friends of $user_id.
    730                 $friend_ids = BP_Friends_Friendship::get_friend_user_ids( $user_id );
     928                // Get all friendships, of any status, for the user.
     929                $friendships    = self::get_friendships( $user_id );
     930                $friend_ids     = array();
     931                $friendship_ids = array();
     932                foreach ( $friendships as $friendship ) {
     933                        $friend_ids[]     = ( $friendship->friend_user_id == $user_id ) ? $friendship->initiator_user_id : $friendship->friend_user_id;
     934                        $friendship_ids[] = $friendship->id;
     935                }
    731936
    732                 // Delete all friendships related to $user_id.
    733                 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->friends->table_name} WHERE friend_user_id = %d OR initiator_user_id = %d", $user_id, $user_id ) );
     937                // Delete the friendships from the database.
     938                if ( $friendship_ids ) {
     939                        $friendship_ids_sql = implode( ',', wp_parse_id_list( $friendship_ids ) );
     940                        $wpdb->query( "DELETE FROM {$bp->friends->table_name} WHERE id IN ({$friendship_ids_sql})" );
     941                }
    734942
    735943                // Delete friend request notifications for members who have a
    736944                // notification from this user.
    class BP_Friends_Friendship { 
    738946                        $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->notifications->table_name} WHERE component_name = 'friends' AND ( component_action = 'friendship_request' OR component_action = 'friendship_accepted' ) AND item_id = %d", $user_id ) );
    739947                }
    740948
    741                 // Loop through friend_ids and update their counts.
     949                // Clean up the friendships cache.
     950                foreach ( $friendship_ids as $friendship_id ) {
     951                        wp_cache_delete( $friendship_id, 'bp_friends_friendships' );
     952                }
     953
     954                // Loop through friend_ids to scrub caches and update their total counts.
    742955                foreach ( (array) $friend_ids as $friend_id ) {
    743956                        BP_Friends_Friendship::total_friend_count( $friend_id );
     957                        // Delete cached friendships.
     958                        wp_cache_delete( $friend_id, 'bp_friends_friendships_for_user' );
    744959                }
     960
     961                // Delete cached friendships.
     962                wp_cache_delete( $user_id, 'bp_friends_friendships_for_user' );
    745963        }
    746964}
  • tests/phpunit/testcases/friends/functions.php

    diff --git tests/phpunit/testcases/friends/functions.php tests/phpunit/testcases/friends/functions.php
    index bd9c148..8c41570 100644
    class BP_Tests_Friends_Functions extends BP_UnitTestCase { 
    267267                $this->filter_fired = current_filter();
    268268                return $value;
    269269        }
     270
     271        /**
     272         * @group friendship_caching
     273         */
     274        public function test_friends_check_friendship_should_hit_user_cache() {
     275                global $wpdb;
     276                $now = time();
     277                $u1 = $this->factory->user->create( array(
     278                        'last_activity' => date( 'Y-m-d H:i:s', $now ),
     279                ) );
     280                $u2 = $this->factory->user->create( array(
     281                        'last_activity' => date( 'Y-m-d H:i:s', $now - 100 ),
     282                ) );
     283                $u3 = $this->factory->user->create( array(
     284                        'last_activity' => date( 'Y-m-d H:i:s', $now - 200 ),
     285                ) );
     286
     287                friends_add_friend( $u1, $u2, true );
     288                friends_add_friend( $u1, $u3, false );
     289
     290                friends_check_friendship_status( $u1, $u2 );
     291                $first_query_count = $wpdb->num_queries;
     292
     293                friends_check_friendship_status( $u1, $u3 );
     294
     295                $this->assertEquals( $first_query_count, $wpdb->num_queries );
     296        }
     297
     298        /**
     299         * @group friendship_caching
     300         */
     301        public function test_friends_check_friendship_should_hit_friendship_object_cache() {
     302                global $wpdb;
     303                $now = time();
     304                $u1 = $this->factory->user->create( array(
     305                        'last_activity' => date( 'Y-m-d H:i:s', $now ),
     306                ) );
     307                $u2 = $this->factory->user->create( array(
     308                        'last_activity' => date( 'Y-m-d H:i:s', $now - 100 ),
     309                ) );
     310
     311                friends_add_friend( $u1, $u2, true );
     312
     313                friends_check_friendship_status( $u1, $u2 );
     314                $first_query_count = $wpdb->num_queries;
     315
     316                /*
     317                 * We expect this to generate one query to find $u2's friendships,
     318                 * but the friendship object itself should come from cache.
     319                 */
     320                friends_check_friendship_status( $u2, $u1 );
     321
     322                $this->assertEquals( $first_query_count + 1, $wpdb->num_queries );
     323        }
    270324}