use wcf\data\conversation\label\ConversationLabelList;
use wcf\data\conversation\UserConversationList;
use wcf\system\clipboard\ClipboardHandler;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\IllegalLinkException;
use wcf\system\page\PageLocationManager;
+use wcf\system\request\LinkHandler;
use wcf\system\WCF;
use wcf\util\ArrayUtil;
+use wcf\util\HeaderUtil;
/**
* Shows a list of conversations.
*
* @author Marcel Werk
- * @copyright 2001-2018 WoltLab GmbH
+ * @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package WoltLabSuite\Core\Page
*
// labels
$this->labelList = ConversationLabel::getLabelsByUser();
- if (isset($_REQUEST['labelID'])) {
+ if (!empty($_REQUEST['labelID'])) {
$this->labelID = intval($_REQUEST['labelID']);
$validLabel = false;
}
}
- if (isset($_REQUEST['participants'])) $this->participants = ArrayUtil::trim(explode(',', $_REQUEST['participants']));
+ if (isset($_REQUEST['participants'])) $this->participants = array_slice(ArrayUtil::trim(explode(',', $_REQUEST['participants'])), 0, 20);
+
+ if (!empty($_POST)) {
+ $participantsParameter = '';
+ foreach ($this->participants as $participant) {
+ if (!empty($participantsParameter)) $participantsParameter .= ',';
+ $participantsParameter .= \rawurlencode($participant);
+ }
+ if (!empty($participantsParameter)) {
+ $participantsParameter = '&participants=' . $participantsParameter;
+ }
+
+ HeaderUtil::redirect(LinkHandler::getInstance()->getLink('ConversationList', [], 'sortField='.$this->sortField.'&sortOrder='.$this->sortOrder.'&filter='.$this->filter.'&labelID='.$this->labelID.'&pageNo='.$this->pageNo.$participantsParameter));
+ exit;
+ }
}
/** @noinspection PhpMissingParentCallCommonInspection */
$this->objectList->setLabelList($this->labelList);
if (!empty($this->participants)) {
- $this->objectList->getConditionBuilder()->add('conversation.conversationID IN (SELECT conversationID FROM wcf'.WCF_N.'_conversation_to_user WHERE username IN (?) GROUP BY conversationID HAVING COUNT(conversationID) = ?)', [
- $this->participants,
- count($this->participants)
- ]);
+ // The column `conversation_to_user.username` has no index, causing full table scans when
+ // trying to filter by it, therefore we'll read the user ids in advance.
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add('username IN (?)', [$this->participants]);
+ $sql = "SELECT userID
+ FROM wcf".WCF_N."_user
+ ".$conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ $userIDs = [];
+ while ($userID = $statement->fetchColumn()) {
+ $userIDs[] = $userID;
+ }
+
+ if (!empty($userIDs)) {
+ // The condition is split into two branches in order to account for invisible participants.
+ // Invisible participants are only visible to the conversation starter and remain invisible
+ // until the write their first message.
+ //
+ // We need to protect these users from being exposed as participants by including them for
+ // any conversation that the current user has started. For all other conversations, users
+ // flagged with `isInvisible = 0` must be excluded.
+ //
+ // See https://github.com/WoltLab/com.woltlab.wcf.conversation/issues/131
+ $this->objectList->getConditionBuilder()->add('
+ (
+ (
+ conversation.userID = ?
+ AND
+ conversation.conversationID IN (
+ SELECT conversationID
+ FROM wcf'.WCF_N.'_conversation_to_user
+ WHERE participantID IN (?)
+ GROUP BY conversationID
+ HAVING COUNT(conversationID) = ?
+ )
+ )
+ OR
+ (
+ conversation.userID <> ?
+ AND
+ conversation.conversationID IN (
+ SELECT conversationID
+ FROM wcf'.WCF_N.'_conversation_to_user
+ WHERE participantID IN (?)
+ AND isInvisible = ?
+ GROUP BY conversationID
+ HAVING COUNT(conversationID) = ?
+ )
+ )
+ )', [
+ // Parameters for the first condition.
+ WCF::getUser()->userID,
+ $userIDs,
+ count($userIDs),
+
+ // Parameters for the second condition.
+ WCF::getUser()->userID,
+ $userIDs,
+ 0,
+ count($userIDs),
+ ]);
+ }
}
}
'draftCount' => $this->draftCount,
'hiddenCount' => $this->hiddenCount,
'outboxCount' => $this->outboxCount,
- 'participants' => $this->participants
+ 'participants' => $this->participants,
+ 'validSortFields' => $this->validSortFields,
]);
}
}