2 namespace wcf\data\conversation
;
3 use wcf\data\conversation\label\ConversationLabel
;
4 use wcf\data\conversation\label\ConversationLabelList
;
5 use wcf\system\cache\runtime\UserProfileRuntimeCache
;
6 use wcf\system\database\util\PreparedStatementConditionBuilder
;
10 * Represents a list of conversations.
13 * @copyright 2001-2019 WoltLab GmbH
14 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
15 * @package WoltLabSuite\Core\Data\Conversation
17 * @method ViewableConversation current()
18 * @method ViewableConversation[] getObjects()
19 * @method ViewableConversation|null search($objectID)
20 * @property ViewableConversation[] $objects
22 class UserConversationList
extends ConversationList
{
24 * list of available filters
27 public static $availableFilters = ['hidden', 'draft', 'outbox'];
37 * @var ConversationLabelList
44 public $decoratorClassName = ViewableConversation
::class;
47 * Creates a new UserConversationList
49 * @param integer $userID
50 * @param string $filter
51 * @param integer $labelID
53 public function __construct($userID, $filter = '', $labelID = 0) {
54 parent
::__construct();
56 $this->filter
= $filter;
59 if ($this->filter
=== 'draft') {
60 $this->getConditionBuilder()->add('conversation.userID = ?', [$userID]);
61 $this->getConditionBuilder()->add('conversation.isDraft = 1');
64 $this->getConditionBuilder()->add('conversation_to_user.participantID = ?', [$userID]);
65 $this->getConditionBuilder()->add('conversation_to_user.hideConversation = ?', [$this->filter
== 'hidden' ?
1 : 0]);
66 $this->sqlConditionJoins
= "LEFT JOIN wcf".WCF_N
."_conversation conversation ON (conversation.conversationID = conversation_to_user.conversationID)";
67 if ($this->filter
== 'outbox') $this->getConditionBuilder()->add('conversation.userID = ?', [$userID]);
72 $this->getConditionBuilder()->add("conversation.conversationID IN (
74 FROM wcf".WCF_N
."_conversation_label_to_object
80 $this->sqlSelects
= "DISTINCT conversation_message.userID AS ownPosts";
81 $this->sqlJoins
= "LEFT JOIN wcf".WCF_N
."_conversation_message conversation_message ON (conversation_message.conversationID = conversation.conversationID AND conversation_message.userID = ".$userID.")";
84 if (!empty($this->sqlSelects
)) $this->sqlSelects
.= ',';
85 $this->sqlSelects
.= "conversation_to_user.*";
86 $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)";
88 if ($this->filter
!== 'draft') {
89 $this->sqlSelects
.= ", conversation.*, CASE WHEN conversation_to_user.leftAt <> 0 THEN conversation_to_user.leftAt ELSE conversation.lastPostTime END AS lastPostTime";
90 // this avoids appending `conversation.*` to the SELECT list
91 $this->useQualifiedShorthand
= false;
96 * Sets the label list of the user the conversations belong to.
98 * @param ConversationLabelList $labelList
100 public function setLabelList(ConversationLabelList
$labelList) {
101 $this->labelList
= $labelList;
107 public function countObjects() {
108 if ($this->filter
== 'draft') return parent
::countObjects();
110 $sql = "SELECT COUNT(*) AS count
111 FROM wcf".WCF_N
."_conversation_to_user conversation_to_user
112 ".$this->sqlConditionJoins
."
113 ".$this->getConditionBuilder()->__toString();
114 $statement = WCF
::getDB()->prepareStatement($sql);
115 $statement->execute($this->getConditionBuilder()->getParameters());
116 $row = $statement->fetchArray();
117 return $row['count'];
123 public function readObjectIDs() {
124 if ($this->filter
=== 'draft') {
125 parent
::readObjectIDs();
130 $sql = "SELECT conversation_to_user.conversationID AS objectID
131 FROM wcf".WCF_N
."_conversation_to_user conversation_to_user
132 ".$this->sqlConditionJoins
."
133 ".$this->getConditionBuilder()->__toString()."
134 ".(!empty($this->sqlOrderBy
) ?
"ORDER BY ".$this->sqlOrderBy
: '');
135 $statement = WCF
::getDB()->prepareStatement($sql, $this->sqlLimit
, $this->sqlOffset
);
136 $statement->execute($this->getConditionBuilder()->getParameters());
137 $this->objectIDs
= $statement->fetchAll(\PDO
::FETCH_COLUMN
);
143 public function readObjects() {
144 if ($this->objectIDs
=== null) {
145 $this->readObjectIDs();
148 parent
::readObjects();
150 if (!empty($this->objects
)) {
152 foreach ($this->objects
as $conversation) {
153 if ($conversation->lastMessageID
) {
154 $messageIDs[] = $conversation->lastMessageID
;
157 if (!empty($messageIDs)) {
158 $conditions = new PreparedStatementConditionBuilder();
159 $conditions->add("messageID IN (?)", [$messageIDs]);
160 $sql = "SELECT messageID, userID, username, time
161 FROM wcf".WCF_N
."_conversation_message
163 $statement = WCF
::getDB()->prepareStatement($sql);
164 $statement->execute($conditions->getParameters());
166 while ($row = $statement->fetchArray()) {
167 $messageData[$row['messageID']] = $row;
170 foreach ($this->objects
as $conversation) {
171 if ($conversation->lastMessageID
) {
172 $data = (isset($messageData[$conversation->lastMessageID
])) ?
$messageData[$conversation->lastMessageID
] : null;
173 if ($data !== null) {
174 $conversation->setLastMessage($data['userID'], $data['username'], $data['time']);
177 $conversation->setLastMessage(null, '', 0);
183 $labels = $this->loadLabelAssignments();
186 foreach ($this->objects
as $conversationID => $conversation) {
187 if (isset($labels[$conversationID])) {
188 foreach ($labels[$conversationID] as $label) {
189 $conversation->assignLabel($label);
193 if ($conversation->userID
) {
194 $userIDs[] = $conversation->userID
;
196 if ($conversation->lastPosterID
) {
197 $userIDs[] = $conversation->lastPosterID
;
201 if (!empty($userIDs)) {
202 UserProfileRuntimeCache
::getInstance()->cacheObjectIDs($userIDs);
208 * Returns a list of conversation labels.
210 * @return ConversationLabel[]
212 protected function getLabels() {
213 if ($this->labelList
=== null) {
214 $this->labelList
= ConversationLabel
::getLabelsByUser();
217 return $this->labelList
->getObjects();
221 * Returns label assignments per conversation.
223 * @return ConversationLabel[][]
225 protected function loadLabelAssignments() {
226 $labels = $this->getLabels();
227 if (empty($labels)) {
231 $conditions = new PreparedStatementConditionBuilder();
232 $conditions->add("conversationID IN (?)", [array_keys($this->objects
)]);
233 $conditions->add("labelID IN (?)", [array_keys($labels)]);
235 $sql = "SELECT labelID, conversationID
236 FROM wcf".WCF_N
."_conversation_label_to_object
238 $statement = WCF
::getDB()->prepareStatement($sql);
239 $statement->execute($conditions->getParameters());
241 while ($row = $statement->fetchArray()) {
242 if (!isset($data[$row['conversationID']])) {
243 $data[$row['conversationID']] = [];
246 $data[$row['conversationID']][$row['labelID']] = $labels[$row['labelID']];