[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-friends/classes/ -> class-bp-friends-friendship.php (source)

   1  <?php
   2  /**
   3   * BuddyPress Friends Classes.
   4   *
   5   * @package BuddyPress
   6   * @subpackage FriendsClasses
   7   * @since 1.0.0
   8   */
   9  
  10  // Exit if accessed directly.
  11  defined( 'ABSPATH' ) || exit;
  12  
  13  /**
  14   * BuddyPress Friendship object.
  15   *
  16   * @since 1.0.0
  17   */
  18  class BP_Friends_Friendship {
  19  
  20      /**
  21       * ID of the friendship.
  22       *
  23       * @since 1.0.0
  24       * @var int
  25       */
  26      public $id;
  27  
  28      /**
  29       * User ID of the friendship initiator.
  30       *
  31       * @since 1.0.0
  32       * @var int
  33       */
  34      public $initiator_user_id;
  35  
  36      /**
  37       * User ID of the 'friend' - the one invited to the friendship.
  38       *
  39       * @since 1.0.0
  40       * @var int
  41       */
  42      public $friend_user_id;
  43  
  44      /**
  45       * Has the friendship been confirmed/accepted?
  46       *
  47       * @since 1.0.0
  48       * @var int
  49       */
  50      public $is_confirmed;
  51  
  52      /**
  53       * Is this a "limited" friendship?
  54       *
  55       * Not currently used by BuddyPress.
  56       *
  57       * @since 1.0.0
  58       * @var int
  59       */
  60      public $is_limited;
  61  
  62      /**
  63       * Date the friendship was created.
  64       *
  65       * @since 1.0.0
  66       * @var string
  67       */
  68      public $date_created;
  69  
  70      /**
  71       * Is this a request?
  72       *
  73       * Not currently used in BuddyPress.
  74       *
  75       * @since 1.0.0
  76       * @var bool
  77       */
  78      public $is_request;
  79  
  80      /**
  81       * Should additional friend details be queried?
  82       *
  83       * @since 1.0.0
  84       * @var bool
  85       */
  86      public $populate_friend_details;
  87  
  88      /**
  89       * Details about the friend.
  90       *
  91       * @since 1.0.0
  92       * @var BP_Core_User
  93       */
  94      public $friend;
  95  
  96      /**
  97       * Constructor method.
  98       *
  99       * @since 1.5.0
 100       *
 101       * @param int|null $id                      Optional. The ID of an existing friendship.
 102       * @param bool     $is_request              Deprecated.
 103       * @param bool     $populate_friend_details True if friend details should be queried.
 104       */
 105  	public function __construct( $id = null, $is_request = false, $populate_friend_details = true ) {
 106          $this->is_request = $is_request;
 107  
 108          if ( !empty( $id ) ) {
 109              $this->id                      = (int) $id;
 110              $this->populate_friend_details = $populate_friend_details;
 111              $this->populate( $this->id );
 112          }
 113      }
 114  
 115      /**
 116       * Set up data about the current friendship.
 117       *
 118       * @since 1.0.0
 119       */
 120  	public function populate() {
 121          global $wpdb;
 122  
 123          $bp = buddypress();
 124  
 125          // Check cache for friendship data.
 126          $friendship = wp_cache_get( $this->id, 'bp_friends_friendships' );
 127  
 128          // Cache missed, so query the DB.
 129          if ( false === $friendship ) {
 130              $friendship = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->friends->table_name} WHERE id = %d", $this->id ) );
 131  
 132              wp_cache_set( $this->id, $friendship, 'bp_friends_friendships' );
 133          }
 134  
 135          // No friendship found so set the ID and bail.
 136          if ( empty( $friendship ) || is_wp_error( $friendship ) ) {
 137              $this->id = 0;
 138              return;
 139          }
 140  
 141          $this->initiator_user_id = (int) $friendship->initiator_user_id;
 142          $this->friend_user_id    = (int) $friendship->friend_user_id;
 143          $this->is_confirmed      = (int) $friendship->is_confirmed;
 144          $this->is_limited        = (int) $friendship->is_limited;
 145          $this->date_created      = $friendship->date_created;
 146  
 147          if ( ! empty( $this->populate_friend_details ) ) {
 148              if ( $this->friend_user_id == bp_displayed_user_id() ) {
 149                  $this->friend = new BP_Core_User( $this->initiator_user_id );
 150              } else {
 151                  $this->friend = new BP_Core_User( $this->friend_user_id );
 152              }
 153          }
 154      }
 155  
 156      /**
 157       * Save the current friendship to the database.
 158       *
 159       * @since 1.0.0
 160       *
 161       * @return bool True on success, false on failure.
 162       */
 163  	public function save() {
 164          global $wpdb;
 165  
 166          $bp = buddypress();
 167  
 168          $this->initiator_user_id = apply_filters( 'friends_friendship_initiator_user_id_before_save', $this->initiator_user_id, $this->id );
 169          $this->friend_user_id    = apply_filters( 'friends_friendship_friend_user_id_before_save',    $this->friend_user_id,    $this->id );
 170          $this->is_confirmed      = apply_filters( 'friends_friendship_is_confirmed_before_save',      $this->is_confirmed,      $this->id );
 171          $this->is_limited        = apply_filters( 'friends_friendship_is_limited_before_save',        $this->is_limited,        $this->id );
 172          $this->date_created      = apply_filters( 'friends_friendship_date_created_before_save',      $this->date_created,      $this->id );
 173  
 174          /**
 175           * Fires before processing and saving the current friendship request.
 176           *
 177           * @since 1.0.0
 178           *
 179           * @param BP_Friends_Friendship $value Current friendship request object.
 180           */
 181          do_action_ref_array( 'friends_friendship_before_save', array( &$this ) );
 182  
 183          // Update.
 184          if (!empty( $this->id ) ) {
 185              $result = $wpdb->query( $wpdb->prepare( "UPDATE {$bp->friends->table_name} SET initiator_user_id = %d, friend_user_id = %d, is_confirmed = %d, is_limited = %d, date_created = %s WHERE id = %d", $this->initiator_user_id, $this->friend_user_id, $this->is_confirmed, $this->is_limited, $this->date_created, $this->id ) );
 186  
 187          // Save.
 188          } else {
 189              $result = $wpdb->query( $wpdb->prepare( "INSERT INTO {$bp->friends->table_name} ( initiator_user_id, friend_user_id, is_confirmed, is_limited, date_created ) VALUES ( %d, %d, %d, %d, %s )", $this->initiator_user_id, $this->friend_user_id, $this->is_confirmed, $this->is_limited, $this->date_created ) );
 190              $this->id = $wpdb->insert_id;
 191          }
 192  
 193          /**
 194           * Fires after processing and saving the current friendship request.
 195           *
 196           * @since 1.0.0
 197           *
 198           * @param BP_Friends_Friendship $value Current friendship request object.
 199           */
 200          do_action_ref_array( 'friends_friendship_after_save', array( &$this ) );
 201  
 202          return $result;
 203      }
 204  
 205      /**
 206       * Delete the current friendship from the database.
 207       *
 208       * @since 1.0.0
 209       *
 210       * @return bool|int
 211       */
 212  	public function delete() {
 213          global $wpdb;
 214  
 215          $bp = buddypress();
 216  
 217          return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->friends->table_name} WHERE id = %d", $this->id ) );
 218      }
 219  
 220      /** Static Methods ********************************************************/
 221  
 222      /**
 223       * Get the friendships for a given user.
 224       *
 225       * @since 2.6.0
 226       *
 227       * @param int   $user_id              ID of the user whose friends are being retrieved.
 228       * @param array $args {
 229       *        Optional. Filter parameters.
 230       *        @type int    $id                ID of specific friendship to retrieve.
 231       *        @type int    $initiator_user_id ID of friendship initiator.
 232       *        @type int    $friend_user_id    ID of specific friendship to retrieve.
 233       *        @type int    $is_confirmed      Whether the friendship has been accepted.
 234       *        @type int    $is_limited        Whether the friendship is limited.
 235       *        @type string $order_by          Column name to order by.
 236       *        @type string $sort_order        ASC or DESC. Default DESC.
 237       * }
 238       * @param string $operator            Optional. Operator to use in `wp_list_filter()`.
 239       *
 240       * @return array $friendships Array of friendship objects.
 241       */
 242  	public static function get_friendships( $user_id, $args = array(), $operator = 'AND' ) {
 243  
 244          if ( empty( $user_id ) ) {
 245              $user_id = bp_loggedin_user_id();
 246          }
 247  
 248          $r = bp_parse_args( $args, array(
 249              'id'                => null,
 250              'initiator_user_id' => null,
 251              'friend_user_id'    => null,
 252              'is_confirmed'      => null,
 253              'is_limited'        => null,
 254              'order_by'          => 'date_created',
 255              'sort_order'        => 'DESC',
 256              'page'              => null,
 257              'per_page'          => null
 258          ), 'bp_get_user_friendships' );
 259  
 260          // First, we get all friendships that involve the user.
 261          $friendship_ids = wp_cache_get( $user_id, 'bp_friends_friendships_for_user' );
 262          if ( false === $friendship_ids ) {
 263              $friendship_ids = self::get_friendship_ids_for_user( $user_id );
 264              wp_cache_set( $user_id, $friendship_ids, 'bp_friends_friendships_for_user' );
 265          }
 266  
 267          // Prime the membership cache.
 268          $uncached_friendship_ids = bp_get_non_cached_ids( $friendship_ids, 'bp_friends_friendships' );
 269          if ( ! empty( $uncached_friendship_ids ) ) {
 270              $uncached_friendships = self::get_friendships_by_id( $uncached_friendship_ids );
 271  
 272              foreach ( $uncached_friendships as $uncached_friendship ) {
 273                  wp_cache_set( $uncached_friendship->id, $uncached_friendship, 'bp_friends_friendships' );
 274              }
 275          }
 276  
 277          // Assemble filter array.
 278          $filters = wp_array_slice_assoc( $r, array( 'id', 'initiator_user_id', 'friend_user_id', 'is_confirmed', 'is_limited' ) );
 279          foreach ( $filters as $filter_name => $filter_value ) {
 280              if ( is_null( $filter_value ) ) {
 281                  unset( $filters[ $filter_name ] );
 282              }
 283          }
 284  
 285          // Populate friendship array from cache, and normalize.
 286          $friendships = array();
 287          $int_keys    = array( 'id', 'initiator_user_id', 'friend_user_id' );
 288          $bool_keys   = array( 'is_confirmed', 'is_limited' );
 289          foreach ( $friendship_ids as $friendship_id ) {
 290              // Create a limited BP_Friends_Friendship object (don't fetch the user details).
 291              $friendship = new BP_Friends_Friendship( $friendship_id, false, false );
 292  
 293              // Sanity check.
 294              if ( ! isset( $friendship->id ) ) {
 295                  continue;
 296              }
 297  
 298              // Integer values.
 299              foreach ( $int_keys as $index ) {
 300                  $friendship->{$index} = intval( $friendship->{$index} );
 301              }
 302  
 303              // Boolean values.
 304              foreach ( $bool_keys as $index ) {
 305                  $friendship->{$index} = (bool) $friendship->{$index};
 306              }
 307  
 308              // We need to support the same operators as wp_list_filter().
 309              if ( 'OR' == $operator || 'NOT' == $operator ) {
 310                  $matched = 0;
 311  
 312                  foreach ( $filters as $filter_name => $filter_value ) {
 313                      if ( isset( $friendship->{$filter_name} ) && $filter_value == $friendship->{$filter_name} ) {
 314                          $matched++;
 315                      }
 316                  }
 317  
 318                  if ( ( 'OR' == $operator && $matched > 0 )
 319                    || ( 'NOT' == $operator && 0 == $matched ) ) {
 320                      $friendships[ $friendship->id ] = $friendship;
 321                  }
 322  
 323              } else {
 324                  /*
 325                   * This is the more typical 'AND' style of filter.
 326                   * If any of the filters miss, we move on.
 327                   */
 328                  foreach ( $filters as $filter_name => $filter_value ) {
 329                      if ( ! isset( $friendship->{$filter_name} ) || $filter_value != $friendship->{$filter_name} ) {
 330                          continue 2;
 331                      }
 332                  }
 333                  $friendships[ $friendship->id ] = $friendship;
 334              }
 335  
 336          }
 337  
 338          // Sort the results on a column name.
 339          if ( in_array( $r['order_by'], array( 'id', 'initiator_user_id', 'friend_user_id' ) ) ) {
 340              $friendships = bp_sort_by_key( $friendships, $r['order_by'], 'num', true );
 341          }
 342  
 343          // Adjust the sort direction of the results.
 344          if ( 'ASC' === strtoupper( $r['sort_order'] ) ) {
 345              // `true` to preserve keys.
 346              $friendships = array_reverse( $friendships, true );
 347          }
 348  
 349          // Paginate the results.
 350          if ( $r['per_page'] && $r['page'] ) {
 351              $start       = ( $r['page'] - 1 ) * ( $r['per_page'] );
 352              $friendships = array_slice( $friendships, $start, $r['per_page'] );
 353          }
 354  
 355          return $friendships;
 356      }
 357  
 358      /**
 359       * Get all friendship IDs for a user.
 360       *
 361       * @since 2.7.0
 362       *
 363       * @param int $user_id ID of the user.
 364       * @return array
 365       */
 366  	public static function get_friendship_ids_for_user( $user_id ) {
 367          global $wpdb;
 368  
 369          $bp = buddypress();
 370  
 371          $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 ) );
 372  
 373          return $friendship_ids;
 374      }
 375  
 376      /**
 377       * Get the IDs of a given user's friends.
 378       *
 379       * @since 1.0.0
 380       *
 381       * @param int  $user_id              ID of the user whose friends are being retrieved.
 382       * @param bool $friend_requests_only Optional. Whether to fetch
 383       *                                   unaccepted requests only. Default: false.
 384       * @param bool $assoc_arr            Optional. True to receive an array of arrays
 385       *                                   keyed as 'user_id' => $user_id; false to get a one-dimensional
 386       *                                   array of user IDs. Default: false.
 387       * @return array $fids IDs of friends for provided user.
 388       */
 389  	public static function get_friend_user_ids( $user_id, $friend_requests_only = false, $assoc_arr = false ) {
 390          global $wpdb;
 391  
 392          if ( ! empty( $friend_requests_only ) ) {
 393              $args = array(
 394                  'is_confirmed' => 0,
 395                  'friend_user_id' => $user_id
 396              );
 397          } else {
 398              $args = array(
 399                  'is_confirmed' => 1,
 400              );
 401          }
 402  
 403          $friendships = self::get_friendships( $user_id, $args );
 404  
 405          $fids = array();
 406          foreach ( $friendships as $friendship ) {
 407              if ( ! empty( $assoc_arr ) ) {
 408                  $fids[] = array( 'user_id' => ( $friendship->friend_user_id == $user_id ) ? $friendship->initiator_user_id : $friendship->friend_user_id );
 409              } else {
 410                  $fids[] = ( $friendship->friend_user_id == $user_id ) ? $friendship->initiator_user_id : $friendship->friend_user_id;
 411              }
 412          }
 413  
 414          return array_map( 'intval', $fids );
 415      }
 416  
 417      /**
 418       * Get the ID of the friendship object, if any, between a pair of users.
 419       *
 420       * @since 1.0.0
 421       *
 422       * @param int $user_id   The ID of the first user.
 423       * @param int $friend_id The ID of the second user.
 424       * @return int|null The ID of the friendship object if found, otherwise null.
 425       */
 426  	public static function get_friendship_id( $user_id, $friend_id ) {
 427          $friendship_id = null;
 428  
 429          // Can't friend yourself.
 430          if ( $user_id == $friend_id ) {
 431              return $friendship_id;
 432          }
 433  
 434          /*
 435           * Find friendships where the possible_friend_userid is the
 436           * initiator or friend.
 437           */
 438          $args = array(
 439              'initiator_user_id' => $friend_id,
 440              'friend_user_id'    => $friend_id
 441          );
 442          $result = self::get_friendships( $user_id, $args, 'OR' );
 443          if ( $result ) {
 444              $friendship_id = current( $result )->id;
 445          }
 446          return $friendship_id;
 447      }
 448  
 449      /**
 450       * Get a list of IDs of users who have requested friendship of a given user.
 451       *
 452       * @since 1.2.0
 453       *
 454       * @param int $user_id The ID of the user who has received the
 455       *                     friendship requests.
 456       * @return array|bool An array of user IDs, or false if none are found.
 457       */
 458  	public static function get_friendship_request_user_ids( $user_id ) {
 459          $friend_requests = wp_cache_get( $user_id, 'bp_friends_requests' );
 460  
 461          if ( false === $friend_requests ) {
 462              $friend_requests = self::get_friend_user_ids( $user_id, true );
 463  
 464              wp_cache_set( $user_id, $friend_requests, 'bp_friends_requests' );
 465          }
 466  
 467          // Integer casting.
 468          if ( ! empty( $friend_requests ) ) {
 469              $friend_requests = array_map( 'intval', $friend_requests );
 470          }
 471  
 472          return $friend_requests;
 473      }
 474  
 475      /**
 476       * Get a total friend count for a given user.
 477       *
 478       * @since 1.0.0
 479       *
 480       * @param int $user_id Optional. ID of the user whose friendships you
 481       *                     are counting. Default: displayed user (if any), otherwise
 482       *                     logged-in user.
 483       * @return int Friend count for the user.
 484       */
 485  	public static function total_friend_count( $user_id = 0 ) {
 486          global $wpdb;
 487  
 488          if ( empty( $user_id ) ) {
 489              $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
 490          }
 491  
 492          /*
 493           * This is stored in 'total_friend_count' usermeta.
 494           * This function will recalculate, update and return.
 495           */
 496  
 497          $args = array(
 498              'is_confirmed' => 1,
 499          );
 500          $friendships = self::get_friendships( $user_id, $args );
 501          $count       = count( $friendships );
 502  
 503          // Do not update meta if user has never had friends.
 504          if ( ! $count && ! bp_get_user_meta( $user_id, 'total_friend_count', true ) ) {
 505              return 0;
 506          }
 507  
 508          bp_update_user_meta( $user_id, 'total_friend_count', (int) $count );
 509  
 510          return absint( $count );
 511      }
 512  
 513      /**
 514       * Search the friends of a user by a search string.
 515       *
 516       * @since 1.0.0
 517       *
 518       * @param string   $filter  The search string, matched against xprofile
 519       *                        fields (if available), or usermeta 'nickname' field.
 520       * @param int      $user_id ID of the user whose friends are being searched.
 521       * @param int|null $limit   Optional. Max number of friends to return.
 522       * @param int|null $page    Optional. The page of results to return. Default:
 523       *                          null (no pagination - return all results).
 524       * @return array|bool On success, an array: {
 525       *     @type array $friends IDs of friends returned by the query.
 526       *     @type int   $count   Total number of friends (disregarding
 527       *                          pagination) who match the search.
 528       * }. Returns false on failure.
 529       */
 530  	public static function search_friends( $filter, $user_id, $limit = null, $page = null ) {
 531          global $wpdb;
 532  
 533          /*
 534           * TODO: Optimize this function.
 535           */
 536  
 537          if ( empty( $user_id ) )
 538              $user_id = bp_loggedin_user_id();
 539  
 540          // Only search for matching strings at the beginning of the
 541          // name (@todo - figure out why this restriction).
 542          $search_terms_like = bp_esc_like( $filter ) . '%';
 543  
 544          $pag_sql = '';
 545          if ( !empty( $limit ) && !empty( $page ) )
 546              $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) );
 547  
 548          if ( !$friend_ids = BP_Friends_Friendship::get_friend_user_ids( $user_id ) )
 549              return false;
 550  
 551          // Get all the user ids for the current user's friends.
 552          $fids = implode( ',', wp_parse_id_list( $friend_ids ) );
 553  
 554          if ( empty( $fids ) )
 555              return false;
 556  
 557          $bp = buddypress();
 558  
 559          // Filter the user_ids based on the search criteria.
 560          if ( bp_is_active( 'xprofile' ) ) {
 561              $sql       = $wpdb->prepare( "SELECT DISTINCT user_id FROM {$bp->profile->table_name_data} WHERE user_id IN ({$fids}) AND value LIKE %s {$pag_sql}", $search_terms_like );
 562              $total_sql = $wpdb->prepare( "SELECT COUNT(DISTINCT user_id) FROM {$bp->profile->table_name_data} WHERE user_id IN ({$fids}) AND value LIKE %s", $search_terms_like );
 563          } else {
 564              $sql       = $wpdb->prepare( "SELECT DISTINCT user_id FROM {$wpdb->usermeta} WHERE user_id IN ({$fids}) AND meta_key = 'nickname' AND meta_value LIKE %s {$pag_sql}", $search_terms_like );
 565              $total_sql = $wpdb->prepare( "SELECT COUNT(DISTINCT user_id) FROM {$wpdb->usermeta} WHERE user_id IN ({$fids}) AND meta_key = 'nickname' AND meta_value LIKE %s", $search_terms_like );
 566          }
 567  
 568          $filtered_friend_ids = $wpdb->get_col( $sql );
 569          $total_friend_ids    = $wpdb->get_var( $total_sql );
 570  
 571          if ( empty( $filtered_friend_ids ) )
 572              return false;
 573  
 574          return array( 'friends' => array_map( 'intval', $filtered_friend_ids ), 'total' => (int) $total_friend_ids );
 575      }
 576  
 577      /**
 578       * Check friendship status between two users.
 579       *
 580       * Note that 'pending' means that $initiator_userid has sent a friend
 581       * request to $possible_friend_userid that has not yet been approved,
 582       * while 'awaiting_response' is the other way around ($possible_friend_userid
 583       * sent the initial request).
 584       *
 585       * @since 1.0.0
 586       *
 587       * @param int $initiator_userid       The ID of the user who is the initiator
 588       *                                    of the potential friendship/request.
 589       * @param int $possible_friend_userid The ID of the user who is the
 590       *                                    recipient of the potential friendship/request.
 591       * @return string|false $value The friendship status, from among 'not_friends',
 592       *                             'is_friend', 'pending', and 'awaiting_response'.
 593       */
 594  	public static function check_is_friend( $initiator_userid, $possible_friend_userid ) {
 595          global $wpdb;
 596  
 597          if ( empty( $initiator_userid ) || empty( $possible_friend_userid ) ) {
 598              return false;
 599          }
 600  
 601          // Can't friend yourself.
 602          if ( $initiator_userid == $possible_friend_userid ) {
 603              return 'not_friends';
 604          }
 605  
 606          BP_Friends_Friendship::update_bp_friends_cache( $initiator_userid, $possible_friend_userid );
 607  
 608          return bp_core_get_incremented_cache( $initiator_userid . ':' . $possible_friend_userid, 'bp_friends' );
 609      }
 610  
 611  
 612      /**
 613       * Find uncached friendships between a user and one or more other users and cache them.
 614       *
 615       * @since 3.0.0
 616       *
 617       * @param int $user_id                          The ID of the primary user for whom we want
 618       *                                              to check friendships statuses.
 619       * @param int|array|string $possible_friend_ids The IDs of the one or more users
 620       *                                              to check friendship status with primary user.
 621       * @return null
 622       */
 623  	public static function update_bp_friends_cache( $user_id, $possible_friend_ids ) {
 624          global $wpdb;
 625          $bp = buddypress();
 626          $possible_friend_ids = wp_parse_id_list( $possible_friend_ids );
 627  
 628          $fetch = array();
 629          foreach ( $possible_friend_ids as $friend_id ) {
 630              // Check for cached items in both friendship directions.
 631              if ( false === bp_core_get_incremented_cache( $user_id . ':' . $friend_id, 'bp_friends' )
 632                  || false === bp_core_get_incremented_cache( $friend_id . ':' . $user_id, 'bp_friends' ) ) {
 633                  $fetch[] = $friend_id;
 634              }
 635          }
 636          if ( empty( $fetch ) ) {
 637              return;
 638          }
 639  
 640          $friend_ids_sql = implode( ',', array_unique( $fetch ) );
 641          $sql = $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 ({$friend_ids_sql}) ) OR (initiator_user_id IN ({$friend_ids_sql}) AND friend_user_id = %d )", $user_id, $user_id );
 642          $friendships = $wpdb->get_results( $sql );
 643  
 644          // Use $handled to keep track of all of the $possible_friend_ids we've matched.
 645          $handled = array();
 646          foreach ( $friendships as $friendship ) {
 647              $initiator_user_id = (int) $friendship->initiator_user_id;
 648              $friend_user_id    = (int) $friendship->friend_user_id;
 649              if ( 1 === (int) $friendship->is_confirmed ) {
 650                  $status_initiator = $status_friend = 'is_friend';
 651              } else {
 652                  $status_initiator = 'pending';
 653                  $status_friend    = 'awaiting_response';
 654              }
 655              bp_core_set_incremented_cache( $initiator_user_id . ':' . $friend_user_id, 'bp_friends', $status_initiator );
 656              bp_core_set_incremented_cache( $friend_user_id . ':' . $initiator_user_id, 'bp_friends', $status_friend );
 657  
 658              $handled[] = ( $initiator_user_id === $user_id ) ? $friend_user_id : $initiator_user_id;
 659          }
 660  
 661          // Set all those with no matching entry to "not friends" status.
 662          $not_friends = array_diff( $fetch, $handled );
 663  
 664          foreach ( $not_friends as $not_friend_id ) {
 665              bp_core_set_incremented_cache( $user_id . ':' . $not_friend_id, 'bp_friends', 'not_friends' );
 666              bp_core_set_incremented_cache( $not_friend_id . ':' . $user_id, 'bp_friends', 'not_friends' );
 667          }
 668      }
 669  
 670      /**
 671       * Get the last active date of many users at once.
 672       *
 673       * @todo Why is this in the Friends component?
 674       *
 675       * @since 1.0.0
 676       *
 677       * @param array $user_ids IDs of users whose last_active meta is
 678       *                        being queried.
 679       * @return array $retval Array of last_active values + user_ids.
 680       */
 681  	public static function get_bulk_last_active( $user_ids ) {
 682          global $wpdb;
 683  
 684          $last_activities = BP_Core_User::get_last_activity( $user_ids );
 685  
 686          // Sort and structure as expected in legacy function.
 687          usort( $last_activities, function( $a, $b ) {
 688              if ( $a['date_recorded'] == $b['date_recorded'] ) {
 689                  return 0;
 690              }
 691  
 692              return ( strtotime( $a['date_recorded'] ) < strtotime( $b['date_recorded'] ) ) ? 1 : -1;
 693          } );
 694  
 695          $retval = array();
 696          foreach ( $last_activities as $last_activity ) {
 697              $u = new stdClass;
 698              $u->last_activity = $last_activity['date_recorded'];
 699              $u->user_id       = $last_activity['user_id'];
 700  
 701              $retval[] = $u;
 702          }
 703  
 704          return $retval;
 705      }
 706  
 707      /**
 708       * Mark a friendship as accepted.
 709       *
 710       * @since 1.0.0
 711       *
 712       * @param int $friendship_id ID of the friendship to be accepted.
 713       * @return int Number of database rows updated.
 714       */
 715  	public static function accept($friendship_id) {
 716          global $wpdb;
 717  
 718          $bp = buddypress();
 719  
 720          return $wpdb->query( $wpdb->prepare( "UPDATE {$bp->friends->table_name} SET is_confirmed = 1, date_created = %s WHERE id = %d AND friend_user_id = %d", bp_core_current_time(), $friendship_id, bp_loggedin_user_id() ) );
 721      }
 722  
 723      /**
 724       * Remove a friendship or a friendship request INITIATED BY the logged-in user.
 725       *
 726       * @since 1.6.0
 727       *
 728       * @param int $friendship_id ID of the friendship to be withdrawn.
 729       * @return int Number of database rows deleted.
 730       */
 731  	public static function withdraw($friendship_id) {
 732          global $wpdb;
 733  
 734          $bp = buddypress();
 735  
 736          return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->friends->table_name} WHERE id = %d AND initiator_user_id = %d", $friendship_id, bp_loggedin_user_id() ) );
 737      }
 738  
 739      /**
 740       * Remove a friendship or a friendship request MADE OF the logged-in user.
 741       *
 742       * @since 1.0.0
 743       *
 744       * @param int $friendship_id ID of the friendship to be rejected.
 745       * @return int Number of database rows deleted.
 746       */
 747  	public static function reject($friendship_id) {
 748          global $wpdb;
 749  
 750          $bp = buddypress();
 751  
 752          return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->friends->table_name} WHERE id = %d AND friend_user_id = %d", $friendship_id, bp_loggedin_user_id() ) );
 753      }
 754  
 755      /**
 756       * Search users.
 757       *
 758       * @todo Why does this exist, and why is it in bp-friends?
 759       *
 760       * @since 1.0.0
 761       *
 762       * @param string   $filter  String to search by.
 763       * @param int      $user_id A user ID param that is unused.
 764       * @param int|null $limit   Optional. Max number of records to return.
 765       * @param int|null $page    Optional. Number of the page to return. Default:
 766       *                          false (no pagination - return all results).
 767       * @return array $filtered_ids IDs of users who match the query.
 768       */
 769  	public static function search_users( $filter, $user_id, $limit = null, $page = null ) {
 770          global $wpdb;
 771  
 772          // Only search for matching strings at the beginning of the
 773          // name (@todo - figure out why this restriction).
 774          $search_terms_like = bp_esc_like( $filter ) . '%';
 775  
 776          $usermeta_table = $wpdb->base_prefix . 'usermeta';
 777          $users_table    = $wpdb->base_prefix . 'users';
 778  
 779          $pag_sql = '';
 780          if ( !empty( $limit ) && !empty( $page ) )
 781              $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * intval( $limit ) ), intval( $limit ) );
 782  
 783          $bp = buddypress();
 784  
 785          // Filter the user_ids based on the search criteria.
 786          if ( bp_is_active( 'xprofile' ) ) {
 787              $sql = $wpdb->prepare( "SELECT DISTINCT d.user_id as id FROM {$bp->profile->table_name_data} d, {$users_table} u WHERE d.user_id = u.id AND d.value LIKE %s ORDER BY d.value DESC {$pag_sql}", $search_terms_like );
 788          } else {
 789              $sql = $wpdb->prepare( "SELECT DISTINCT user_id as id FROM {$usermeta_table} WHERE meta_value LIKE %s ORDER BY d.value DESC {$pag_sql}", $search_terms_like );
 790          }
 791  
 792          $filtered_fids = $wpdb->get_col($sql);
 793  
 794          if ( empty( $filtered_fids ) )
 795              return false;
 796  
 797          return $filtered_fids;
 798      }
 799  
 800      /**
 801       * Get a count of users who match a search term.
 802       *
 803       * @todo Why does this exist, and why is it in bp-friends?
 804       *
 805       * @since 1.0.0
 806       *
 807       * @param string $filter Search term.
 808       * @return int Count of users matching the search term.
 809       */
 810  	public static function search_users_count( $filter ) {
 811          global $wpdb;
 812  
 813          // Only search for matching strings at the beginning of the
 814          // name (@todo - figure out why this restriction).
 815          $search_terms_like = bp_esc_like( $filter ) . '%';
 816  
 817          $usermeta_table = $wpdb->prefix . 'usermeta';
 818          $users_table    = $wpdb->base_prefix . 'users';
 819  
 820          $bp = buddypress();
 821  
 822          // Filter the user_ids based on the search criteria.
 823          if ( bp_is_active( 'xprofile' ) ) {
 824              $sql = $wpdb->prepare( "SELECT COUNT(DISTINCT d.user_id) FROM {$bp->profile->table_name_data} d, {$users_table} u WHERE d.user_id = u.id AND d.value LIKE %s", $search_terms_like );
 825          } else {
 826              $sql = $wpdb->prepare( "SELECT COUNT(DISTINCT user_id) FROM {$usermeta_table} WHERE meta_value LIKE %s", $search_terms_like );
 827          }
 828  
 829          $user_count = $wpdb->get_col($sql);
 830  
 831          if ( empty( $user_count ) )
 832              return false;
 833  
 834          return $user_count[0];
 835      }
 836  
 837      /**
 838       * Sort a list of user IDs by their display names.
 839       *
 840       * @todo Why does this exist, and why is it in bp-friends?
 841       *
 842       * @since 1.0.0
 843       *
 844       * @param array $user_ids Array of user IDs.
 845       * @return array User IDs, sorted by the associated display names.
 846       */
 847  	public static function sort_by_name( $user_ids ) {
 848          global $wpdb;
 849  
 850          if ( !bp_is_active( 'xprofile' ) )
 851              return false;
 852  
 853          $bp = buddypress();
 854  
 855          $user_ids = implode( ',', wp_parse_id_list( $user_ids ) );
 856  
 857          return $wpdb->get_results( $wpdb->prepare( "SELECT user_id FROM {$bp->profile->table_name_data} pd, {$bp->profile->table_name_fields} pf WHERE pf.id = pd.field_id AND pf.name = %s AND pd.user_id IN ( {$user_ids} ) ORDER BY pd.value ASC", bp_xprofile_fullname_field_name() ) );
 858      }
 859  
 860      /**
 861       * Get a list of random friend IDs.
 862       *
 863       * @since 1.0.0
 864       *
 865       * @param int $user_id       ID of the user whose friends are being retrieved.
 866       * @param int $total_friends Optional. Number of random friends to get.
 867       *                           Default: 5.
 868       * @return array|false An array of random friend user IDs on success;
 869       *                     false if none are found.
 870       */
 871  	public static function get_random_friends( $user_id, $total_friends = 5 ) {
 872          global $wpdb;
 873  
 874          $bp      = buddypress();
 875          $fids    = array();
 876          $sql     = $wpdb->prepare( "SELECT friend_user_id, initiator_user_id FROM {$bp->friends->table_name} WHERE (friend_user_id = %d || initiator_user_id = %d) && is_confirmed = 1 ORDER BY rand() LIMIT %d", $user_id, $user_id, $total_friends );
 877          $results = $wpdb->get_results( $sql );
 878  
 879          for ( $i = 0, $count = count( $results ); $i < $count; ++$i ) {
 880              $fids[] = ( $results[$i]->friend_user_id == $user_id ) ? $results[$i]->initiator_user_id : $results[$i]->friend_user_id;
 881          }
 882  
 883          // Remove duplicates.
 884          if ( count( $fids ) > 0 )
 885              return array_flip( array_flip( $fids ) );
 886          else
 887              return false;
 888      }
 889  
 890      /**
 891       * Get a count of a user's friends who can be invited to a given group.
 892       *
 893       * Users can invite any of their friends except:
 894       *
 895       * - users who are already in the group
 896       * - users who have a pending invite to the group
 897       * - users who have been banned from the group
 898       *
 899       * @since 1.0.0
 900       * @todo Need to do a group component check before using group functions.
 901       *
 902       * @param int $user_id  ID of the user whose friends are being counted.
 903       * @param int $group_id ID of the group friends are being invited to.
 904       * @return int $invitable_count Eligible friend count.
 905       */
 906  	public static function get_invitable_friend_count( $user_id, $group_id ) {
 907  
 908          // Setup some data we'll use below.
 909          $is_group_admin  = groups_is_user_admin( $user_id, $group_id );
 910          $friend_ids      = BP_Friends_Friendship::get_friend_user_ids( $user_id );
 911          $invitable_count = 0;
 912  
 913          for ( $i = 0, $count = count( $friend_ids ); $i < $count; ++$i ) {
 914  
 915              // If already a member, they cannot be invited again.
 916              if ( groups_is_user_member( (int) $friend_ids[$i], $group_id ) ) {
 917                  continue;
 918              }
 919  
 920              // If user already has invite, they cannot be added.
 921              if ( groups_check_user_has_invite( (int) $friend_ids[$i], $group_id ) ) {
 922                  continue;
 923              }
 924  
 925              // If user is not group admin and friend is banned, they cannot be invited.
 926              if ( ( false === $is_group_admin ) && groups_is_user_banned( (int) $friend_ids[$i], $group_id ) ) {
 927                  continue;
 928              }
 929  
 930              $invitable_count++;
 931          }
 932  
 933          return $invitable_count;
 934      }
 935  
 936      /**
 937       * Get friendship objects by ID (or an array of IDs).
 938       *
 939       * @since 2.7.0
 940       *
 941       * @param int|string|array $friendship_ids Single friendship ID or comma-separated/array list of friendship IDs.
 942       * @return array
 943       */
 944  	public static function get_friendships_by_id( $friendship_ids ) {
 945          global $wpdb;
 946  
 947          $bp = buddypress();
 948  
 949          $friendship_ids = implode( ',', wp_parse_id_list( $friendship_ids ) );
 950          return $wpdb->get_results( "SELECT * FROM {$bp->friends->table_name} WHERE id IN ({$friendship_ids})" );
 951      }
 952  
 953      /**
 954       * Get the friend user IDs for a given friendship.
 955       *
 956       * @since 1.0.0
 957       *
 958       * @param int $friendship_id ID of the friendship.
 959       * @return null|stdClass friend_user_id and initiator_user_id.
 960       */
 961  	public static function get_user_ids_for_friendship( $friendship_id ) {
 962  
 963          $friendship = new BP_Friends_Friendship( $friendship_id, false, false );
 964  
 965          if ( empty( $friendship->id ) ) {
 966              return null;
 967          }
 968  
 969          $retval = new StdClass;
 970          $retval->friend_user_id = $friendship->friend_user_id;
 971          $retval->initiator_user_id = $friendship->initiator_user_id;
 972  
 973          return $retval;
 974      }
 975  
 976      /**
 977       * Delete all friendships and friend notifications related to a user.
 978       *
 979       * @since 1.0.0
 980       *
 981       * @param int $user_id ID of the user being expunged.
 982       */
 983  	public static function delete_all_for_user( $user_id ) {
 984          global $wpdb;
 985  
 986          $bp = buddypress();
 987  
 988          // Get all friendships, of any status, for the user.
 989          $friendships    = self::get_friendships( $user_id );
 990          $friend_ids     = array();
 991          $friendship_ids = array();
 992          foreach ( $friendships as $friendship ) {
 993              $friendship_ids[] = $friendship->id;
 994              if ( $friendship->is_confirmed ) {
 995                  $friend_ids[] = ( $friendship->friend_user_id == $user_id ) ? $friendship->initiator_user_id : $friendship->friend_user_id;
 996              }
 997          }
 998  
 999          // Delete the friendships from the database.
1000          if ( $friendship_ids ) {
1001              $friendship_ids_sql = implode( ',', wp_parse_id_list( $friendship_ids ) );
1002              $wpdb->query( "DELETE FROM {$bp->friends->table_name} WHERE id IN ({$friendship_ids_sql})" );
1003          }
1004  
1005          // Delete friend request notifications for members who have a
1006          // notification from this user.
1007          if ( bp_is_active( 'notifications' ) ) {
1008              $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 ) );
1009          }
1010  
1011          // Clean up the friendships cache.
1012          foreach ( $friendship_ids as $friendship_id ) {
1013              wp_cache_delete( $friendship_id, 'bp_friends_friendships' );
1014          }
1015  
1016          // Loop through friend_ids to scrub user caches and update total count metas.
1017          foreach ( (array) $friend_ids as $friend_id ) {
1018              // Delete cached friendships.
1019              wp_cache_delete( $friend_id, 'bp_friends_friendships_for_user' );
1020              BP_Friends_Friendship::total_friend_count( $friend_id );
1021          }
1022  
1023          // Delete cached friendships.
1024          wp_cache_delete( $user_id, 'bp_friends_friendships_for_user' );
1025      }
1026  }


Generated: Sun Nov 17 01:01:36 2019 Cross-referenced by PHPXref 0.7.1