You are here

function privatemsg_thread_load in Privatemsg 7

Same name and namespace in other branches
  1. 6.2 privatemsg.module \privatemsg_thread_load()
  2. 6 privatemsg.module \privatemsg_thread_load()
  3. 7.2 privatemsg.module \privatemsg_thread_load()

Load a thread with all the messages and participants.

This function is called by the menu system through the %privatemsg_thread wildcard.

Parameters

$thread_id: Thread id, pmi.thread_id or pm.mid of the first message in that thread.

$account: User object for which the thread should be loaded, defaults to the current user.

$start: Message offset from the start of the thread.

$useAccessDenied: Set to TRUE if the function should forward to the access denied page instead of not found. This is used by the menu system because that does load arguments before access checks are made. Defaults to FALSE.

Return value

$thread object, with keys messages, participants, title and user. messages contains an array of messages, participants an array of user, subject the subject of the thread and user the user viewing the thread.

If no messages are found, or the thread_id is invalid, the function returns FALSE.

Related topics

File

./privatemsg.module, line 440
Allows users to send private messages to other users.

Code

function privatemsg_thread_load($thread_id, $account = NULL, $start = NULL, $useAccessDenied = FALSE) {
  $threads =& drupal_static(__FUNCTION__, array());
  $thread_id = (int) $thread_id;
  if ($thread_id > 0) {
    $thread = array(
      'thread_id' => $thread_id,
    );
    if (is_null($account)) {
      global $user;
      $account = clone $user;
    }
    if (!isset($threads[$account->uid])) {
      $threads[$account->uid] = array();
    }
    if (!array_key_exists($thread_id, $threads[$account->uid])) {

      // Load the list of participants.
      $thread['participants'] = _privatemsg_load_thread_participants($thread_id, $account, FALSE, 'view');
      $thread['read_all'] = FALSE;
      if (empty($thread['participants']) && privatemsg_user_access('read all private messages', $account)) {
        $thread['read_all'] = TRUE;

        // Load all participants.
        $thread['participants'] = _privatemsg_load_thread_participants($thread_id, FALSE, FALSE, 'view');
      }

      // Load messages returned by the messages query with privatemsg_message_load_multiple().
      $query = _privatemsg_assemble_query('messages', array(
        $thread_id,
      ), $thread['read_all'] ? NULL : $account);

      // Use subquery to bypass group by since it is not possible to alter
      // existing GROUP BY statements.
      $countQuery = db_select($query);
      $countQuery
        ->addExpression('COUNT(*)');
      $thread['message_count'] = $thread['to'] = $countQuery
        ->execute()
        ->fetchField();
      $thread['from'] = 1;

      // Check if we need to limit the messages.
      $max_amount = variable_get('privatemsg_view_max_amount', 20);

      // If there is no start value, select based on get params.
      if (is_null($start)) {
        if (isset($_GET['start']) && $_GET['start'] < $thread['message_count']) {
          $start = $_GET['start'];
        }
        elseif (!variable_get('privatemsg_view_use_max_as_default', FALSE) && $max_amount == PRIVATEMSG_UNLIMITED) {
          $start = PRIVATEMSG_UNLIMITED;
        }
        else {
          $start = $thread['message_count'] - (variable_get('privatemsg_view_use_max_as_default', FALSE) ? variable_get('privatemsg_view_default_amount', 10) : $max_amount);
        }
      }
      if ($start != PRIVATEMSG_UNLIMITED) {
        if ($max_amount == PRIVATEMSG_UNLIMITED) {
          $last_page = 0;
          $max_amount = $thread['message_count'];
        }
        else {

          // Calculate the number of messages on the "last" page to avoid
          // message overlap.
          // Note - the last page lists the earliest messages, not the latest.
          $paging_count = variable_get('privatemsg_view_use_max_as_default', FALSE) ? $thread['message_count'] - variable_get('privatemsg_view_default_amount', 10) : $thread['message_count'];
          $last_page = $paging_count % $max_amount;
        }

        // Sanity check - we cannot start from a negative number.
        if ($start < 0) {
          $start = 0;
        }
        $thread['start'] = $start;

        //If there are newer messages on the page, show pager link allowing to go to the newer messages.
        if ($start + $max_amount + 1 < $thread['message_count']) {
          $thread['to'] = $start + $max_amount;
          $thread['newer_start'] = $start + $max_amount;
        }
        if ($start - $max_amount >= 0) {
          $thread['older_start'] = $start - $max_amount;
        }
        elseif ($start > 0) {
          $thread['older_start'] = 0;
        }

        // Do not show messages on the last page that would show on the page
        // before. This will only work when using the visual pager.
        if ($start < $last_page && $max_amount != PRIVATEMSG_UNLIMITED && $max_amount < $thread['message_count']) {
          unset($thread['older_start']);
          $thread['to'] = $thread['newer_start'] = $max_amount = $last_page;

          // Start from the first message - this is a specific hack to make sure
          // the message display has sane paging on the last page.
          $start = 0;
        }

        // Visual counts start from 1 instead of zero, so plus one.
        $thread['from'] = $start + 1;
        $query
          ->range($start, $max_amount);
      }
      $conditions = array();
      if (!$thread['read_all']) {
        $conditions['account'] = $account;
      }

      // If the $ids parameter is empty, privatemsg_message_load_multiple will
      // load all threads.
      // @see https://drupal.org/node/2033161
      $ids = $query
        ->execute()
        ->fetchCol();
      if (count($ids)) {
        $thread['messages'] = privatemsg_message_load_multiple($ids, $conditions);
      }

      // If there are no messages, don't allow access to the thread.
      if (empty($thread['messages'])) {
        if ($useAccessDenied) {

          // Generate new query with read all to see if the thread does exist.
          $query = _privatemsg_assemble_query('messages', array(
            $thread_id,
          ), NULL);
          $exists = $query
            ->countQuery()
            ->execute()
            ->fetchField();
          if (!$exists) {

            // Thread does not exist, display 404.
            $thread = FALSE;
          }
        }
        else {
          $thread = FALSE;
        }
      }
      else {

        // General data, assume subject is the same for all messages of that thread.
        $thread['user'] = $account;
        $message = current($thread['messages']);
        $thread['subject'] = $thread['subject-original'] = $message->subject;
        if ($message->has_tokens) {
          $thread['subject'] = privatemsg_token_replace($thread['subject'], array(
            'privatemsg_message' => $message,
          ), array(
            'sanitize' => TRUE,
            'privatemsg-show-span' => FALSE,
          ));
        }
      }
      $threads[$account->uid][$thread_id] = $thread;
    }
    return $threads[$account->uid][$thread_id];
  }
  return FALSE;
}