BP_Friends_Friendship

BuddyPress Friendship object.

Defined (1)

The class is defined in the following location(s).

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