[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-messages/classes/ -> class-bp-messages-thread.php (source)

   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       * @since 10.0.0 Updated the `$args` with new paremeters.
 113       *
 114       * @param int    $thread_id          The message thread ID.
 115       * @param string $order              The order to sort the messages. Either 'ASC' or 'DESC'.
 116       *                                   Defaults to 'ASC'.
 117       * @param array  $args               {
 118       *     Array of arguments.
 119       *     @type int         $user_id             ID of the user to get the unread count.
 120       *     @type bool        $update_meta_cache   Whether to pre-fetch metadata for
 121       *                                            queried message items. Default: true.
 122       *     @type int|null    $page                Page of messages being requested. Default to null, meaning all.
 123       *     @type int|null    $per_page            Messages to return per page. Default to null, meaning all.
 124       *     @type string      $order               Optional. The order to sort the messages. Either 'ASC' or 'DESC'.
 125       *                                            Defaults to 'ASC'.
 126       *     @type int|null    $recipients_page     Page of recipients being requested. Default to null, meaning all.
 127       *     @type int|null    $recipients_per_page Recipients to return per page. Defaults to null, meaning all.
 128       * }
 129       */
 130  	public function __construct( $thread_id = 0, $order = 'ASC', $args = array() ) {
 131          if ( ! empty( $thread_id ) ) {
 132              $this->populate( $thread_id, $order, $args );
 133          }
 134      }
 135  
 136      /**
 137       * Populate method.
 138       *
 139       * Used in the constructor.
 140       *
 141       * @since 1.0.0
 142       * @since 10.0.0 Updated the `$args` with new paremeters.
 143       *
 144       * @param int    $thread_id                   The message thread ID.
 145       * @param string $order                       The order to sort the messages. Either 'ASC' or 'DESC'.
 146       *                                            Defaults to 'ASC'.
 147       * @param array  $args                        {
 148       *     Array of arguments.
 149       *     @type int         $user_id             ID of the user to get the unread count.
 150       *     @type bool        $update_meta_cache   Whether to pre-fetch metadata for
 151       *                                            queried message items. Default: true.
 152       *     @type int|null    $page                Page of messages being requested. Default to null, meaning all.
 153       *     @type int|null    $per_page            Messages to return per page. Default to null, meaning all.
 154       *     @type string      $order               The order to sort the messages. Either 'ASC' or 'DESC'.
 155       *                                            Defaults to 'ASC'.
 156       *     @type int|null    $recipients_page     Page of recipients being requested. Default to null, meaning all.
 157       *     @type int|null    $recipients_per_page Recipients to return per page. Defaults to null, meaning all.
 158       * }
 159       * @return bool False if there are no messages.
 160       */
 161  	public function populate( $thread_id = 0, $order = 'ASC', $args = array() ) {
 162  
 163          $user_id =
 164              bp_displayed_user_id() ?
 165              bp_displayed_user_id() :
 166              bp_loggedin_user_id();
 167  
 168          // Merge $args with our defaults.
 169          $r = bp_parse_args(
 170              $args,
 171              array(
 172                  'user_id'             => $user_id,
 173                  'update_meta_cache'   => true,
 174                  'page'                => null,
 175                  'per_page'            => null,
 176                  'order'               => bp_esc_sql_order( $order ),
 177                  'recipients_page'     => null,
 178                  'recipients_per_page' => null,
 179              )
 180          );
 181  
 182          $this->messages_order = $r['order'];
 183          $this->thread_id      = (int) $thread_id;
 184  
 185          // Get messages for thread.
 186          $this->messages = self::get_messages( $this->thread_id, $r );
 187  
 188          if ( empty( $this->messages ) ) {
 189              return false;
 190          }
 191  
 192          $last_message_index         = count( $this->messages ) - 1;
 193          $this->last_message_id      = $this->messages[ $last_message_index ]->id;
 194          $this->last_message_date    = $this->messages[ $last_message_index ]->date_sent;
 195          $this->last_sender_id       = $this->messages[ $last_message_index ]->sender_id;
 196          $this->last_message_subject = $this->messages[ $last_message_index ]->subject;
 197          $this->last_message_content = $this->messages[ $last_message_index ]->message;
 198  
 199          foreach ( (array) $this->messages as $key => $message ) {
 200              $this->sender_ids[ $message->sender_id ] = $message->sender_id;
 201          }
 202  
 203          // Fetch the recipients.
 204          $this->recipients = $this->get_recipients( $thread_id, $r );
 205  
 206          // Get the unread count for the user.
 207          if ( isset( $this->recipients[ $r['user_id'] ] ) ) {
 208              $this->unread_count = $this->recipients[ $r['user_id'] ]->unread_count;
 209          }
 210  
 211          // Grab all message meta.
 212          if ( true === (bool) $r['update_meta_cache'] ) {
 213              bp_messages_update_meta_cache( wp_list_pluck( $this->messages, 'id' ) );
 214          }
 215  
 216          /**
 217           * Fires after a BP_Messages_Thread object has been populated.
 218           *
 219           * @since 2.2.0
 220           * @since 10.0.0 Added `$r` as a parameter.
 221           *
 222           * @param BP_Messages_Thread $this Message thread object.
 223           * @param array              $r    Array of paremeters.
 224           */
 225          do_action( 'bp_messages_thread_post_populate', $this, $r );
 226      }
 227  
 228      /**
 229       * Mark a thread initialized in this class as read.
 230       *
 231       * @since 1.0.0
 232       *
 233       * @see BP_Messages_Thread::mark_as_read()
 234       */
 235  	public function mark_read() {
 236          self::mark_as_read( $this->thread_id );
 237      }
 238  
 239      /**
 240       * Mark a thread initialized in this class as unread.
 241       *
 242       * @since 1.0.0
 243       *
 244       * @see BP_Messages_Thread::mark_as_unread()
 245       */
 246  	public function mark_unread() {
 247          self::mark_as_unread( $this->thread_id );
 248      }
 249  
 250      /**
 251       * Returns recipients for a message thread.
 252       *
 253       * @since 1.0.0
 254       * @since 2.3.0  Added `$thread_id` as a parameter.
 255       * @since 10.0.0 Added `$args` as a parameter.
 256       *
 257       * @global BuddyPress $bp The one true BuddyPress instance.
 258       * @global wpdb $wpdb WordPress database object.
 259       *
 260       * @param int   $thread_id Message thread ID.
 261       * @param array $args      {
 262       *     Array of arguments.
 263       *     @type int|null $recipients_page     Page of recipients being requested. Default to all.
 264       *     @type int|null $recipients_per_page Recipients to return per page. Defaults to all.
 265       * }
 266       * @return array
 267       */
 268  	public function get_recipients( $thread_id = 0, $args = array() ) {
 269          global $wpdb;
 270  
 271          if ( empty( $thread_id ) ) {
 272              $thread_id = $this->thread_id;
 273          }
 274  
 275          $thread_id = (int) $thread_id;
 276  
 277          if ( empty( $thread_id ) ) {
 278              return array();
 279          }
 280  
 281          $bp = buddypress();
 282          $r  = bp_parse_args(
 283              $args,
 284              array(
 285                  'recipients_page'     => null,
 286                  'recipients_per_page' => null,
 287              )
 288          );
 289  
 290          // Get recipients from cache if available.
 291          $recipients = wp_cache_get( 'thread_recipients_' . $thread_id, 'bp_messages' );
 292  
 293          // Get recipients and cache it.
 294          if ( empty( $recipients ) ) {
 295  
 296              // Query recipients.
 297              $results = $wpdb->get_results(
 298                  $wpdb->prepare(
 299                      "SELECT * FROM {$bp->messages->table_name_recipients} WHERE thread_id = %d",
 300                      $thread_id
 301                  )
 302              );
 303  
 304              $recipients = array();
 305              foreach ( (array) $results as $recipient ) {
 306                  $recipient_properties              = get_object_vars( $recipient );
 307                  $recipients[ $recipient->user_id ] = (object) array_map( 'intval', $recipient_properties );
 308              }
 309  
 310              // Cache recipients.
 311              wp_cache_set( 'thread_recipients_' . $thread_id, (array) $recipients, 'bp_messages' );
 312          }
 313  
 314          // Paginate the results.
 315          if ( ! empty( $recipients ) && $r['recipients_per_page'] && $r['recipients_page'] ) {
 316              $start      = ( $r['recipients_page'] - 1 ) * ( $r['recipients_per_page'] );
 317              $recipients = array_slice( $recipients, $start, $r['recipients_per_page'] );
 318          }
 319  
 320          /**
 321           * Filters the recipients of a message thread.
 322           *
 323           * @since 2.2.0
 324           * @since 10.0.0 Added `$r` as a parameter.
 325           *
 326           * @param array $recipients Array of recipient objects.
 327           * @param int   $thread_id  ID of the thread.
 328           * @param array $r          An array of parameters.
 329           */
 330          return apply_filters( 'bp_messages_thread_get_recipients', (array) $recipients, (int) $thread_id, (array) $r );
 331      }
 332  
 333      /** Static Functions ******************************************************/
 334  
 335      /**
 336       * Get messages associated with a thread.
 337       *
 338       * @since 2.3.0
 339       * @since 10.0.0 Added `$args` as a parameter.
 340       *
 341       * @global BuddyPress $bp The one true BuddyPress instance.
 342       * @global wpdb $wpdb WordPress database object.
 343       *
 344       * @param int   $thread_id The message thread ID.
 345       * @param array $args      {
 346       *     Array of arguments.
 347       *     @type int|null    $page     Page of messages being requested. Default to all.
 348       *     @type int|null    $per_page Messages to return per page. Default to all.
 349       *     @type string      $order    The order to sort the messages. Either 'ASC' or 'DESC'.
 350       *                                 Defaults to 'ASC'.
 351       * }
 352       * @return array
 353       */
 354  	public static function get_messages( $thread_id = 0, $args = array() ) {
 355          global $wpdb;
 356  
 357          $thread_id = (int) $thread_id;
 358          if ( empty( $thread_id ) ) {
 359              return array();
 360          }
 361  
 362          $bp = buddypress();
 363          $r  = bp_parse_args(
 364              $args,
 365              array(
 366                  'page'     => null,
 367                  'per_page' => null,
 368                  'order'    => 'ASC',
 369              )
 370          );
 371  
 372          // Sanitize 'order'.
 373          $r['order'] = bp_esc_sql_order( $r['order'] );
 374  
 375          // Get messages from cache if available.
 376          $messages = wp_cache_get( $thread_id, 'bp_messages_threads' );
 377  
 378          // Get messages and cache it.
 379          if ( empty( $messages ) ) {
 380  
 381              // Query messages.
 382              $messages = $wpdb->get_results(
 383                  $wpdb->prepare(
 384                      "SELECT * FROM {$bp->messages->table_name_messages} WHERE thread_id = %d ORDER BY date_sent ASC",
 385                      $thread_id
 386                  )
 387              );
 388  
 389              foreach ( $messages as $key => $data ) {
 390                  $messages[ $key ]->id        = (int) $messages[ $key ]->id;
 391                  $messages[ $key ]->thread_id = (int) $messages[ $key ]->thread_id;
 392                  $messages[ $key ]->sender_id = (int) $messages[ $key ]->sender_id;
 393              }
 394  
 395              // Cache messages.
 396              wp_cache_set( $thread_id, (array) $messages, 'bp_messages_threads' );
 397          }
 398  
 399          // Flip if order is DESC.
 400          if ( 'DESC' === $r['order'] ) {
 401              $messages = array_reverse( $messages );
 402          }
 403  
 404          // Paginate the results.
 405          if ( ! empty( $messages ) && $r['per_page'] && $r['page'] ) {
 406              $start    = ( $r['page'] - 1 ) * ( $r['per_page'] );
 407              $messages = array_slice( $messages, $start, $r['per_page'] );
 408          }
 409  
 410          /**
 411           * Filters the messages associated with a thread.
 412           *
 413           * @since 10.0.0
 414           *
 415           * @param array $messages   Array of message objects.
 416           * @param int   $thread_id  ID of the thread.
 417           * @param array $r          An array of parameters.
 418           */
 419          return apply_filters( 'bp_messages_thread_get_messages', (array) $messages, (int) $thread_id, (array) $r );
 420      }
 421  
 422      /**
 423       * Static method to get message recipients by thread ID.
 424       *
 425       * @since 2.3.0
 426       *
 427       * @param int $thread_id The thread ID.
 428       * @return array
 429       */
 430  	public static function get_recipients_for_thread( $thread_id = 0 ) {
 431          $thread = new self( false );
 432          return $thread->get_recipients( $thread_id );
 433      }
 434  
 435      /**
 436       * Mark messages in a thread as deleted or delete all messages in a thread.
 437       *
 438       * Note: All messages in a thread are deleted once every recipient in a thread
 439       * has marked the thread as deleted.
 440       *
 441       * @since 1.0.0
 442       * @since 2.7.0 The $user_id parameter was added. Previously the current user
 443       *              was always assumed.
 444       *
 445       * @global BuddyPress $bp The one true BuddyPress instance.
 446       * @global wpdb $wpdb WordPress database object.
 447       *
 448       * @param int $thread_id The message thread ID.
 449       * @param int $user_id The ID of the user in the thread to mark messages as
 450       *                     deleted for. Defaults to the current logged-in user.
 451       *
 452       * @return bool
 453       */
 454  	public static function delete( $thread_id = 0, $user_id = 0 ) {
 455          global $wpdb;
 456  
 457          $thread_id = (int) $thread_id;
 458          $user_id = (int) $user_id;
 459  
 460          if ( empty( $user_id ) ) {
 461              $user_id = bp_loggedin_user_id();
 462          }
 463  
 464          /**
 465           * Fires before a message thread is marked as deleted.
 466           *
 467           * @since 2.2.0
 468           * @since 2.7.0 The $user_id parameter was added.
 469           *
 470           * @param int $thread_id ID of the thread being deleted.
 471           * @param int $user_id   ID of the user that the thread is being deleted for.
 472           */
 473          do_action( 'bp_messages_thread_before_mark_delete', $thread_id, $user_id );
 474  
 475          $bp = buddypress();
 476  
 477          // Mark messages as deleted
 478          $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 ) );
 479  
 480          // Get the message ids in order to pass to the action.
 481          $message_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id FROM {$bp->messages->table_name_messages} WHERE thread_id = %d", $thread_id ) );
 482  
 483          // Check to see if any more recipients remain for this message.
 484          $recipients = $wpdb->get_results( $wpdb->prepare( "SELECT id FROM {$bp->messages->table_name_recipients} WHERE thread_id = %d AND is_deleted = 0", $thread_id ) );
 485  
 486          // No more recipients so delete all messages associated with the thread.
 487          if ( empty( $recipients ) ) {
 488  
 489              /**
 490               * Fires before an entire message thread is deleted.
 491               *
 492               * @since 2.2.0
 493               *
 494               * @param int   $thread_id   ID of the thread being deleted.
 495               * @param array $message_ids IDs of messages being deleted.
 496               */
 497              do_action( 'bp_messages_thread_before_delete', $thread_id, $message_ids );
 498  
 499              // Delete all the messages.
 500              $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->messages->table_name_messages} WHERE thread_id = %d", $thread_id ) );
 501  
 502              // Do something for each message ID.
 503              foreach ( $message_ids as $message_id ) {
 504  
 505                  // Delete message meta.
 506                  bp_messages_delete_meta( $message_id );
 507  
 508                  /**
 509                   * Fires after a message is deleted. This hook is poorly named.
 510                   *
 511                   * @since 1.0.0
 512                   *
 513                   * @param int $message_id ID of the message.
 514                   */
 515                  do_action( 'messages_thread_deleted_thread', $message_id );
 516              }
 517  
 518              // Delete all the recipients.
 519              $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->messages->table_name_recipients} WHERE thread_id = %d", $thread_id ) );
 520          }
 521  
 522          /**
 523           * Fires after a message thread is either marked as deleted or deleted.
 524           *
 525           * @since 2.2.0
 526           * @since 2.7.0 The $user_id parameter was added.
 527           *
 528           * @param int   $thread_id   ID of the thread being deleted.
 529           * @param array $message_ids IDs of messages being deleted.
 530           * @param int   $user_id     ID of the user the threads were deleted for.
 531           */
 532          do_action( 'bp_messages_thread_after_delete', $thread_id, $message_ids, $user_id );
 533  
 534          return true;
 535      }
 536  
 537      /**
 538       * Exit a user from a thread.
 539       *
 540       * @since 10.0.0
 541       *
 542       * @global wpdb $wpdb WordPress database object.
 543       *
 544       * @param int $thread_id The message thread ID.
 545       * @param int $user_id The ID of the user in the thread.
 546       *                     Defaults to the current logged-in user.
 547       *
 548       * @return bool
 549       */
 550  	public static function exit_thread( $thread_id = 0, $user_id = 0 ) {
 551          global $wpdb;
 552  
 553          $thread_id = (int) $thread_id;
 554          $user_id   = (int) $user_id;
 555  
 556          if ( empty( $user_id ) ) {
 557              $user_id = bp_loggedin_user_id();
 558          }
 559  
 560          // Check the user is a recipient of the thread and recipients count > 2.
 561          $recipients    = self::get_recipients_for_thread( $thread_id );
 562          $recipient_ids = wp_list_pluck( $recipients, 'user_id' );
 563  
 564          if ( 2 >= count( $recipient_ids ) || ! in_array( $user_id, $recipient_ids, true ) ) {
 565              return false;
 566          }
 567  
 568          /**
 569           * Fires before a user exits a thread.
 570           *
 571           * @since 10.0.0
 572           *
 573           * @param int $thread_id ID of the thread being deleted.
 574           * @param int $user_id   ID of the user that the thread is being deleted for.
 575           */
 576          do_action( 'bp_messages_thread_before_exit', $thread_id, $user_id );
 577  
 578          $bp = buddypress();
 579  
 580          // Delete the user from messages recipients
 581          $exited = $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->messages->table_name_recipients} WHERE thread_id = %d AND user_id = %d", $thread_id, $user_id ) );
 582  
 583          // Bail if the user wasn't removed from the recipients list.
 584          if ( empty( $exited ) ) {
 585              return false;
 586          }
 587  
 588          /**
 589           * Fires after a user exits a thread.
 590           *
 591           * @since 10.0.0
 592           *
 593           * @param int   $thread_id ID of the thread being deleted.
 594           * @param int   $user_id   ID of the user the threads were deleted for.
 595           */
 596          do_action( 'bp_messages_thread_after_exit', $thread_id, $user_id );
 597  
 598          return true;
 599      }
 600  
 601      /**
 602       * Get current message threads for a user.
 603       *
 604       * @since 1.0.0
 605       *
 606       * @global BuddyPress $bp The one true BuddyPress instance.
 607       * @global wpdb $wpdb WordPress database object.
 608       *
 609       * @param array $args {
 610       *     Array of arguments.
 611       *     @type int      $user_id             The user ID.
 612       *     @type string   $box                 The type of mailbox to get. Either 'inbox' or 'sentbox'.
 613       *                                         Defaults to 'inbox'.
 614       *     @type string   $type                The type of messages to get. Either 'all' or 'unread'
 615       *                                         or 'read'. Defaults to 'all'.
 616       *     @type int      $limit               The number of messages to get. Defaults to null.
 617       *     @type int      $page                The page number to get. Defaults to null.
 618       *     @type string   $search_terms        The search term to use. Defaults to ''.
 619       *     @type array    $meta_query          Meta query arguments. See WP_Meta_Query for more details.
 620       *     @type int|null $recipients_page     Page of recipients being requested. Default to null, meaning all.
 621       *     @type int|null $recipients_per_page Recipients to return per page. Defaults to null, meaning all.
 622       *     @type int|null $messages_page       Page of messages being requested. Default to null, meaning all.
 623       *     @type int|null $messages_per_page   Messages to return per page. Defaults to null, meaning all.
 624       * }
 625       * @return array|bool Array on success. False on failure.
 626       */
 627  	public static function get_current_threads_for_user( $args = array() ) {
 628          global $wpdb;
 629  
 630          $function_args = func_get_args();
 631  
 632          // Backward compatibility with old method of passing arguments.
 633          if ( ! is_array( $args ) || count( $function_args ) > 1 ) {
 634              _deprecated_argument(
 635                  __METHOD__,
 636                  '2.2.0',
 637                  sprintf(
 638                      /* translators: 1: the name of the method. 2: the name of the file. */
 639                      esc_html__( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ),
 640                      __METHOD__,
 641                      __FILE__
 642                  )
 643              );
 644  
 645              $old_args_keys = array(
 646                  0 => 'user_id',
 647                  1 => 'box',
 648                  2 => 'type',
 649                  3 => 'limit',
 650                  4 => 'page',
 651                  5 => 'search_terms',
 652              );
 653  
 654              $args = bp_core_parse_args_array( $old_args_keys, $function_args );
 655          }
 656  
 657          $r = bp_parse_args(
 658              $args,
 659              array(
 660                  'user_id'             => false,
 661                  'box'                 => 'inbox',
 662                  'type'                => 'all',
 663                  'limit'               => null,
 664                  'page'                => null,
 665                  'recipients_page'     => null,
 666                  'recipients_per_page' => null,
 667                  'messages_page'       => null,
 668                  'messages_per_page'   => null,
 669                  'search_terms'        => '',
 670                  'meta_query'          => array(),
 671              )
 672          );
 673  
 674          $pag_sql = $type_sql = $search_sql = $user_id_sql = $sender_sql = '';
 675          $meta_query_sql = array(
 676              'join'  => '',
 677              'where' => '',
 678          );
 679  
 680          if ( $r['limit'] && $r['page'] ) {
 681              $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $r['page'] - 1 ) * $r['limit'] ), intval( $r['limit'] ) );
 682          }
 683  
 684          if ( $r['type'] == 'unread' ) {
 685              $type_sql = " AND r.unread_count != 0 ";
 686          } elseif ( $r['type'] == 'read' ) {
 687              $type_sql = " AND r.unread_count = 0 ";
 688          }
 689  
 690          if ( ! empty( $r['search_terms'] ) ) {
 691              $search_terms_like = '%' . bp_esc_like( $r['search_terms'] ) . '%';
 692              $search_sql        = $wpdb->prepare( "AND ( subject LIKE %s OR message LIKE %s )", $search_terms_like, $search_terms_like );
 693          }
 694  
 695          $r['user_id'] = (int) $r['user_id'];
 696  
 697          // Default deleted SQL.
 698          $deleted_sql = 'r.is_deleted = 0';
 699  
 700          switch ( $r['box'] ) {
 701              case 'sentbox':
 702                  $user_id_sql = 'AND ' . $wpdb->prepare( 'm.sender_id = %d', $r['user_id'] );
 703                  $sender_sql  = 'AND m.sender_id = r.user_id';
 704                  break;
 705  
 706              case 'inbox':
 707                  $user_id_sql = 'AND ' . $wpdb->prepare( 'r.user_id = %d', $r['user_id'] );
 708                  $sender_sql  = 'AND r.sender_only = 0';
 709                  break;
 710  
 711              default:
 712                  // Omit user-deleted threads from all other custom message boxes.
 713                  $deleted_sql = $wpdb->prepare( '( r.user_id = %d AND r.is_deleted = 0 )', $r['user_id'] );
 714                  break;
 715          }
 716  
 717          // Process meta query into SQL.
 718          $meta_query = self::get_meta_query_sql( $r['meta_query'] );
 719          if ( ! empty( $meta_query['join'] ) ) {
 720              $meta_query_sql['join'] = $meta_query['join'];
 721          }
 722          if ( ! empty( $meta_query['where'] ) ) {
 723              $meta_query_sql['where'] = $meta_query['where'];
 724          }
 725  
 726          $bp = buddypress();
 727  
 728          // Set up SQL array.
 729          $sql = array();
 730          $sql['select'] = 'SELECT m.thread_id, MAX(m.date_sent) AS date_sent';
 731          $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']}";
 732          $sql['where']  = "WHERE {$deleted_sql} {$user_id_sql} {$sender_sql} {$type_sql} {$search_sql} {$meta_query_sql['where']}";
 733          $sql['misc']   = "GROUP BY m.thread_id ORDER BY date_sent DESC {$pag_sql}";
 734  
 735          // Get thread IDs.
 736          $thread_ids = $wpdb->get_results( implode( ' ', $sql ) );
 737          if ( empty( $thread_ids ) ) {
 738              return false;
 739          }
 740  
 741          // Adjust $sql to work for thread total.
 742          $sql['select'] = 'SELECT COUNT( DISTINCT m.thread_id )';
 743          unset( $sql['misc'] );
 744          $total_threads = $wpdb->get_var( implode( ' ', $sql ) );
 745  
 746          // Sort threads by date_sent.
 747          foreach( (array) $thread_ids as $thread ) {
 748              $sorted_threads[ $thread->thread_id ] = strtotime( $thread->date_sent );
 749          }
 750  
 751          arsort( $sorted_threads );
 752  
 753          $threads = array();
 754          foreach ( (array) $sorted_threads as $thread_id => $date_sent ) {
 755              $threads[] = new BP_Messages_Thread(
 756                  $thread_id,
 757                  'ASC',
 758                  array(
 759                      'update_meta_cache'   => false,
 760                      'recipients_page'     => $r['recipients_page'],
 761                      'recipients_per_page' => $r['recipients_per_page'],
 762                      'page'                => $r['messages_page'],
 763                      'per_page'            => $r['messages_per_page'],
 764                  )
 765              );
 766          }
 767  
 768          /**
 769           * Filters the results of the query for a user's message threads.
 770           *
 771           * @since 2.2.0
 772           *
 773           * @param array $value {
 774           *     @type array $threads       Array of threads. Passed by reference.
 775           *     @type int   $total_threads Number of threads found by the query.
 776           * }
 777           *  @param array $r    Array of paremeters.
 778           */
 779          return apply_filters(
 780              'bp_messages_thread_current_threads',
 781              array(
 782                  'threads' => &$threads,
 783                  'total'   => (int) $total_threads,
 784              ),
 785              $r
 786          );
 787      }
 788  
 789      /**
 790       * Get the SQL for the 'meta_query' param in BP_Messages_Thread::get_current_threads_for_user().
 791       *
 792       * We use WP_Meta_Query to do the heavy lifting of parsing the meta_query array
 793       * and creating the necessary SQL clauses.
 794       *
 795       * @since 2.2.0
 796       *
 797       * @global wpdb $wpdb WordPress database object.
 798       *
 799       * @param array $meta_query An array of meta_query filters. See the
 800       *                          documentation for WP_Meta_Query for details.
 801       * @return array $sql_array 'join' and 'where' clauses.
 802       */
 803  	public static function get_meta_query_sql( $meta_query = array() ) {
 804          global $wpdb;
 805  
 806          $sql_array = array(
 807              'join'  => '',
 808              'where' => '',
 809          );
 810  
 811          if ( ! empty( $meta_query ) ) {
 812              $meta_query = new WP_Meta_Query( $meta_query );
 813  
 814              // WP_Meta_Query expects the table name at
 815              // $wpdb->messagemeta.
 816              $wpdb->messagemeta = buddypress()->messages->table_name_meta;
 817  
 818              return $meta_query->get_sql( 'message', 'm', 'id' );
 819          }
 820  
 821          return $sql_array;
 822      }
 823  
 824      /**
 825       * Mark a thread as read.
 826       *
 827       * @since 1.0.0
 828       * @since 9.0.0 Added the `user_id` parameter.
 829       *
 830       * @global BuddyPress $bp The one true BuddyPress instance.
 831       * @global wpdb $wpdb WordPress database object.
 832       *
 833       * @param int $thread_id The message thread ID.
 834       * @param int $user_id   The user the thread will be marked as read.
 835       *
 836       * @return bool|int Number of threads marked as read or false on error.
 837       */
 838  	public static function mark_as_read( $thread_id = 0, $user_id = 0 ) {
 839          global $wpdb;
 840  
 841          if ( empty( $user_id ) ) {
 842              $user_id =
 843                  bp_displayed_user_id() ?
 844                  bp_displayed_user_id() :
 845                  bp_loggedin_user_id();
 846          }
 847  
 848          $bp       = buddypress();
 849          $num_rows = $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET unread_count = 0 WHERE user_id = %d AND thread_id = %d", $user_id, $thread_id ) );
 850  
 851          wp_cache_delete( 'thread_recipients_' . $thread_id, 'bp_messages' );
 852          wp_cache_delete( $user_id, 'bp_messages_unread_count' );
 853  
 854          /**
 855           * Fires when messages thread was marked as read.
 856           *
 857           * @since 2.8.0
 858           * @since 9.0.0 Added the `user_id` parameter.
 859           * @since 10.0.0 Added the `$num_rows` parameter.
 860           *
 861           * @param int $thread_id The message thread ID.
 862           * @param int $user_id   The user the thread will be marked as read.
 863           * @param bool|int $num_rows    Number of threads marked as unread or false on error.
 864           */
 865          do_action( 'messages_thread_mark_as_read', $thread_id, $user_id, $num_rows );
 866  
 867          return $num_rows;
 868      }
 869  
 870      /**
 871       * Mark a thread as unread.
 872       *
 873       * @since 1.0.0
 874       * @since 9.0.0 Added the `user_id` parameter.
 875       *
 876       * @global BuddyPress $bp The one true BuddyPress instance.
 877       * @global wpdb $wpdb WordPress database object.
 878       *
 879       * @param int $thread_id The message thread ID.
 880       * @param int $user_id   The user the thread will be marked as unread.
 881       *
 882       * @return bool|int Number of threads marked as unread or false on error.
 883       */
 884  	public static function mark_as_unread( $thread_id = 0, $user_id = 0 ) {
 885          global $wpdb;
 886  
 887          if ( empty( $user_id ) ) {
 888              $user_id =
 889                  bp_displayed_user_id() ?
 890                  bp_displayed_user_id() :
 891                  bp_loggedin_user_id();
 892          }
 893  
 894          $bp       = buddypress();
 895          $num_rows = $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET unread_count = 1 WHERE user_id = %d AND thread_id = %d", $user_id, $thread_id ) );
 896  
 897          wp_cache_delete( 'thread_recipients_' . $thread_id, 'bp_messages' );
 898          wp_cache_delete( $user_id, 'bp_messages_unread_count' );
 899  
 900          /**
 901           * Fires when messages thread was marked as unread.
 902           *
 903           * @since 2.8.0
 904           * @since 9.0.0  Added the `$user_id` parameter.
 905           * @since 10.0.0 Added the `$num_rows` parameter.
 906           *
 907           * @param int      $thread_id The message thread ID.
 908           * @param int      $user_id   The user the thread will be marked as unread.
 909           * @param bool|int $num_rows  Number of threads marked as unread or false on error.
 910           */
 911          do_action( 'messages_thread_mark_as_unread', $thread_id, $user_id, $num_rows );
 912  
 913          return $num_rows;
 914      }
 915  
 916      /**
 917       * Returns the total number of message threads for a user.
 918       *
 919       * @since 1.0.0
 920       *
 921       * @param int    $user_id The user ID.
 922       * @param string $box     The type of mailbox to get. Either 'inbox' or 'sentbox'.
 923       *                        Defaults to 'inbox'.
 924       * @param string $type    The type of messages to get. Either 'all' or 'unread'.
 925       *                        or 'read'. Defaults to 'all'.
 926       * @return int Total thread count for the provided user.
 927       */
 928  	public static function get_total_threads_for_user( $user_id, $box = 'inbox', $type = 'all' ) {
 929          global $wpdb;
 930  
 931          $exclude_sender = $type_sql = '';
 932          if ( $box !== 'sentbox' ) {
 933              $exclude_sender = 'AND sender_only != 1';
 934          }
 935  
 936          if ( $type === 'unread' ) {
 937              $type_sql = 'AND unread_count != 0';
 938          } elseif ( $type === 'read' ) {
 939              $type_sql = 'AND unread_count = 0';
 940          }
 941  
 942          $bp = buddypress();
 943  
 944          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 ) );
 945      }
 946  
 947      /**
 948       * Determine if the logged-in user is a sender of any message in a thread.
 949       *
 950       * @since 1.0.0
 951       *
 952       * @global BuddyPress $bp The one true BuddyPress instance.
 953       * @global wpdb $wpdb WordPress database object.
 954       *
 955       * @param int $thread_id The message thread ID.
 956       * @return bool
 957       */
 958  	public static function user_is_sender( $thread_id ) {
 959          global $wpdb;
 960  
 961          $bp = buddypress();
 962  
 963          $sender_ids = $wpdb->get_col( $wpdb->prepare( "SELECT sender_id FROM {$bp->messages->table_name_messages} WHERE thread_id = %d", $thread_id ) );
 964  
 965          if ( empty( $sender_ids ) ) {
 966              return false;
 967          }
 968  
 969          return in_array( bp_loggedin_user_id(), $sender_ids, true );
 970      }
 971  
 972      /**
 973       * Returns the userlink of the last sender in a message thread.
 974       *
 975       * @since 1.0.0
 976       *
 977       * @global BuddyPress $bp The one true BuddyPress instance.
 978       * @global wpdb $wpdb WordPress database object.
 979       *
 980       * @param int $thread_id The message thread ID.
 981       * @return string|bool The user link on success. Boolean false on failure.
 982       */
 983  	public static function get_last_sender( $thread_id ) {
 984          global $wpdb;
 985  
 986          $bp = buddypress();
 987  
 988          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 ) ) ) {
 989              return false;
 990          }
 991  
 992          return bp_core_get_userlink( $sender_id, true );
 993      }
 994  
 995      /**
 996       * Gets the unread message count for a user.
 997       *
 998       * @since 1.0.0
 999       *
1000       * @global BuddyPress $bp The one true BuddyPress instance.
1001       * @global wpdb $wpdb WordPress database object.
1002       *
1003       * @param int $user_id The user ID.
1004       * @return int Total inbox unread count for user.
1005       */
1006  	public static function get_inbox_count( $user_id = 0 ) {
1007          global $wpdb;
1008  
1009          if ( empty( $user_id ) ) {
1010              $user_id = bp_loggedin_user_id();
1011          }
1012  
1013          $unread_count = wp_cache_get( $user_id, 'bp_messages_unread_count' );
1014  
1015          if ( false === $unread_count ) {
1016              $bp = buddypress();
1017  
1018              $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 ) );
1019  
1020              wp_cache_set( $user_id, $unread_count, 'bp_messages_unread_count' );
1021          }
1022  
1023          /**
1024           * Filters a user's unread message count.
1025           *
1026           * @since 2.2.0
1027           *
1028           * @param int $unread_count Unread message count.
1029           * @param int $user_id      ID of the user.
1030           */
1031          return apply_filters( 'messages_thread_get_inbox_count', (int) $unread_count, $user_id );
1032      }
1033  
1034      /**
1035       * Checks whether a user is a part of a message thread discussion.
1036       *
1037       * @since 1.0.0
1038       *
1039       * @param int $thread_id The message thread ID.
1040       * @param int $user_id   The user ID. Default: ID of the logged-in user.
1041       * @return int|null The recorded recipient ID on success, null on failure.
1042       */
1043  	public static function check_access( $thread_id, $user_id = 0 ) {
1044  
1045          if ( empty( $user_id ) ) {
1046              $user_id = bp_loggedin_user_id();
1047          }
1048  
1049          $recipients = self::get_recipients_for_thread( $thread_id );
1050  
1051          if ( isset( $recipients[ $user_id ] ) && 0 === $recipients[ $user_id ]->is_deleted ) {
1052              return $recipients[ $user_id ]->id;
1053          }
1054  
1055          return null;
1056      }
1057  
1058      /**
1059       * Checks whether a message thread exists.
1060       *
1061       * @since 1.0.0
1062       *
1063       * @param int $thread_id The message thread ID.
1064       * @return bool|int|null The message thread ID on success, null on failure.
1065       */
1066  	public static function is_valid( $thread_id = 0 ) {
1067  
1068          // Bail if no thread ID is passed.
1069          if ( empty( $thread_id ) ) {
1070              return false;
1071          }
1072  
1073          $thread = self::get_messages( $thread_id );
1074  
1075          if ( ! empty( $thread ) ) {
1076              return $thread_id;
1077          } else {
1078              return null;
1079          }
1080      }
1081  
1082      /**
1083       * Returns a string containing all the message recipient userlinks.
1084       *
1085       * String is comma-delimited.
1086       *
1087       * If a message thread has more than four users, the returned string is simply
1088       * "X Recipients" where "X" is the number of recipients in the message thread.
1089       *
1090       * @since 1.0.0
1091       *
1092       * @param array $recipients Array containing the message recipients (array of objects).
1093       * @return string String of message recipent userlinks.
1094       */
1095  	public static function get_recipient_links( $recipients ) {
1096  
1097          if ( count( $recipients ) >= 5 ) {
1098              /* translators: %s: number of message recipients */
1099              return sprintf( __( '%s Recipients', 'buddypress' ), number_format_i18n( count( $recipients ) ) );
1100          }
1101  
1102          $recipient_links = array();
1103  
1104          foreach ( (array) $recipients as $recipient ) {
1105              $recipient_link = bp_core_get_userlink( $recipient->user_id );
1106  
1107              if ( empty( $recipient_link ) ) {
1108                  $recipient_link = __( 'Deleted User', 'buddypress' );
1109              }
1110  
1111              $recipient_links[] = $recipient_link;
1112          }
1113  
1114          return implode( ', ', (array) $recipient_links );
1115      }
1116  
1117      /**
1118       * Upgrade method for the older BP message thread DB table.
1119       *
1120       * @todo We should remove this. No one is going to upgrade from v1.1, right?
1121       *
1122       * @since 1.2.0
1123       *
1124       * @global BuddyPress $bp The one true BuddyPress instance.
1125       * @global wpdb $wpdb WordPress database object.
1126       *
1127       * @return bool
1128       */
1129  	public static function update_tables() {
1130          global $wpdb;
1131  
1132          $bp_prefix = bp_core_get_table_prefix();
1133          $errors    = false;
1134          $threads   = $wpdb->get_results( "SELECT * FROM {$bp_prefix}bp_messages_threads" );
1135  
1136          // Nothing to update, just return true to remove the table.
1137          if ( empty( $threads ) ) {
1138              return true;
1139          }
1140  
1141          $bp = buddypress();
1142  
1143          foreach( (array) $threads as $thread ) {
1144              $message_ids = maybe_unserialize( $thread->message_ids );
1145  
1146              if ( ! empty( $message_ids ) ) {
1147                  $message_ids = implode( ',', $message_ids );
1148  
1149                  // Add the thread_id to the messages table.
1150                  if ( ! $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_messages} SET thread_id = %d WHERE id IN ({$message_ids})", $thread->id ) ) ) {
1151                      $errors = true;
1152                  }
1153              }
1154          }
1155  
1156          return (bool) ! $errors;
1157      }
1158  }


Generated: Sat Apr 27 01:00:55 2024 Cross-referenced by PHPXref 0.7.1