function MessageFolder()
{
    global $txt, $scripturl, $db_prefix, $ID_MEMBER, $modSettings, $context;
    global $messages_request, $user_info, $recipients, $options;
    // Make sure the starting location is valid.
    if (isset($_GET['start']) && $_GET['start'] != 'new') {
        $_GET['start'] = (int) $_GET['start'];
    } elseif (!isset($_GET['start']) && !empty($options['view_newest_pm_first'])) {
        $_GET['start'] = 0;
    } else {
        $_GET['start'] = 'new';
    }
    // Set up some basic theme stuff.
    $context['allow_hide_email'] = !empty($modSettings['allow_hideEmail']);
    $context['from_or_to'] = $context['folder'] != 'outbox' ? 'from' : 'to';
    $context['get_pmessage'] = 'prepareMessageContext';
    $labelQuery = $context['folder'] != 'outbox' ? "\n\t\t\tAND FIND_IN_SET('{$context['current_label_id']}', pmr.labels)" : '';
    // Set the index bar correct!
    messageIndexBar($context['current_label_id'] == -1 ? $context['folder'] : 'label' . $context['current_label_id']);
    // Sorting the folder.
    $sort_methods = array('date' => 'pm.ID_PM', 'name' => "IFNULL(mem.realName, '')", 'subject' => 'pm.subject');
    // They didn't pick one, use the forum default.
    if (!isset($_GET['sort']) || !isset($sort_methods[$_GET['sort']])) {
        $context['sort_by'] = 'date';
        $_GET['sort'] = 'pm.ID_PM';
        $descending = false;
    } else {
        $context['sort_by'] = $_GET['sort'];
        $_GET['sort'] = $sort_methods[$_GET['sort']];
        $descending = isset($_GET['desc']);
    }
    if (!empty($options['view_newest_pm_first'])) {
        $descending = !$descending;
    }
    $context['sort_direction'] = $descending ? 'down' : 'up';
    // Why would you want access to your outbox if you're not allowed to send anything?
    if ($context['folder'] == 'outbox') {
        isAllowedTo('pm_send');
    }
    // Set the text to resemble the current folder.
    $pmbox = $context['folder'] != 'outbox' ? $txt[316] : $txt[320];
    $txt[412] = str_replace('PMBOX', $pmbox, $txt[412]);
    // Now, build the link tree!
    $context['linktree'][] = array('url' => $scripturl . '?action=pm;f=' . $context['folder'], 'name' => $pmbox);
    // Build it further for a label.
    if ($context['current_label_id'] != -1) {
        $context['linktree'][] = array('url' => $scripturl . '?action=pm;f=' . $context['folder'] . ';l=' . $context['current_label_id'], 'name' => $txt['pm_current_label'] . ': ' . $context['current_label']);
    }
    // Mark all messages as read if in the inbox.
    if ($context['folder'] != 'outbox' && !empty($context['labels'][(int) $context['current_label_id']]['unread_messages'])) {
        markMessages(null, $context['current_label_id']);
    }
    // Figure out how many messages there are.
    if ($context['folder'] == 'outbox') {
        $request = db_query("\n\t\t\tSELECT COUNT(*)\n\t\t\tFROM {$db_prefix}personal_messages\n\t\t\tWHERE ID_MEMBER_FROM = {$ID_MEMBER}\n\t\t\t\tAND deletedBySender = 0", __FILE__, __LINE__);
    } else {
        $request = db_query("\n\t\t\tSELECT COUNT(*)\n\t\t\tFROM {$db_prefix}pm_recipients AS pmr\n\t\t\tWHERE pmr.ID_MEMBER = {$ID_MEMBER}\n\t\t\t\tAND pmr.deleted = 0{$labelQuery}", __FILE__, __LINE__);
    }
    list($max_messages) = mysql_fetch_row($request);
    mysql_free_result($request);
    // Only show the button if there are messages to delete.
    $context['show_delete'] = $max_messages > 0;
    // Start on the last page.
    if (!is_numeric($_GET['start']) || $_GET['start'] >= $max_messages) {
        $_GET['start'] = $max_messages - 1 - ($max_messages - 1) % $modSettings['defaultMaxMessages'];
    } elseif ($_GET['start'] < 0) {
        $_GET['start'] = 0;
    }
    // ... but wait - what if we want to start from a specific message?
    if (isset($_GET['pmid'])) {
        $_GET['pmid'] = (int) $_GET['pmid'];
        // With only one page of PM's we're gonna want page 1.
        if ($max_messages <= $modSettings['defaultMaxMessages']) {
            $_GET['start'] = 0;
        } else {
            if ($context['folder'] == 'outbox') {
                $request = db_query("\n\t\t\t\t\tSELECT COUNT(*)\n\t\t\t\t\tFROM {$db_prefix}personal_messages\n\t\t\t\t\tWHERE ID_MEMBER_FROM = {$ID_MEMBER}\n\t\t\t\t\t\tAND deletedBySender = 0\n\t\t\t\t\t\tAND ID_PM " . ($descending ? '>' : '<') . " {$_GET['pmid']}", __FILE__, __LINE__);
            } else {
                $request = db_query("\n\t\t\t\t\tSELECT COUNT(*)\n\t\t\t\t\tFROM {$db_prefix}pm_recipients AS pmr\n\t\t\t\t\tWHERE pmr.ID_MEMBER = {$ID_MEMBER}\n\t\t\t\t\t\tAND pmr.deleted = 0{$labelQuery}\n\t\t\t\t\t\tAND ID_PM " . ($descending ? '>' : '<') . " {$_GET['pmid']}", __FILE__, __LINE__);
            }
            list($_GET['start']) = mysql_fetch_row($request);
            mysql_free_result($request);
            // To stop the page index's being abnormal, start the page on the page the message would normally be located on...
            $_GET['start'] = $modSettings['defaultMaxMessages'] * (int) ($_GET['start'] / $modSettings['defaultMaxMessages']);
        }
    }
    // Set up the page index.
    $context['page_index'] = constructPageIndex($scripturl . '?action=pm;f=' . $context['folder'] . (isset($_REQUEST['l']) ? ';l=' . (int) $_REQUEST['l'] : '') . ';sort=' . $context['sort_by'] . (isset($_GET['desc']) ? ';desc' : ''), $_GET['start'], $max_messages, $modSettings['defaultMaxMessages']);
    $context['start'] = $_GET['start'];
    // Determine the navigation context (especially useful for the wireless template).
    $context['links'] = array('first' => $_GET['start'] >= $modSettings['defaultMaxMessages'] ? $scripturl . '?action=pm;start=0' : '', 'prev' => $_GET['start'] >= $modSettings['defaultMaxMessages'] ? $scripturl . '?action=pm;start=' . ($_GET['start'] - $modSettings['defaultMaxMessages']) : '', 'next' => $_GET['start'] + $modSettings['defaultMaxMessages'] < $max_messages ? $scripturl . '?action=pm;start=' . ($_GET['start'] + $modSettings['defaultMaxMessages']) : '', 'last' => $_GET['start'] + $modSettings['defaultMaxMessages'] < $max_messages ? $scripturl . '?action=pm;start=' . floor(($max_messages - 1) / $modSettings['defaultMaxMessages']) * $modSettings['defaultMaxMessages'] : '', 'up' => $scripturl);
    $context['page_info'] = array('current_page' => $_GET['start'] / $modSettings['defaultMaxMessages'] + 1, 'num_pages' => floor(($max_messages - 1) / $modSettings['defaultMaxMessages']) + 1);
    // Load the messages up...
    // !!!SLOW This query uses a filesort. (inbox only.)
    $request = db_query("\n\t\tSELECT pm.ID_PM, pm.ID_MEMBER_FROM\n\t\tFROM ({$db_prefix}personal_messages AS pm" . ($context['folder'] == 'outbox' ? ')' . ($context['sort_by'] == 'name' ? "\n\t\t\tLEFT JOIN {$db_prefix}pm_recipients AS pmr ON (pmr.ID_PM = pm.ID_PM)" : '') : ", {$db_prefix}pm_recipients AS pmr)") . ($context['sort_by'] == 'name' ? "\n\t\t\tLEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = " . ($context['folder'] == 'outbox' ? 'pmr.ID_MEMBER' : 'pm.ID_MEMBER_FROM') . ")" : '') . "\n\t\tWHERE " . ($context['folder'] == 'outbox' ? "pm.ID_MEMBER_FROM = {$ID_MEMBER}\n\t\t\tAND pm.deletedBySender = 0" : "pmr.ID_PM = pm.ID_PM\n\t\t\tAND pmr.ID_MEMBER = {$ID_MEMBER}\n\t\t\tAND pmr.deleted = 0{$labelQuery}") . (empty($_GET['pmsg']) ? '' : "\n\t\t\tAND pm.ID_PM = " . (int) $_GET['pmsg']) . "\n\t\tORDER BY " . ($_GET['sort'] == 'pm.ID_PM' && $context['folder'] != 'outbox' ? 'pmr.ID_PM' : $_GET['sort']) . ($descending ? ' DESC' : ' ASC') . (empty($_GET['pmsg']) ? "\n\t\tLIMIT {$_GET['start']}, {$modSettings['defaultMaxMessages']}" : ''), __FILE__, __LINE__);
    // Load the ID_PMs and ID_MEMBERs and initialize recipients.
    $pms = array();
    $posters = $context['folder'] == 'outbox' ? array($ID_MEMBER) : array();
    $recipients = array();
    while ($row = mysql_fetch_assoc($request)) {
        if (!isset($recipients[$row['ID_PM']])) {
            $pms[] = $row['ID_PM'];
            if (!empty($row['ID_MEMBER_FROM']) && $context['folder'] != 'outbox') {
                $posters[] = $row['ID_MEMBER_FROM'];
            }
            $recipients[$row['ID_PM']] = array('to' => array(), 'bcc' => array());
        }
    }
    mysql_free_result($request);
    if (!empty($pms)) {
        // Get recipients (don't include bcc-recipients for your inbox, you're not supposed to know :P).
        $request = db_query("\n\t\t\tSELECT pmr.ID_PM, mem_to.ID_MEMBER AS ID_MEMBER_TO, mem_to.realName AS toName, pmr.bcc, pmr.labels, pmr.is_read\n\t\t\tFROM {$db_prefix}pm_recipients AS pmr\n\t\t\t\tLEFT JOIN {$db_prefix}members AS mem_to ON (mem_to.ID_MEMBER = pmr.ID_MEMBER)\n\t\t\tWHERE pmr.ID_PM IN (" . implode(', ', $pms) . ")", __FILE__, __LINE__);
        $context['message_labels'] = array();
        $context['message_replied'] = array();
        while ($row = mysql_fetch_assoc($request)) {
            if ($context['folder'] == 'outbox' || empty($row['bcc'])) {
                $recipients[$row['ID_PM']][empty($row['bcc']) ? 'to' : 'bcc'][] = empty($row['ID_MEMBER_TO']) ? $txt[28] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER_TO'] . '">' . $row['toName'] . '</a>';
            }
            if ($row['ID_MEMBER_TO'] == $ID_MEMBER && $context['folder'] != 'outbox') {
                $context['message_replied'][$row['ID_PM']] = $row['is_read'] & 2;
                $row['labels'] = $row['labels'] == '' ? array() : explode(',', $row['labels']);
                foreach ($row['labels'] as $v) {
                    if (isset($context['labels'][(int) $v])) {
                        $context['message_labels'][$row['ID_PM']][(int) $v] = array('id' => $v, 'name' => $context['labels'][(int) $v]['name']);
                    }
                }
            }
        }
        mysql_free_result($request);
        // Load any users....
        $posters = array_unique($posters);
        if (!empty($posters)) {
            loadMemberData($posters);
        }
        // Execute the query!
        $messages_request = db_query("\n\t\t\tSELECT pm.ID_PM, pm.subject, pm.ID_MEMBER_FROM, pm.body, pm.msgtime, pm.fromName\n\t\t\tFROM {$db_prefix}personal_messages AS pm" . ($context['folder'] == 'outbox' ? "\n\t\t\t\tLEFT JOIN {$db_prefix}pm_recipients AS pmr ON (pmr.ID_PM = pm.ID_PM)" : '') . ($context['sort_by'] == 'name' ? "\n\t\t\t\tLEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = " . ($context['folder'] == 'outbox' ? 'pmr.ID_MEMBER' : 'pm.ID_MEMBER_FROM') . ")" : '') . "\n\t\t\tWHERE pm.ID_PM IN (" . implode(',', $pms) . ")" . ($context['folder'] == 'outbox' ? "\n\t\t\tGROUP BY pm.ID_PM" : '') . "\n\t\t\tORDER BY {$_GET['sort']} " . ($descending ? ' DESC' : ' ASC') . "\n\t\t\tLIMIT " . count($pms), __FILE__, __LINE__);
    } else {
        $messages_request = false;
    }
    $context['can_send_pm'] = allowedTo('pm_send');
    if (!WIRELESS) {
        $context['sub_template'] = 'folder';
    }
    $context['page_title'] = $txt[143];
}
Exemple #2
0
/**
 * A folder, ie. inbox/sent etc.
 */
function MessageFolder()
{
    global $txt, $scripturl, $modSettings, $context, $subjects_request;
    global $messages_request, $user_info, $recipients, $options, $smcFunc, $memberContext, $user_settings;
    // Changing view?
    if (isset($_GET['view'])) {
        $context['display_mode'] = $context['display_mode'] > 1 ? 0 : $context['display_mode'] + 1;
        updateMemberData($user_info['id'], array('pm_prefs' => $user_settings['pm_prefs'] & 252 | $context['display_mode']));
    }
    // Make sure the starting location is valid.
    if (isset($_GET['start']) && $_GET['start'] != 'new') {
        $_GET['start'] = (int) $_GET['start'];
    } elseif (!isset($_GET['start']) && !empty($options['view_newest_pm_first'])) {
        $_GET['start'] = 0;
    } else {
        $_GET['start'] = 'new';
    }
    // Set up some basic theme stuff.
    $context['from_or_to'] = $context['folder'] != 'sent' ? 'from' : 'to';
    $context['get_pmessage'] = 'prepareMessageContext';
    $context['signature_enabled'] = substr($modSettings['signature_settings'], 0, 1) == 1;
    $context['disabled_fields'] = isset($modSettings['disabled_profile_fields']) ? array_flip(explode(',', $modSettings['disabled_profile_fields'])) : array();
    $labelQuery = $context['folder'] != 'sent' ? '
			AND FIND_IN_SET(' . $context['current_label_id'] . ', pmr.labels) != 0' : '';
    // Set the index bar correct!
    messageIndexBar($context['current_label_id'] == -1 ? $context['folder'] : 'label' . $context['current_label_id']);
    // Sorting the folder.
    $sort_methods = array('date' => 'pm.id_pm', 'name' => 'IFNULL(mem.real_name, \'\')', 'subject' => 'pm.subject');
    // They didn't pick one, use the forum default.
    if (!isset($_GET['sort']) || !isset($sort_methods[$_GET['sort']])) {
        $context['sort_by'] = 'date';
        $_GET['sort'] = 'pm.id_pm';
        // An overriding setting?
        $descending = !empty($options['view_newest_pm_first']);
    } else {
        $context['sort_by'] = $_GET['sort'];
        $_GET['sort'] = $sort_methods[$_GET['sort']];
        $descending = isset($_GET['desc']);
    }
    $context['sort_direction'] = $descending ? 'down' : 'up';
    // Set the text to resemble the current folder.
    $pmbox = $context['folder'] != 'sent' ? $txt['inbox'] : $txt['sent_items'];
    $txt['delete_all'] = str_replace('PMBOX', $pmbox, $txt['delete_all']);
    // Now, build the link tree!
    if ($context['current_label_id'] == -1) {
        $context['linktree'][] = array('url' => $scripturl . '?action=pm;f=' . $context['folder'], 'name' => $pmbox);
    }
    // Build it further for a label.
    if ($context['current_label_id'] != -1) {
        $context['linktree'][] = array('url' => $scripturl . '?action=pm;f=' . $context['folder'] . ';l=' . $context['current_label_id'], 'name' => $txt['pm_current_label'] . ': ' . $context['current_label']);
    }
    // Figure out how many messages there are.
    if ($context['folder'] == 'sent') {
        $request = $smcFunc['db_query']('', '
			SELECT COUNT(' . ($context['display_mode'] == 2 ? 'DISTINCT pm.id_pm_head' : '*') . ')
			FROM {db_prefix}personal_messages AS pm
			WHERE pm.id_member_from = {int:current_member}
				AND pm.deleted_by_sender = {int:not_deleted}', array('current_member' => $user_info['id'], 'not_deleted' => 0));
    } else {
        $request = $smcFunc['db_query']('', '
			SELECT COUNT(' . ($context['display_mode'] == 2 ? 'DISTINCT pm.id_pm_head' : '*') . ')
			FROM {db_prefix}pm_recipients AS pmr' . ($context['display_mode'] == 2 ? '
				INNER JOIN {db_prefix}personal_messages AS pm ON (pm.id_pm = pmr.id_pm)' : '') . '
			WHERE pmr.id_member = {int:current_member}
				AND pmr.deleted = {int:not_deleted}' . $labelQuery, array('current_member' => $user_info['id'], 'not_deleted' => 0));
    }
    list($max_messages) = $smcFunc['db_fetch_row']($request);
    $smcFunc['db_free_result']($request);
    // Only show the button if there are messages to delete.
    $context['show_delete'] = $max_messages > 0;
    // Start on the last page.
    if (!is_numeric($_GET['start']) || $_GET['start'] >= $max_messages) {
        $_GET['start'] = $max_messages - 1 - ($max_messages - 1) % $modSettings['defaultMaxMessages'];
    } elseif ($_GET['start'] < 0) {
        $_GET['start'] = 0;
    }
    // ... but wait - what if we want to start from a specific message?
    if (isset($_GET['pmid'])) {
        $pmID = (int) $_GET['pmid'];
        // Make sure you have access to this PM.
        if (!isAccessiblePM($pmID, $context['folder'] == 'sent' ? 'outbox' : 'inbox')) {
            fatal_lang_error('no_access', false);
        }
        $context['current_pm'] = $pmID;
        // With only one page of PM's we're gonna want page 1.
        if ($max_messages <= $modSettings['defaultMaxMessages']) {
            $_GET['start'] = 0;
        } elseif (!isset($_GET['kstart'])) {
            if ($context['folder'] == 'sent') {
                $request = $smcFunc['db_query']('', '
					SELECT COUNT(' . ($context['display_mode'] == 2 ? 'DISTINCT pm.id_pm_head' : '*') . ')
					FROM {db_prefix}personal_messages
					WHERE id_member_from = {int:current_member}
						AND deleted_by_sender = {int:not_deleted}
						AND id_pm ' . ($descending ? '>' : '<') . ' {int:id_pm}', array('current_member' => $user_info['id'], 'not_deleted' => 0, 'id_pm' => $pmID));
            } else {
                $request = $smcFunc['db_query']('', '
					SELECT COUNT(' . ($context['display_mode'] == 2 ? 'DISTINCT pm.id_pm_head' : '*') . ')
					FROM {db_prefix}pm_recipients AS pmr' . ($context['display_mode'] == 2 ? '
						INNER JOIN {db_prefix}personal_messages AS pm ON (pm.id_pm = pmr.id_pm)' : '') . '
					WHERE pmr.id_member = {int:current_member}
						AND pmr.deleted = {int:not_deleted}' . $labelQuery . '
						AND pmr.id_pm ' . ($descending ? '>' : '<') . ' {int:id_pm}', array('current_member' => $user_info['id'], 'not_deleted' => 0, 'id_pm' => $pmID));
            }
            list($_GET['start']) = $smcFunc['db_fetch_row']($request);
            $smcFunc['db_free_result']($request);
            // To stop the page index's being abnormal, start the page on the page the message would normally be located on...
            $_GET['start'] = $modSettings['defaultMaxMessages'] * (int) ($_GET['start'] / $modSettings['defaultMaxMessages']);
        }
    }
    // Sanitize and validate pmsg variable if set.
    if (isset($_GET['pmsg'])) {
        $pmsg = (int) $_GET['pmsg'];
        if (!isAccessiblePM($pmsg, $context['folder'] == 'sent' ? 'outbox' : 'inbox')) {
            fatal_lang_error('no_access', false);
        }
    }
    // Set up the page index.
    $context['page_index'] = constructPageIndex($scripturl . '?action=pm;f=' . $context['folder'] . (isset($_REQUEST['l']) ? ';l=' . (int) $_REQUEST['l'] : '') . ';sort=' . $context['sort_by'] . ($descending ? ';desc' : ''), $_GET['start'], $max_messages, $modSettings['defaultMaxMessages']);
    $context['start'] = $_GET['start'];
    // Determine the navigation context (especially useful for the wireless template).
    $context['links'] = array('first' => $_GET['start'] >= $modSettings['defaultMaxMessages'] ? $scripturl . '?action=pm;start=0' : '', 'prev' => $_GET['start'] >= $modSettings['defaultMaxMessages'] ? $scripturl . '?action=pm;start=' . ($_GET['start'] - $modSettings['defaultMaxMessages']) : '', 'next' => $_GET['start'] + $modSettings['defaultMaxMessages'] < $max_messages ? $scripturl . '?action=pm;start=' . ($_GET['start'] + $modSettings['defaultMaxMessages']) : '', 'last' => $_GET['start'] + $modSettings['defaultMaxMessages'] < $max_messages ? $scripturl . '?action=pm;start=' . floor(($max_messages - 1) / $modSettings['defaultMaxMessages']) * $modSettings['defaultMaxMessages'] : '', 'up' => $scripturl);
    $context['page_info'] = array('current_page' => $_GET['start'] / $modSettings['defaultMaxMessages'] + 1, 'num_pages' => floor(($max_messages - 1) / $modSettings['defaultMaxMessages']) + 1);
    // First work out what messages we need to see - if grouped is a little trickier...
    if ($context['display_mode'] == 2) {
        // On a non-default sort due to PostgreSQL we have to do a harder sort.
        if ($smcFunc['db_title'] == 'PostgreSQL' && $_GET['sort'] != 'pm.id_pm') {
            $sub_request = $smcFunc['db_query']('', '
				SELECT MAX({raw:sort}) AS sort_param, pm.id_pm_head
				FROM {db_prefix}personal_messages AS pm' . ($context['folder'] == 'sent' ? $context['sort_by'] == 'name' ? '
					LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)' : '' : '
					INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm
						AND pmr.id_member = {int:current_member}
						AND pmr.deleted = {int:not_deleted}
						' . $labelQuery . ')') . ($context['sort_by'] == 'name' ? '
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = {raw:id_member})' : '') . '
				WHERE ' . ($context['folder'] == 'sent' ? 'pm.id_member_from = {int:current_member}
					AND pm.deleted_by_sender = {int:not_deleted}' : '1=1') . (empty($pmsg) ? '' : '
					AND pm.id_pm = {int:id_pm}') . '
				GROUP BY pm.id_pm_head
				ORDER BY sort_param' . ($descending ? ' DESC' : ' ASC') . (empty($pmsg) ? '
				LIMIT ' . $_GET['start'] . ', ' . $modSettings['defaultMaxMessages'] : ''), array('current_member' => $user_info['id'], 'not_deleted' => 0, 'id_member' => $context['folder'] == 'sent' ? 'pmr.id_member' : 'pm.id_member_from', 'id_pm' => isset($pmsg) ? $pmsg : '0', 'sort' => $_GET['sort']));
            $sub_pms = array();
            while ($row = $smcFunc['db_fetch_assoc']($sub_request)) {
                $sub_pms[$row['id_pm_head']] = $row['sort_param'];
            }
            $smcFunc['db_free_result']($sub_request);
            $request = $smcFunc['db_query']('', '
				SELECT pm.id_pm AS id_pm, pm.id_pm_head
				FROM {db_prefix}personal_messages AS pm' . ($context['folder'] == 'sent' ? $context['sort_by'] == 'name' ? '
					LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)' : '' : '
					INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm
						AND pmr.id_member = {int:current_member}
						AND pmr.deleted = {int:not_deleted}
						' . $labelQuery . ')') . ($context['sort_by'] == 'name' ? '
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = {raw:id_member})' : '') . '
				WHERE ' . (empty($sub_pms) ? '0=1' : 'pm.id_pm IN ({array_int:pm_list})') . '
				ORDER BY ' . ($_GET['sort'] == 'pm.id_pm' && $context['folder'] != 'sent' ? 'id_pm' : '{raw:sort}') . ($descending ? ' DESC' : ' ASC') . (empty($pmsg) ? '
				LIMIT ' . $_GET['start'] . ', ' . $modSettings['defaultMaxMessages'] : ''), array('current_member' => $user_info['id'], 'pm_list' => array_keys($sub_pms), 'not_deleted' => 0, 'sort' => $_GET['sort'], 'id_member' => $context['folder'] == 'sent' ? 'pmr.id_member' : 'pm.id_member_from'));
        } else {
            $request = $smcFunc['db_query']('pm_conversation_list', '
				SELECT MAX(pm.id_pm) AS id_pm, pm.id_pm_head
				FROM {db_prefix}personal_messages AS pm' . ($context['folder'] == 'sent' ? $context['sort_by'] == 'name' ? '
					LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)' : '' : '
					INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm
						AND pmr.id_member = {int:current_member}
						AND pmr.deleted = {int:deleted_by}
						' . $labelQuery . ')') . ($context['sort_by'] == 'name' ? '
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = {raw:pm_member})' : '') . '
				WHERE ' . ($context['folder'] == 'sent' ? 'pm.id_member_from = {int:current_member}
					AND pm.deleted_by_sender = {int:deleted_by}' : '1=1') . (empty($pmsg) ? '' : '
					AND pm.id_pm = {int:pmsg}') . '
				GROUP BY pm.id_pm_head
				ORDER BY ' . ($_GET['sort'] == 'pm.id_pm' && $context['folder'] != 'sent' ? 'id_pm' : '{raw:sort}') . ($descending ? ' DESC' : ' ASC') . (empty($_GET['pmsg']) ? '
				LIMIT ' . $_GET['start'] . ', ' . $modSettings['defaultMaxMessages'] : ''), array('current_member' => $user_info['id'], 'deleted_by' => 0, 'sort' => $_GET['sort'], 'pm_member' => $context['folder'] == 'sent' ? 'pmr.id_member' : 'pm.id_member_from', 'pmsg' => isset($pmsg) ? (int) $pmsg : 0));
        }
    } else {
        // @todo SLOW This query uses a filesort. (inbox only.)
        $request = $smcFunc['db_query']('', '
			SELECT pm.id_pm, pm.id_pm_head, pm.id_member_from
			FROM {db_prefix}personal_messages AS pm' . ($context['folder'] == 'sent' ? '' . ($context['sort_by'] == 'name' ? '
				LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)' : '') : '
				INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm
					AND pmr.id_member = {int:current_member}
					AND pmr.deleted = {int:is_deleted}
					' . $labelQuery . ')') . ($context['sort_by'] == 'name' ? '
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = {raw:pm_member})' : '') . '
			WHERE ' . ($context['folder'] == 'sent' ? 'pm.id_member_from = {raw:current_member}
				AND pm.deleted_by_sender = {int:is_deleted}' : '1=1') . (empty($pmsg) ? '' : '
				AND pm.id_pm = {int:pmsg}') . '
			ORDER BY ' . ($_GET['sort'] == 'pm.id_pm' && $context['folder'] != 'sent' ? 'pmr.id_pm' : '{raw:sort}') . ($descending ? ' DESC' : ' ASC') . (empty($pmsg) ? '
			LIMIT ' . $_GET['start'] . ', ' . $modSettings['defaultMaxMessages'] : ''), array('current_member' => $user_info['id'], 'is_deleted' => 0, 'sort' => $_GET['sort'], 'pm_member' => $context['folder'] == 'sent' ? 'pmr.id_member' : 'pm.id_member_from', 'pmsg' => isset($pmsg) ? (int) $pmsg : 0));
    }
    // Load the id_pms and initialize recipients.
    $pms = array();
    $lastData = array();
    $posters = $context['folder'] == 'sent' ? array($user_info['id']) : array();
    $recipients = array();
    while ($row = $smcFunc['db_fetch_assoc']($request)) {
        if (!isset($recipients[$row['id_pm']])) {
            if (isset($row['id_member_from'])) {
                $posters[$row['id_pm']] = $row['id_member_from'];
            }
            $pms[$row['id_pm']] = $row['id_pm'];
            $recipients[$row['id_pm']] = array('to' => array(), 'bcc' => array());
        }
        // Keep track of the last message so we know what the head is without another query!
        if (empty($pmID) && (empty($options['view_newest_pm_first']) || !isset($lastData)) || empty($lastData) || !empty($pmID) && $pmID == $row['id_pm']) {
            $lastData = array('id' => $row['id_pm'], 'head' => $row['id_pm_head']);
        }
    }
    $smcFunc['db_free_result']($request);
    // Make sure that we have been given a correct head pm id!
    if ($context['display_mode'] == 2 && !empty($pmID) && $pmID != $lastData['id']) {
        fatal_lang_error('no_access', false);
    }
    if (!empty($pms)) {
        // Select the correct current message.
        if (empty($pmID)) {
            $context['current_pm'] = $lastData['id'];
        }
        // This is a list of the pm's that are used for "full" display.
        if ($context['display_mode'] == 0) {
            $display_pms = $pms;
        } else {
            $display_pms = array($context['current_pm']);
        }
        // At this point we know the main id_pm's. But - if we are looking at conversations we need the others!
        if ($context['display_mode'] == 2) {
            $request = $smcFunc['db_query']('', '
				SELECT pm.id_pm, pm.id_member_from, pm.deleted_by_sender, pmr.id_member, pmr.deleted
				FROM {db_prefix}personal_messages AS pm
					INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)
				WHERE pm.id_pm_head = {int:id_pm_head}
					AND ((pm.id_member_from = {int:current_member} AND pm.deleted_by_sender = {int:not_deleted})
						OR (pmr.id_member = {int:current_member} AND pmr.deleted = {int:not_deleted}))
				ORDER BY pm.id_pm', array('current_member' => $user_info['id'], 'id_pm_head' => $lastData['head'], 'not_deleted' => 0));
            while ($row = $smcFunc['db_fetch_assoc']($request)) {
                // This is, frankly, a joke. We will put in a workaround for people sending to themselves - yawn!
                if ($context['folder'] == 'sent' && $row['id_member_from'] == $user_info['id'] && $row['deleted_by_sender'] == 1) {
                    continue;
                } elseif ($row['id_member'] == $user_info['id'] & $row['deleted'] == 1) {
                    continue;
                }
                if (!isset($recipients[$row['id_pm']])) {
                    $recipients[$row['id_pm']] = array('to' => array(), 'bcc' => array());
                }
                $display_pms[] = $row['id_pm'];
                $posters[$row['id_pm']] = $row['id_member_from'];
            }
            $smcFunc['db_free_result']($request);
        }
        // This is pretty much EVERY pm!
        $all_pms = array_merge($pms, $display_pms);
        $all_pms = array_unique($all_pms);
        // Get recipients (don't include bcc-recipients for your inbox, you're not supposed to know :P).
        $request = $smcFunc['db_query']('', '
			SELECT pmr.id_pm, mem_to.id_member AS id_member_to, mem_to.real_name AS to_name, pmr.bcc, pmr.labels, pmr.is_read
			FROM {db_prefix}pm_recipients AS pmr
				LEFT JOIN {db_prefix}members AS mem_to ON (mem_to.id_member = pmr.id_member)
			WHERE pmr.id_pm IN ({array_int:pm_list})', array('pm_list' => $all_pms));
        $context['message_labels'] = array();
        $context['message_replied'] = array();
        $context['message_unread'] = array();
        while ($row = $smcFunc['db_fetch_assoc']($request)) {
            if ($context['folder'] == 'sent' || empty($row['bcc'])) {
                $recipients[$row['id_pm']][empty($row['bcc']) ? 'to' : 'bcc'][] = empty($row['id_member_to']) ? $txt['guest_title'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member_to'] . '">' . $row['to_name'] . '</a>';
            }
            if ($row['id_member_to'] == $user_info['id'] && $context['folder'] != 'sent') {
                $context['message_replied'][$row['id_pm']] = $row['is_read'] & 2;
                $context['message_unread'][$row['id_pm']] = $row['is_read'] == 0;
                $row['labels'] = $row['labels'] == '' ? array() : explode(',', $row['labels']);
                foreach ($row['labels'] as $v) {
                    if (isset($context['labels'][(int) $v])) {
                        $context['message_labels'][$row['id_pm']][(int) $v] = array('id' => $v, 'name' => $context['labels'][(int) $v]['name']);
                    }
                }
            }
        }
        $smcFunc['db_free_result']($request);
        // Make sure we don't load unnecessary data.
        if ($context['display_mode'] == 1) {
            foreach ($posters as $k => $v) {
                if (!in_array($k, $display_pms)) {
                    unset($posters[$k]);
                }
            }
        }
        // Load any users....
        $posters = array_unique($posters);
        if (!empty($posters)) {
            loadMemberData($posters);
        }
        // If we're on grouped/restricted view get a restricted list of messages.
        if ($context['display_mode'] != 0) {
            // Get the order right.
            $orderBy = array();
            foreach (array_reverse($pms) as $pm) {
                $orderBy[] = 'pm.id_pm = ' . $pm;
            }
            // Seperate query for these bits!
            $subjects_request = $smcFunc['db_query']('', '
				SELECT pm.id_pm, pm.subject, pm.id_member_from, pm.msgtime, IFNULL(mem.real_name, pm.from_name) AS from_name,
					IFNULL(mem.id_member, 0) AS not_guest
				FROM {db_prefix}personal_messages AS pm
					LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = pm.id_member_from)
				WHERE pm.id_pm IN ({array_int:pm_list})
				ORDER BY ' . implode(', ', $orderBy) . '
				LIMIT ' . count($pms), array('pm_list' => $pms));
        }
        // Execute the query!
        $messages_request = $smcFunc['db_query']('', '
			SELECT pm.id_pm, pm.subject, pm.id_member_from, pm.body, pm.msgtime, pm.from_name
			FROM {db_prefix}personal_messages AS pm' . ($context['folder'] == 'sent' ? '
				LEFT JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)' : '') . ($context['sort_by'] == 'name' ? '
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = {raw:id_member})' : '') . '
			WHERE pm.id_pm IN ({array_int:display_pms})' . ($context['folder'] == 'sent' ? '
			GROUP BY pm.id_pm, pm.subject, pm.id_member_from, pm.body, pm.msgtime, pm.from_name' : '') . '
			ORDER BY ' . ($context['display_mode'] == 2 ? 'pm.id_pm' : $_GET['sort']) . ($descending ? ' DESC' : ' ASC') . '
			LIMIT ' . count($display_pms), array('display_pms' => $display_pms, 'id_member' => $context['folder'] == 'sent' ? 'pmr.id_member' : 'pm.id_member_from'));
    } else {
        $messages_request = false;
    }
    $context['can_send_pm'] = allowedTo('pm_send');
    $context['can_send_email'] = allowedTo('send_email_to_members');
    if (!WIRELESS) {
        $context['sub_template'] = 'folder';
    }
    $context['page_title'] = $txt['pm_inbox'];
    // Finally mark the relevant messages as read.
    if ($context['folder'] != 'sent' && !empty($context['labels'][(int) $context['current_label_id']]['unread_messages'])) {
        // If the display mode is "old sk00l" do them all...
        if ($context['display_mode'] == 0) {
            markMessages(null, $context['current_label_id']);
        } elseif (!empty($context['current_pm'])) {
            markMessages($display_pms, $context['current_label_id']);
        }
    }
    // Build the conversation button array.
    if ($context['display_mode'] == 2) {
        $context['conversation_buttons'] = array('reply' => array('text' => 'reply_to_all', 'image' => 'reply.png', 'lang' => true, 'url' => $scripturl . '?action=pm;sa=send;f=' . $context['folder'] . ($context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '') . ';pmsg=' . $context['current_pm'] . ';u=all', 'active' => true), 'delete' => array('text' => 'delete_conversation', 'image' => 'delete.png', 'lang' => true, 'url' => $scripturl . '?action=pm;sa=pmactions;pm_actions[' . $context['current_pm'] . ']=delete;conversation;f=' . $context['folder'] . ';start=' . $context['start'] . ($context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '') . ';' . $context['session_var'] . '=' . $context['session_id'], 'custom' => 'onclick="return confirm(\'' . addslashes($txt['remove_message']) . '?\');"'));
        // Allow mods to add additional buttons here
        call_integration_hook('integrate_conversation_buttons');
    }
}
 /**
  * This is the main function of personal messages, called before the action handler.
  *
  * What it does:
  * - PersonalMessages is a menu-based controller.
  * - It sets up the menu.
  * - Calls from the menu the appropriate method/function for the current area.
  *
  * @see Action_Controller::action_index()
  */
 public function action_index()
 {
     global $context;
     require_once SUBSDIR . '/Action.class.php';
     // Finally all the things we know how to do
     $subActions = array('manlabels' => array($this, 'action_manlabels', 'permission' => 'pm_read'), 'manrules' => array($this, 'action_manrules', 'permission' => 'pm_read'), 'markunread' => array($this, 'action_markunread', 'permission' => 'pm_read'), 'pmactions' => array($this, 'action_pmactions', 'permission' => 'pm_read'), 'prune' => array($this, 'action_prune', 'permission' => 'pm_read'), 'removeall' => array($this, 'action_removeall', 'permission' => 'pm_read'), 'removeall2' => array($this, 'action_removeall2', 'permission' => 'pm_read'), 'report' => array($this, 'action_report', 'permission' => 'pm_read'), 'search' => array($this, 'action_search', 'permission' => 'pm_read'), 'search2' => array($this, 'action_search2', 'permission' => 'pm_read'), 'send' => array($this, 'action_send', 'permission' => 'pm_read'), 'send2' => array($this, 'action_send2', 'permission' => 'pm_read'), 'settings' => array($this, 'action_settings', 'permission' => 'pm_read'), 'showpmdrafts' => array('dir' => CONTROLLERDIR, 'file' => 'Draft.controller.php', 'controller' => 'Draft_Controller', 'function' => 'action_showPMDrafts', 'permission' => 'pm_read'), 'inbox' => array($this, 'action_folder', 'permission' => 'pm_read'));
     // Set up our action array
     $action = new Action();
     // Known action, go to it, otherwise the inbox for you
     $subAction = $action->initialize($subActions, 'inbox');
     // Set the right index bar for the action
     if ($subAction === 'inbox') {
         messageIndexBar($context['current_label_id'] == -1 ? $context['folder'] : 'label' . $context['current_label_id']);
     } elseif (!isset($_REQUEST['xml'])) {
         messageIndexBar($subAction);
     }
     // And off we go!
     $action->dispatch($subAction);
 }