/bp-messages/classes/class-bp-messages-thread.php

  1. <?php 
  2. /** 
  3. * BuddyPress Messages Classes. 
  4. * 
  5. * @package BuddyPress 
  6. * @subpackage MessagesClasses 
  7. * @since 1.0.0 
  8. */ 
  9.  
  10. // Exit if accessed directly. 
  11. defined( 'ABSPATH' ) || exit; 
  12.  
  13. /** 
  14. * BuddyPress Message Thread class. 
  15. * 
  16. * @since 1.0.0 
  17. */ 
  18. class BP_Messages_Thread { 
  19.  
  20. /** 
  21. * The message thread ID. 
  22. * 
  23. * @since 1.0.0 
  24. * @var int 
  25. */ 
  26. public $thread_id; 
  27.  
  28. /** 
  29. * The current messages. 
  30. * 
  31. * @since 1.0.0 
  32. * @var array 
  33. */ 
  34. public $messages; 
  35.  
  36. /** 
  37. * The current recipients in the message thread. 
  38. * 
  39. * @since 1.0.0 
  40. * @var array 
  41. */ 
  42. public $recipients; 
  43.  
  44. /** 
  45. * The user IDs of all messages in the message thread. 
  46. * 
  47. * @since 1.2.0 
  48. * @var array 
  49. */ 
  50. public $sender_ids; 
  51.  
  52. /** 
  53. * The unread count for the logged-in user. 
  54. * 
  55. * @since 1.2.0 
  56. * @var int 
  57. */ 
  58. public $unread_count; 
  59.  
  60. /** 
  61. * The content of the last message in this thread. 
  62. * 
  63. * @since 1.2.0 
  64. * @var string 
  65. */ 
  66. public $last_message_content; 
  67.  
  68. /** 
  69. * The date of the last message in this thread. 
  70. * 
  71. * @since 1.2.0 
  72. * @var string 
  73. */ 
  74. public $last_message_date; 
  75.  
  76. /** 
  77. * The ID of the last message in this thread. 
  78. * 
  79. * @since 1.2.0 
  80. * @var int 
  81. */ 
  82. public $last_message_id; 
  83.  
  84. /** 
  85. * The subject of the last message in this thread. 
  86. * 
  87. * @since 1.2.0 
  88. * @var string 
  89. */ 
  90. public $last_message_subject; 
  91.  
  92. /** 
  93. * The user ID of the author of the last message in this thread. 
  94. * 
  95. * @since 1.2.0 
  96. * @var int 
  97. */ 
  98. public $last_sender_id; 
  99.  
  100. /** 
  101. * Sort order of the messages in this thread (ASC or DESC). 
  102. * 
  103. * @since 1.5.0 
  104. * @var string 
  105. */ 
  106. public $messages_order; 
  107.  
  108. /** 
  109. * Constructor. 
  110. * 
  111. * @since 1.0.0 
  112. * 
  113. * @see BP_Messages_Thread::populate() for full description of parameters. 
  114. * 
  115. * @param bool $thread_id ID for the message thread. 
  116. * @param string $order Order to display the messages in. 
  117. * @param array $args Array of arguments for thread querying. 
  118. */ 
  119. public function __construct( $thread_id = false, $order = 'ASC', $args = array() ) { 
  120. if ( $thread_id ) { 
  121. $this->populate( $thread_id, $order, $args ); 
  122.  
  123. /** 
  124. * Populate method. 
  125. * 
  126. * Used in constructor. 
  127. * 
  128. * @since 1.0.0 
  129. * 
  130. * @param int $thread_id The message thread ID. 
  131. * @param string $order The order to sort the messages. Either 'ASC' or 'DESC'. 
  132. * @param array $args { 
  133. * Array of arguments. 
  134. * @type bool $update_meta_cache Whether to pre-fetch metadata for 
  135. * queried message items. Default: true. 
  136. * } 
  137. * @return bool False on failure. 
  138. */ 
  139. public function populate( $thread_id = 0, $order = 'ASC', $args = array() ) { 
  140.  
  141. if ( 'ASC' !== $order && 'DESC' !== $order ) { 
  142. $order = 'ASC'; 
  143.  
  144. // Merge $args with our defaults. 
  145. $r = wp_parse_args( $args, array( 
  146. 'user_id' => bp_loggedin_user_id(),  
  147. 'update_meta_cache' => true 
  148. ) ); 
  149.  
  150. $this->messages_order = $order; 
  151. $this->thread_id = (int) $thread_id; 
  152.  
  153. // Get messages for thread. 
  154. $this->messages = self::get_messages( $this->thread_id ); 
  155.  
  156. if ( empty( $this->messages ) || is_wp_error( $this->messages ) ) { 
  157. return false; 
  158.  
  159. // Flip if order is DESC. 
  160. if ( 'DESC' === $order ) { 
  161. $this->messages = array_reverse( $this->messages ); 
  162.  
  163. $last_message_index = count( $this->messages ) - 1; 
  164. $this->last_message_id = $this->messages[ $last_message_index ]->id; 
  165. $this->last_message_date = $this->messages[ $last_message_index ]->date_sent; 
  166. $this->last_sender_id = $this->messages[ $last_message_index ]->sender_id; 
  167. $this->last_message_subject = $this->messages[ $last_message_index ]->subject; 
  168. $this->last_message_content = $this->messages[ $last_message_index ]->message; 
  169.  
  170. foreach ( (array) $this->messages as $key => $message ) { 
  171. $this->sender_ids[ $message->sender_id ] = $message->sender_id; 
  172.  
  173. // Fetch the recipients. 
  174. $this->recipients = $this->get_recipients(); 
  175.  
  176. // Get the unread count for the logged in user. 
  177. if ( isset( $this->recipients[ $r['user_id'] ] ) ) { 
  178. $this->unread_count = $this->recipients[ $r['user_id'] ]->unread_count; 
  179.  
  180. // Grab all message meta. 
  181. if ( true === (bool) $r['update_meta_cache'] ) { 
  182. bp_messages_update_meta_cache( wp_list_pluck( $this->messages, 'id' ) ); 
  183.  
  184. /** 
  185. * Fires after a BP_Messages_Thread object has been populated. 
  186. * 
  187. * @since 2.2.0 
  188. * 
  189. * @param BP_Messages_Thread $this Message thread object. 
  190. */ 
  191. do_action( 'bp_messages_thread_post_populate', $this ); 
  192.  
  193. /** 
  194. * Mark a thread initialized in this class as read. 
  195. * 
  196. * @since 1.0.0 
  197. * 
  198. * @see BP_Messages_Thread::mark_as_read() 
  199. */ 
  200. public function mark_read() { 
  201. BP_Messages_Thread::mark_as_read( $this->thread_id ); 
  202.  
  203. /** 
  204. * Mark a thread initialized in this class as unread. 
  205. * 
  206. * @since 1.0.0 
  207. * 
  208. * @see BP_Messages_Thread::mark_as_unread() 
  209. */ 
  210. public function mark_unread() { 
  211. BP_Messages_Thread::mark_as_unread( $this->thread_id ); 
  212.  
  213. /** 
  214. * Returns recipients for a message thread. 
  215. * 
  216. * @since 1.0.0 
  217. * @since 2.3.0 Added $thread_id as a parameter. 
  218. * 
  219. * @param int $thread_id The thread ID. 
  220. * @return array 
  221. */ 
  222. public function get_recipients( $thread_id = 0 ) { 
  223. global $wpdb; 
  224.  
  225. if ( empty( $thread_id ) ) { 
  226. $thread_id = $this->thread_id; 
  227.  
  228. $thread_id = (int) $thread_id; 
  229.  
  230. $recipients = wp_cache_get( 'thread_recipients_' . $thread_id, 'bp_messages' ); 
  231. if ( false === $recipients ) { 
  232. $bp = buddypress(); 
  233.  
  234. $recipients = array(); 
  235. $sql = $wpdb->prepare( "SELECT * FROM {$bp->messages->table_name_recipients} WHERE thread_id = %d", $thread_id ); 
  236. $results = $wpdb->get_results( $sql ); 
  237.  
  238. foreach ( (array) $results as $recipient ) { 
  239. $recipients[ $recipient->user_id ] = $recipient; 
  240.  
  241. wp_cache_set( 'thread_recipients_' . $thread_id, $recipients, 'bp_messages' ); 
  242.  
  243. // Cast all items from the messages DB table as integers. 
  244. foreach ( (array) $recipients as $key => $data ) { 
  245. $recipients[ $key ] = (object) array_map( 'intval', (array) $data ); 
  246.  
  247. /** 
  248. * Filters the recipients of a message thread. 
  249. * 
  250. * @since 2.2.0 
  251. * 
  252. * @param array $recipients Array of recipient objects. 
  253. * @param int $thread_id ID of the current thread. 
  254. */ 
  255. return apply_filters( 'bp_messages_thread_get_recipients', $recipients, $thread_id ); 
  256.  
  257. /** Static Functions ******************************************************/ 
  258.  
  259. /** 
  260. * Get all messages associated with a thread. 
  261. * 
  262. * @since 2.3.0 
  263. * 
  264. * @param int $thread_id The message thread ID. 
  265. * 
  266. * @return object List of messages associated with a thread. 
  267. */ 
  268. public static function get_messages( $thread_id = 0 ) { 
  269. $thread_id = (int) $thread_id; 
  270. $messages = wp_cache_get( $thread_id, 'bp_messages_threads' ); 
  271.  
  272. if ( false === $messages ) { 
  273. global $wpdb; 
  274.  
  275. $bp = buddypress(); 
  276.  
  277. // Always sort by ASC by default. 
  278. $messages = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->messages->table_name_messages} WHERE thread_id = %d ORDER BY date_sent ASC", $thread_id ) ); 
  279.  
  280. wp_cache_set( $thread_id, (array) $messages, 'bp_messages_threads' ); 
  281.  
  282. // Integer casting. 
  283. foreach ( $messages as $key => $data ) { 
  284. $messages[ $key ]->id = (int) $messages[ $key ]->id; 
  285. $messages[ $key ]->thread_id = (int) $messages[ $key ]->thread_id; 
  286. $messages[ $key ]->sender_id = (int) $messages[ $key ]->sender_id; 
  287.  
  288. return $messages; 
  289.  
  290. /** 
  291. * Static method to get message recipients by thread ID. 
  292. * 
  293. * @since 2.3.0 
  294. * 
  295. * @param int $thread_id The thread ID. 
  296. * @return array 
  297. */ 
  298. public static function get_recipients_for_thread( $thread_id = 0 ) { 
  299. $thread = new self( false ); 
  300. return $thread->get_recipients( $thread_id ); 
  301.  
  302. /** 
  303. * Mark messages in a thread as deleted or delete all messages in a thread. 
  304. * 
  305. * Note: All messages in a thread are deleted once every recipient in a thread 
  306. * has marked the thread as deleted. 
  307. * 
  308. * @since 1.0.0 
  309. * @since 2.7.0 The $user_id parameter was added. Previously the current user 
  310. * was always assumed. 
  311. * 
  312. * @param int $thread_id The message thread ID. 
  313. * @param int $user_id The ID of the user in the thread to mark messages as 
  314. * deleted for. Defaults to the current logged-in user. 
  315. * 
  316. * @return bool 
  317. */ 
  318. public static function delete( $thread_id = 0, $user_id = 0 ) { 
  319. global $wpdb; 
  320.  
  321. $thread_id = (int) $thread_id; 
  322. $user_id = (int) $user_id; 
  323.  
  324. if ( empty( $user_id ) ) { 
  325. $user_id = bp_loggedin_user_id(); 
  326.  
  327. /** 
  328. * Fires before a message thread is marked as deleted. 
  329. * 
  330. * @since 2.2.0 
  331. * @since 2.7.0 The $user_id parameter was added. 
  332. * 
  333. * @param int $thread_id ID of the thread being deleted. 
  334. * @param int $user_id ID of the user that the thread is being deleted for. 
  335. */ 
  336. do_action( 'bp_messages_thread_before_mark_delete', $thread_id, $user_id ); 
  337.  
  338. $bp = buddypress(); 
  339.  
  340. // Mark messages as deleted 
  341. $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET is_deleted = 1 WHERE thread_id = %d AND user_id = %d", $thread_id, $user_id ) ); 
  342.  
  343. // Get the message ids in order to pass to the action. 
  344. $message_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id FROM {$bp->messages->table_name_messages} WHERE thread_id = %d", $thread_id ) ); 
  345.  
  346. // Check to see if any more recipients remain for this message. 
  347. $recipients = $wpdb->get_results( $wpdb->prepare( "SELECT id FROM {$bp->messages->table_name_recipients} WHERE thread_id = %d AND is_deleted = 0", $thread_id ) ); 
  348.  
  349. // No more recipients so delete all messages associated with the thread. 
  350. if ( empty( $recipients ) ) { 
  351.  
  352. /** 
  353. * Fires before an entire message thread is deleted. 
  354. * 
  355. * @since 2.2.0 
  356. * 
  357. * @param int $thread_id ID of the thread being deleted. 
  358. * @param array $message_ids IDs of messages being deleted. 
  359. */ 
  360. do_action( 'bp_messages_thread_before_delete', $thread_id, $message_ids ); 
  361.  
  362. // Delete all the messages. 
  363. $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->messages->table_name_messages} WHERE thread_id = %d", $thread_id ) ); 
  364.  
  365. // Do something for each message ID. 
  366. foreach ( $message_ids as $message_id ) { 
  367.  
  368. // Delete message meta. 
  369. bp_messages_delete_meta( $message_id ); 
  370.  
  371. /** 
  372. * Fires after a message is deleted. This hook is poorly named. 
  373. * 
  374. * @since 1.0.0 
  375. * 
  376. * @param int $message_id ID of the message. 
  377. */ 
  378. do_action( 'messages_thread_deleted_thread', $message_id ); 
  379.  
  380. // Delete all the recipients. 
  381. $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->messages->table_name_recipients} WHERE thread_id = %d", $thread_id ) ); 
  382.  
  383. /** 
  384. * Fires after a message thread is either marked as deleted or deleted. 
  385. * 
  386. * @since 2.2.0 
  387. * @since 2.7.0 The $user_id parameter was added. 
  388. * 
  389. * @param int $thread_id ID of the thread being deleted. 
  390. * @param array $message_ids IDs of messages being deleted. 
  391. * @param int $user_id ID of the user the threads were deleted for. 
  392. */ 
  393. do_action( 'bp_messages_thread_after_delete', $thread_id, $message_ids, $user_id ); 
  394.  
  395. return true; 
  396.  
  397. /** 
  398. * Get current message threads for a user. 
  399. * 
  400. * @since 1.0.0 
  401. * 
  402. * @param array $args { 
  403. * Array of arguments. 
  404. * @type int $user_id The user ID. 
  405. * @type string $box The type of mailbox to get. Either 'inbox' or 'sentbox'. 
  406. * Defaults to 'inbox'. 
  407. * @type string $type The type of messages to get. Either 'all' or 'unread' 
  408. * or 'read'. Defaults to 'all'. 
  409. * @type int $limit The number of messages to get. Defaults to null. 
  410. * @type int $page The page number to get. Defaults to null. 
  411. * @type string $search_terms The search term to use. Defaults to ''. 
  412. * @type array $meta_query Meta query arguments. See WP_Meta_Query for more details. 
  413. * } 
  414. * @return array|bool Array on success. Boolean false on failure. 
  415. */ 
  416. public static function get_current_threads_for_user( $args = array() ) { 
  417. global $wpdb; 
  418.  
  419. // Backward compatibility with old method of passing arguments. 
  420. if ( ! is_array( $args ) || func_num_args() > 1 ) { 
  421. _deprecated_argument( __METHOD__, '2.2.0', sprintf( __( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) ); 
  422.  
  423. $old_args_keys = array( 
  424. 0 => 'user_id',  
  425. 1 => 'box',  
  426. 2 => 'type',  
  427. 3 => 'limit',  
  428. 4 => 'page',  
  429. 5 => 'search_terms',  
  430. ); 
  431.  
  432. $args = bp_core_parse_args_array( $old_args_keys, func_get_args() ); 
  433.  
  434. $r = bp_parse_args( $args, array( 
  435. 'user_id' => false,  
  436. 'box' => 'inbox',  
  437. 'type' => 'all',  
  438. 'limit' => null,  
  439. 'page' => null,  
  440. 'search_terms' => '',  
  441. 'meta_query' => array() 
  442. ) ); 
  443.  
  444. $pag_sql = $type_sql = $search_sql = $user_id_sql = $sender_sql = ''; 
  445. $meta_query_sql = array( 
  446. 'join' => '',  
  447. 'where' => '' 
  448. ); 
  449.  
  450. if ( $r['limit'] && $r['page'] ) { 
  451. $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $r['page'] - 1 ) * $r['limit'] ), intval( $r['limit'] ) ); 
  452.  
  453. if ( $r['type'] == 'unread' ) { 
  454. $type_sql = " AND r.unread_count != 0 "; 
  455. } elseif ( $r['type'] == 'read' ) { 
  456. $type_sql = " AND r.unread_count = 0 "; 
  457.  
  458. if ( ! empty( $r['search_terms'] ) ) { 
  459. $search_terms_like = '%' . bp_esc_like( $r['search_terms'] ) . '%'; 
  460. $search_sql = $wpdb->prepare( "AND ( subject LIKE %s OR message LIKE %s )", $search_terms_like, $search_terms_like ); 
  461.  
  462. $r['user_id'] = (int) $r['user_id']; 
  463.  
  464. // Default deleted SQL. 
  465. $deleted_sql = 'r.is_deleted = 0'; 
  466.  
  467. switch ( $r['box'] ) { 
  468. case 'sentbox' : 
  469. $user_id_sql = 'AND ' . $wpdb->prepare( 'm.sender_id = %d', $r['user_id'] ); 
  470. $sender_sql = 'AND m.sender_id = r.user_id'; 
  471. break; 
  472.  
  473. case 'inbox' : 
  474. $user_id_sql = 'AND ' . $wpdb->prepare( 'r.user_id = %d', $r['user_id'] ); 
  475. $sender_sql = 'AND r.sender_only = 0'; 
  476. break; 
  477.  
  478. default : 
  479. // Omit user-deleted threads from all other custom message boxes. 
  480. $deleted_sql = $wpdb->prepare( '( r.user_id = %d AND r.is_deleted = 0 )', $r['user_id'] ); 
  481. break; 
  482.  
  483. // Process meta query into SQL. 
  484. $meta_query = self::get_meta_query_sql( $r['meta_query'] ); 
  485. if ( ! empty( $meta_query['join'] ) ) { 
  486. $meta_query_sql['join'] = $meta_query['join']; 
  487. if ( ! empty( $meta_query['where'] ) ) { 
  488. $meta_query_sql['where'] = $meta_query['where']; 
  489.  
  490. $bp = buddypress(); 
  491.  
  492. // Set up SQL array. 
  493. $sql = array(); 
  494. $sql['select'] = 'SELECT m.thread_id, MAX(m.date_sent) AS date_sent'; 
  495. $sql['from'] = "FROM {$bp->messages->table_name_recipients} r INNER JOIN {$bp->messages->table_name_messages} m ON m.thread_id = r.thread_id {$meta_query_sql['join']}"; 
  496. $sql['where'] = "WHERE {$deleted_sql} {$user_id_sql} {$sender_sql} {$type_sql} {$search_sql} {$meta_query_sql['where']}"; 
  497. $sql['misc'] = "GROUP BY m.thread_id ORDER BY date_sent DESC {$pag_sql}"; 
  498.  
  499. // Get thread IDs. 
  500. $thread_ids = $wpdb->get_results( implode( ' ', $sql ) ); 
  501. if ( empty( $thread_ids ) ) { 
  502. return false; 
  503.  
  504. // Adjust $sql to work for thread total. 
  505. $sql['select'] = 'SELECT COUNT( DISTINCT m.thread_id )'; 
  506. unset( $sql['misc'] ); 
  507. $total_threads = $wpdb->get_var( implode( ' ', $sql ) ); 
  508.  
  509. // Sort threads by date_sent. 
  510. foreach( (array) $thread_ids as $thread ) { 
  511. $sorted_threads[ $thread->thread_id ] = strtotime( $thread->date_sent ); 
  512.  
  513. arsort( $sorted_threads ); 
  514.  
  515. $threads = array(); 
  516. foreach ( (array) $sorted_threads as $thread_id => $date_sent ) { 
  517. $threads[] = new BP_Messages_Thread( $thread_id, 'ASC', array( 
  518. 'update_meta_cache' => false 
  519. ) ); 
  520.  
  521. /** 
  522. * Filters the results of the query for a user's message threads. 
  523. * 
  524. * @since 2.2.0 
  525. * 
  526. * @param array $value { 
  527. * @type array $threads Array of threads. Passed by reference. 
  528. * @type int $total_threads Number of threads found by the query. 
  529. * } 
  530. */ 
  531. return apply_filters( 'bp_messages_thread_current_threads', array( 
  532. 'threads' => &$threads,  
  533. 'total' => (int) $total_threads 
  534. ) ); 
  535.  
  536. /** 
  537. * Get the SQL for the 'meta_query' param in BP_Messages_Thread::get_current_threads_for_user(). 
  538. * 
  539. * We use WP_Meta_Query to do the heavy lifting of parsing the meta_query array 
  540. * and creating the necessary SQL clauses. 
  541. * 
  542. * @since 2.2.0 
  543. * 
  544. * @param array $meta_query An array of meta_query filters. See the 
  545. * documentation for WP_Meta_Query for details. 
  546. * @return array $sql_array 'join' and 'where' clauses. 
  547. */ 
  548. public static function get_meta_query_sql( $meta_query = array() ) { 
  549. global $wpdb; 
  550.  
  551. $sql_array = array( 
  552. 'join' => '',  
  553. 'where' => '',  
  554. ); 
  555.  
  556. if ( ! empty( $meta_query ) ) { 
  557. $meta_query = new WP_Meta_Query( $meta_query ); 
  558.  
  559. // WP_Meta_Query expects the table name at 
  560. // $wpdb->messagemeta. 
  561. $wpdb->messagemeta = buddypress()->messages->table_name_meta; 
  562.  
  563. return $meta_query->get_sql( 'message', 'm', 'id' ); 
  564.  
  565. return $sql_array; 
  566.  
  567. /** 
  568. * Mark a thread as read. 
  569. * 
  570. * @since 1.0.0 
  571. * 
  572. * @param int $thread_id The message thread ID. 
  573. * 
  574. * @return false|int Number of threads marked as read or false on error. 
  575. */ 
  576. public static function mark_as_read( $thread_id = 0 ) { 
  577. global $wpdb; 
  578.  
  579. $bp = buddypress(); 
  580. $retval = $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET unread_count = 0 WHERE user_id = %d AND thread_id = %d", bp_loggedin_user_id(), $thread_id ) ); 
  581.  
  582. wp_cache_delete( 'thread_recipients_' . $thread_id, 'bp_messages' ); 
  583. wp_cache_delete( bp_loggedin_user_id(), 'bp_messages_unread_count' ); 
  584.  
  585. /** 
  586. * Fires when messages thread was marked as read. 
  587. * 
  588. * @since 2.8.0 
  589. * 
  590. * @param int $thread_id The message thread ID. 
  591. */ 
  592. do_action( 'messages_thread_mark_as_read', $thread_id ); 
  593.  
  594. return $retval; 
  595.  
  596. /** 
  597. * Mark a thread as unread. 
  598. * 
  599. * @since 1.0.0 
  600. * 
  601. * @param int $thread_id The message thread ID. 
  602. * 
  603. * @return false|int Number of threads marked as unread or false on error. 
  604. */ 
  605. public static function mark_as_unread( $thread_id = 0 ) { 
  606. global $wpdb; 
  607.  
  608. $bp = buddypress(); 
  609. $retval = $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET unread_count = 1 WHERE user_id = %d AND thread_id = %d", bp_loggedin_user_id(), $thread_id ) ); 
  610.  
  611. wp_cache_delete( 'thread_recipients_' . $thread_id, 'bp_messages' ); 
  612. wp_cache_delete( bp_loggedin_user_id(), 'bp_messages_unread_count' ); 
  613.  
  614. /** 
  615. * Fires when messages thread was marked as unread. 
  616. * 
  617. * @since 2.8.0 
  618. * 
  619. * @param int $thread_id The message thread ID. 
  620. */ 
  621. do_action( 'messages_thread_mark_as_unread', $thread_id ); 
  622.  
  623. return $retval; 
  624.  
  625. /** 
  626. * Returns the total number of message threads for a user. 
  627. * 
  628. * @since 1.0.0 
  629. * 
  630. * @param int $user_id The user ID. 
  631. * @param string $box The type of mailbox to get. Either 'inbox' or 'sentbox'. 
  632. * Defaults to 'inbox'. 
  633. * @param string $type The type of messages to get. Either 'all' or 'unread'. 
  634. * or 'read'. Defaults to 'all'. 
  635. * @return int $value Total thread count for the provided user. 
  636. */ 
  637. public static function get_total_threads_for_user( $user_id, $box = 'inbox', $type = 'all' ) { 
  638. global $wpdb; 
  639.  
  640. $exclude_sender = $type_sql = ''; 
  641. if ( $box !== 'sentbox' ) { 
  642. $exclude_sender = 'AND sender_only != 1'; 
  643.  
  644. if ( $type === 'unread' ) { 
  645. $type_sql = 'AND unread_count != 0'; 
  646. } elseif ( $type === 'read' ) { 
  647. $type_sql = 'AND unread_count = 0'; 
  648.  
  649. $bp = buddypress(); 
  650.  
  651. return (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(thread_id) FROM {$bp->messages->table_name_recipients} WHERE user_id = %d AND is_deleted = 0 {$exclude_sender} {$type_sql}", $user_id ) ); 
  652.  
  653. /** 
  654. * Determine if the logged-in user is a sender of any message in a thread. 
  655. * 
  656. * @since 1.0.0 
  657. * 
  658. * @param int $thread_id The message thread ID. 
  659. * @return bool 
  660. */ 
  661. public static function user_is_sender( $thread_id ) { 
  662. global $wpdb; 
  663.  
  664. $bp = buddypress(); 
  665.  
  666. $sender_ids = $wpdb->get_col( $wpdb->prepare( "SELECT sender_id FROM {$bp->messages->table_name_messages} WHERE thread_id = %d", $thread_id ) ); 
  667.  
  668. if ( empty( $sender_ids ) ) { 
  669. return false; 
  670.  
  671. return in_array( bp_loggedin_user_id(), $sender_ids ); 
  672.  
  673. /** 
  674. * Returns the userlink of the last sender in a message thread. 
  675. * 
  676. * @since 1.0.0 
  677. * 
  678. * @param int $thread_id The message thread ID. 
  679. * @return string|bool The user link on success. Boolean false on failure. 
  680. */ 
  681. public static function get_last_sender( $thread_id ) { 
  682. global $wpdb; 
  683.  
  684. $bp = buddypress(); 
  685.  
  686. if ( ! $sender_id = $wpdb->get_var( $wpdb->prepare( "SELECT sender_id FROM {$bp->messages->table_name_messages} WHERE thread_id = %d GROUP BY sender_id ORDER BY date_sent LIMIT 1", $thread_id ) ) ) { 
  687. return false; 
  688.  
  689. return bp_core_get_userlink( $sender_id, true ); 
  690.  
  691. /** 
  692. * Gets the unread message count for a user. 
  693. * 
  694. * @since 1.0.0 
  695. * 
  696. * @param int $user_id The user ID. 
  697. * @return int $unread_count Total inbox unread count for user. 
  698. */ 
  699. public static function get_inbox_count( $user_id = 0 ) { 
  700. global $wpdb; 
  701.  
  702. if ( empty( $user_id ) ) { 
  703. $user_id = bp_loggedin_user_id(); 
  704.  
  705. $unread_count = wp_cache_get( $user_id, 'bp_messages_unread_count' ); 
  706.  
  707. if ( false === $unread_count ) { 
  708. $bp = buddypress(); 
  709.  
  710. $unread_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT SUM(unread_count) FROM {$bp->messages->table_name_recipients} WHERE user_id = %d AND is_deleted = 0 AND sender_only = 0", $user_id ) ); 
  711.  
  712. wp_cache_set( $user_id, $unread_count, 'bp_messages_unread_count' ); 
  713.  
  714. /** 
  715. * Filters a user's unread message count. 
  716. * 
  717. * @since 2.2.0 
  718. * 
  719. * @param int $unread_count Unread message count. 
  720. * @param int $user_id ID of the user. 
  721. */ 
  722. return apply_filters( 'messages_thread_get_inbox_count', (int) $unread_count, $user_id ); 
  723.  
  724. /** 
  725. * Checks whether a user is a part of a message thread discussion. 
  726. * 
  727. * @since 1.0.0 
  728. * 
  729. * @param int $thread_id The message thread ID. 
  730. * @param int $user_id The user ID. 
  731. * @return int|null The recorded recipient ID on success, null on failure. 
  732. */ 
  733. public static function check_access( $thread_id, $user_id = 0 ) { 
  734.  
  735. if ( empty( $user_id ) ) { 
  736. $user_id = bp_loggedin_user_id(); 
  737.  
  738. $recipients = self::get_recipients_for_thread( $thread_id ); 
  739.  
  740. if ( isset( $recipients[ $user_id ] ) && 0 == $recipients[ $user_id ]->is_deleted ) { 
  741. return $recipients[ $user_id ]->id; 
  742. } else { 
  743. return null; 
  744.  
  745. /** 
  746. * Checks whether a message thread exists. 
  747. * 
  748. * @since 1.0.0 
  749. * 
  750. * @param int $thread_id The message thread ID. 
  751. * @return int|null The message thread ID on success, null on failure. 
  752. */ 
  753. public static function is_valid( $thread_id = 0 ) { 
  754.  
  755. // Bail if no thread ID is passed. 
  756. if ( empty( $thread_id ) ) { 
  757. return false; 
  758.  
  759. $thread = self::get_messages( $thread_id ); 
  760.  
  761. if ( ! empty( $thread ) ) { 
  762. return $thread_id; 
  763. } else { 
  764. return null; 
  765.  
  766. /** 
  767. * Returns a string containing all the message recipient userlinks. 
  768. * 
  769. * String is comma-delimited. 
  770. * 
  771. * If a message thread has more than four users, the returned string is simply 
  772. * "X Recipients" where "X" is the number of recipients in the message thread. 
  773. * 
  774. * @since 1.0.0 
  775. * 
  776. * @param array $recipients Array containing the message recipients (array of objects). 
  777. * @return string $value String of message recipent userlinks. 
  778. */ 
  779. public static function get_recipient_links( $recipients ) { 
  780.  
  781. if ( count( $recipients ) >= 5 ) { 
  782. return sprintf( __( '%s Recipients', 'buddypress' ), number_format_i18n( count( $recipients ) ) ); 
  783.  
  784. $recipient_links = array(); 
  785.  
  786. foreach ( (array) $recipients as $recipient ) { 
  787. $recipient_link = bp_core_get_userlink( $recipient->user_id ); 
  788.  
  789. if ( empty( $recipient_link ) ) { 
  790. $recipient_link = __( 'Deleted User', 'buddypress' ); 
  791.  
  792. $recipient_links[] = $recipient_link; 
  793.  
  794. return implode( ', ', (array) $recipient_links ); 
  795.  
  796. /** 
  797. * Upgrade method for the older BP message thread DB table. 
  798. * 
  799. * @since 1.2.0 
  800. * 
  801. * @todo We should remove this. No one is going to upgrade from v1.1, right? 
  802. * @return bool 
  803. */ 
  804. public static function update_tables() { 
  805. global $wpdb; 
  806.  
  807. $bp_prefix = bp_core_get_table_prefix(); 
  808. $errors = false; 
  809. $threads = $wpdb->get_results( "SELECT * FROM {$bp_prefix}bp_messages_threads" ); 
  810.  
  811. // Nothing to update, just return true to remove the table. 
  812. if ( empty( $threads ) ) { 
  813. return true; 
  814.  
  815. $bp = buddypress(); 
  816.  
  817. foreach( (array) $threads as $thread ) { 
  818. $message_ids = maybe_unserialize( $thread->message_ids ); 
  819.  
  820. if ( ! empty( $message_ids ) ) { 
  821. $message_ids = implode( ', ', $message_ids ); 
  822.  
  823. // Add the thread_id to the messages table. 
  824. if ( ! $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_messages} SET thread_id = %d WHERE id IN ({$message_ids})", $thread->id ) ) ) { 
  825. $errors = true; 
  826.  
  827. return (bool) ! $errors; 
.