[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Jan 19 01:01:32 2021 | Cross-referenced by PHPXref 0.7.1 |