3 namespace wcf\data\conversation
;
5 use wcf\data\conversation\label\ConversationLabel
;
6 use wcf\data\conversation\label\ConversationLabelList
;
7 use wcf\system\cache\runtime\UserProfileRuntimeCache
;
8 use wcf\system\database\util\PreparedStatementConditionBuilder
;
12 * Represents a list of conversations.
15 * @copyright 2001-2019 WoltLab GmbH
16 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
17 * @package WoltLabSuite\Core\Data\Conversation
19 * @method ViewableConversation current()
20 * @method ViewableConversation[] getObjects()
21 * @method ViewableConversation|null search($objectID)
22 * @property ViewableConversation[] $objects
24 class UserConversationList
extends ConversationList
27 * list of available filters
30 public static $availableFilters = ['hidden', 'draft', 'outbox'];
40 * @var ConversationLabelList
47 public $decoratorClassName = ViewableConversation
::class;
50 * Creates a new UserConversationList
53 * @param string $filter
56 public function __construct($userID, $filter = '', $labelID = 0)
58 parent
::__construct();
60 $this->filter
= $filter;
63 if ($this->filter
=== 'draft') {
64 $this->getConditionBuilder()->add('conversation.userID = ?', [$userID]);
65 $this->getConditionBuilder()->add('conversation.isDraft = 1');
67 $this->getConditionBuilder()->add('conversation_to_user.participantID = ?', [$userID]);
68 $this->getConditionBuilder()
69 ->add('conversation_to_user.hideConversation = ?', [$this->filter
== 'hidden' ?
1 : 0]);
70 $this->sqlConditionJoins
= "LEFT JOIN wcf" . WCF_N
. "_conversation conversation ON (conversation.conversationID = conversation_to_user.conversationID)";
71 if ($this->filter
== 'outbox') {
72 $this->getConditionBuilder()->add('conversation.userID = ?', [$userID]);
78 $this->getConditionBuilder()->add("conversation.conversationID IN (
80 FROM wcf" . WCF_N
. "_conversation_label_to_object
86 $this->sqlSelects
= "DISTINCT conversation_message.userID AS ownPosts";
87 $this->sqlJoins
= "LEFT JOIN wcf" . WCF_N
. "_conversation_message conversation_message ON (conversation_message.conversationID = conversation.conversationID AND conversation_message.userID = " . $userID . ")";
90 if (!empty($this->sqlSelects
)) {
91 $this->sqlSelects
.= ',';
93 $this->sqlSelects
.= "conversation_to_user.*";
94 $this->sqlJoins
.= "LEFT JOIN wcf" . WCF_N
. "_conversation_to_user conversation_to_user ON (conversation_to_user.participantID = " . $userID . " AND conversation_to_user.conversationID = conversation.conversationID)";
96 if ($this->filter
!== 'draft') {
97 $this->sqlSelects
.= ", conversation.*, CASE WHEN conversation_to_user.leftAt <> 0 THEN conversation_to_user.leftAt ELSE conversation.lastPostTime END AS lastPostTime";
98 // this avoids appending `conversation.*` to the SELECT list
99 $this->useQualifiedShorthand
= false;
104 * Sets the label list of the user the conversations belong to.
106 * @param ConversationLabelList $labelList
108 public function setLabelList(ConversationLabelList
$labelList)
110 $this->labelList
= $labelList;
116 public function countObjects()
118 if ($this->filter
== 'draft') {
119 return parent
::countObjects();
122 $sql = "SELECT COUNT(*) AS count
123 FROM wcf" . WCF_N
. "_conversation_to_user conversation_to_user
124 " . $this->sqlConditionJoins
. "
125 " . $this->getConditionBuilder();
126 $statement = WCF
::getDB()->prepareStatement($sql);
127 $statement->execute($this->getConditionBuilder()->getParameters());
128 $row = $statement->fetchArray();
130 return $row['count'];
136 public function readObjectIDs()
138 if ($this->filter
=== 'draft') {
139 parent
::readObjectIDs();
144 $sql = "SELECT conversation_to_user.conversationID AS objectID
145 FROM wcf" . WCF_N
. "_conversation_to_user conversation_to_user
146 " . $this->sqlConditionJoins
. "
147 " . $this->getConditionBuilder() . "
148 " . (!empty($this->sqlOrderBy
) ?
"ORDER BY " . $this->sqlOrderBy
: '');
149 $statement = WCF
::getDB()->prepareStatement($sql, $this->sqlLimit
, $this->sqlOffset
);
150 $statement->execute($this->getConditionBuilder()->getParameters());
151 $this->objectIDs
= $statement->fetchAll(\PDO
::FETCH_COLUMN
);
157 public function readObjects()
159 if ($this->objectIDs
=== null) {
160 $this->readObjectIDs();
163 parent
::readObjects();
165 if (!empty($this->objects
)) {
167 foreach ($this->objects
as $conversation) {
168 if ($conversation->lastMessageID
) {
169 $messageIDs[] = $conversation->lastMessageID
;
172 if (!empty($messageIDs)) {
173 $conditions = new PreparedStatementConditionBuilder();
174 $conditions->add("messageID IN (?)", [$messageIDs]);
175 $sql = "SELECT messageID, userID, username, time
176 FROM wcf" . WCF_N
. "_conversation_message
178 $statement = WCF
::getDB()->prepareStatement($sql);
179 $statement->execute($conditions->getParameters());
181 while ($row = $statement->fetchArray()) {
182 $messageData[$row['messageID']] = $row;
185 foreach ($this->objects
as $conversation) {
186 if ($conversation->lastMessageID
) {
187 $data = (isset($messageData[$conversation->lastMessageID
])) ?
$messageData[$conversation->lastMessageID
] : null;
188 if ($data !== null) {
189 $conversation->setLastMessage($data['userID'], $data['username'], $data['time']);
191 $conversation->setLastMessage(null, '', 0);
197 $labels = $this->loadLabelAssignments();
200 foreach ($this->objects
as $conversationID => $conversation) {
201 if (isset($labels[$conversationID])) {
202 foreach ($labels[$conversationID] as $label) {
203 $conversation->assignLabel($label);
207 if ($conversation->userID
) {
208 $userIDs[] = $conversation->userID
;
210 if ($conversation->lastPosterID
) {
211 $userIDs[] = $conversation->lastPosterID
;
215 if (!empty($userIDs)) {
216 UserProfileRuntimeCache
::getInstance()->cacheObjectIDs($userIDs);
222 * Returns a list of conversation labels.
224 * @return ConversationLabel[]
226 protected function getLabels()
228 if ($this->labelList
=== null) {
229 $this->labelList
= ConversationLabel
::getLabelsByUser();
232 return $this->labelList
->getObjects();
236 * Returns label assignments per conversation.
238 * @return ConversationLabel[][]
240 protected function loadLabelAssignments()
242 $labels = $this->getLabels();
243 if (empty($labels)) {
247 $conditions = new PreparedStatementConditionBuilder();
248 $conditions->add("conversationID IN (?)", [\array_keys
($this->objects
)]);
249 $conditions->add("labelID IN (?)", [\array_keys
($labels)]);
251 $sql = "SELECT labelID, conversationID
252 FROM wcf" . WCF_N
. "_conversation_label_to_object
254 $statement = WCF
::getDB()->prepareStatement($sql);
255 $statement->execute($conditions->getParameters());
257 while ($row = $statement->fetchArray()) {
258 if (!isset($data[$row['conversationID']])) {
259 $data[$row['conversationID']] = [];
262 $data[$row['conversationID']][$row['labelID']] = $labels[$row['labelID']];