Reformat SQL queries using spaces
[GitHub/WoltLab/com.woltlab.wcf.conversation.git] / files / lib / data / conversation / ConversationEditor.class.php
CommitLineData
9544b6b4 1<?php
fea86294 2
9544b6b4 3namespace wcf\data\conversation;
fea86294 4
c764783c 5use wcf\data\conversation\message\ConversationMessage;
9544b6b4 6use wcf\data\DatabaseObjectEditor;
363e6c08 7use wcf\system\database\util\PreparedStatementConditionBuilder;
9544b6b4
MW
8use wcf\system\WCF;
9
10/**
11 * Extends the conversation object with functions to create, update and delete conversations.
fea86294
TD
12 *
13 * @author Marcel Werk
14 * @copyright 2001-2019 WoltLab GmbH
15 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
16 * @package WoltLabSuite\Core\Data\Conversation
17 *
18 * @method static Conversation create(array $parameters = [])
19 * @method Conversation getDecoratedObject()
20 * @mixin Conversation
9544b6b4 21 */
fea86294
TD
22class ConversationEditor extends DatabaseObjectEditor
23{
24 /**
25 * @inheritDoc
26 */
27 protected static $baseClass = Conversation::class;
28
29 /**
30 * Adds a new message to this conversation.
31 *
32 * @param ConversationMessage $message
33 */
34 public function addMessage(ConversationMessage $message)
35 {
36 $this->update([
37 'lastPoster' => $message->username,
38 'lastPostTime' => $message->time,
39 'lastPosterID' => $message->userID,
40 'replies' => $this->replies + 1,
41 'attachments' => $this->attachments + $message->attachments,
42 ]);
43 }
44
45 /**
46 * Resets the participants of this conversation.
47 */
48 public function resetParticipants()
49 {
8fbd8b01
MS
50 $sql = "DELETE FROM wcf" . WCF_N . "_conversation_to_user
51 WHERE conversationID = ?
52 AND participantID <> ?";
fea86294
TD
53 $statement = WCF::getDB()->prepareStatement($sql);
54 $statement->execute([$this->conversationID, $this->userID]);
55 }
56
57 /**
58 * Updates the participants of this conversation.
59 *
60 * @param integer[] $participantIDs
61 * @param integer[] $invisibleParticipantIDs
62 * @param string $visibility
63 */
64 public function updateParticipants(array $participantIDs, array $invisibleParticipantIDs = [], $visibility = 'all')
65 {
66 $usernames = [];
67 if (!empty($participantIDs) || !empty($invisibleParticipantIDs)) {
68 $conditions = new PreparedStatementConditionBuilder();
69 $conditions->add("userID IN (?)", [\array_merge($participantIDs, $invisibleParticipantIDs)]);
70
8fbd8b01
MS
71 $sql = "SELECT userID, username
72 FROM wcf" . WCF_N . "_user
73 " . $conditions;
fea86294
TD
74 $statement = WCF::getDB()->prepareStatement($sql);
75 $statement->execute($conditions->getParameters());
76 while ($row = $statement->fetchArray()) {
77 $usernames[$row['userID']] = $row['username'];
78 }
79 }
80
81 if (!empty($participantIDs)) {
82 WCF::getDB()->beginTransaction();
8fbd8b01
MS
83 $sql = "INSERT INTO wcf" . WCF_N . "_conversation_to_user
84 (conversationID, participantID, username, isInvisible, joinedAt)
85 VALUES (?, ?, ?, ?, ?)
86 ON DUPLICATE KEY
87 UPDATE hideConversation = 0,
88 leftAt = 0,
89 leftByOwnChoice = 1";
fea86294
TD
90 $statement = WCF::getDB()->prepareStatement($sql);
91
92 foreach ($participantIDs as $userID) {
93 $statement->execute([
94 $this->conversationID,
95 $userID,
96 $usernames[$userID],
97 0,
98 ($visibility === 'all') ? 0 : TIME_NOW,
99 ]);
100 }
101 WCF::getDB()->commitTransaction();
102 }
103
104 if (!empty($invisibleParticipantIDs)) {
105 WCF::getDB()->beginTransaction();
8fbd8b01
MS
106 $sql = "INSERT INTO wcf" . WCF_N . "_conversation_to_user
107 (conversationID, participantID, username, isInvisible)
108 VALUES (?, ?, ?, ?)";
fea86294
TD
109 $statement = WCF::getDB()->prepareStatement($sql);
110
111 foreach ($invisibleParticipantIDs as $userID) {
112 $statement->execute([
113 $this->conversationID,
114 $userID,
115 $usernames[$userID],
116 1,
117 ]);
118 }
119 WCF::getDB()->commitTransaction();
120 }
121
122 $this->updateParticipantCount();
123 }
124
125 /**
126 * Updates participant count.
127 */
128 public function updateParticipantCount()
129 {
8fbd8b01
MS
130 $sql = "UPDATE wcf" . WCF_N . "_conversation conversation
131 SET participants = (
132 SELECT COUNT(*) AS count
133 FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
134 WHERE conversation_to_user.conversationID = conversation.conversationID
135 AND conversation_to_user.hideConversation <> ?
136 AND conversation_to_user.participantID <> ?
137 AND conversation_to_user.isInvisible = ?
138 )
139 WHERE conversation.conversationID = ?";
fea86294
TD
140 $statement = WCF::getDB()->prepareStatement($sql);
141 $statement->execute([
142 Conversation::STATE_LEFT,
143 $this->userID,
144 0,
145 $this->conversationID,
146 ]);
147 }
148
149 /**
150 * Updates the participant summary of this conversation.
151 */
152 public function updateParticipantSummary()
153 {
8fbd8b01
MS
154 $sql = "SELECT participantID AS userID, hideConversation, username
155 FROM wcf" . WCF_N . "_conversation_to_user
156 WHERE conversationID = ?
157 AND participantID <> ?
158 AND isInvisible = 0
159 ORDER BY username";
fea86294
TD
160 $statement = WCF::getDB()->prepareStatement($sql, 5);
161 $statement->execute([$this->conversationID, $this->userID]);
162
163 $this->update(['participantSummary' => \serialize($statement->fetchAll(\PDO::FETCH_ASSOC))]);
164 }
165
166 /**
167 * Removes a participant from this conversation.
168 *
169 * @param integer $userID
170 */
171 public function removeParticipant($userID)
172 {
173 $sql = "SELECT joinedAt
8fbd8b01
MS
174 FROM wcf" . WCF_N . "_conversation_to_user
175 WHERE conversationID = ?
176 AND participantID = ?";
fea86294
TD
177 $statement = WCF::getDB()->prepareStatement($sql, 1);
178 $statement->execute([$this->conversationID, $userID]);
179 $joinedAt = $statement->fetchSingleColumn();
180
181 $sql = "SELECT messageID
8fbd8b01
MS
182 FROM wcf" . WCF_N . "_conversation_message
183 WHERE conversationID = ?
184 AND time >= ?
185 AND time <= ?";
fea86294
TD
186 $statement = WCF::getDB()->prepareStatement($sql, 1);
187 $statement->execute([
188 $this->conversationID,
189 $joinedAt,
190 TIME_NOW,
191 ]);
192 $lastMessageID = $statement->fetchSingleColumn();
193
8fbd8b01
MS
194 $sql = "UPDATE wcf" . WCF_N . "_conversation_to_user
195 SET leftAt = ?,
196 lastMessageID = ?,
197 leftByOwnChoice = ?
198 WHERE conversationID = ?
199 AND participantID = ?";
fea86294
TD
200 $statement = WCF::getDB()->prepareStatement($sql);
201 $statement->execute([
202 TIME_NOW,
203 $lastMessageID ?: null,
204 0,
205 $this->conversationID,
206 $userID,
207 ]);
208
209 // decrease participant count unless it is the author
210 if ($userID != $this->userID) {
211 $this->updateCounters([
212 'participants' => -1,
213 ]);
214 }
215 }
216
217 /**
218 * Updates the first message of this conversation.
219 */
220 public function updateFirstMessage()
221 {
8fbd8b01
MS
222 $sql = "SELECT messageID
223 FROM wcf" . WCF_N . "_conversation_message
224 WHERE conversationID = ?
225 ORDER BY time ASC";
fea86294
TD
226 $statement = WCF::getDB()->prepareStatement($sql, 1);
227 $statement->execute([
228 $this->conversationID,
229 ]);
230
231 $this->update([
232 'firstMessageID' => $statement->fetchColumn(),
233 ]);
234 }
235
236 /**
237 * Updates the last message of this conversation.
238 */
239 public function updateLastMessage()
240 {
8fbd8b01
MS
241 $sql = "SELECT time, userID, username
242 FROM wcf" . WCF_N . "_conversation_message
243 WHERE conversationID = ?
244 ORDER BY time DESC";
fea86294
TD
245 $statement = WCF::getDB()->prepareStatement($sql, 1);
246 $statement->execute([
247 $this->conversationID,
248 ]);
249 $row = $statement->fetchArray();
250
251 $this->update([
252 'lastPostTime' => $row['time'],
253 'lastPosterID' => $row['userID'],
254 'lastPoster' => $row['username'],
255 ]);
256 }
257
258 /**
259 * Updates the participant summary of the given conversations.
260 *
261 * @param integer[] $conversationIDs
262 */
263 public static function updateParticipantSummaries(array $conversationIDs)
264 {
265 $conversationList = new ConversationList();
266 $conversationList->setObjectIDs($conversationIDs);
267 $conversationList->readObjects();
268
269 foreach ($conversationList as $conversation) {
270 $editor = new self($conversation);
271 $editor->updateParticipantSummary();
272 }
273 }
274
275 /**
276 * Updates the participant counts of the given conversations.
277 *
278 * @param integer[] $conversationIDs
279 */
280 public static function updateParticipantCounts(array $conversationIDs)
281 {
282 $conversationList = new ConversationList();
283 $conversationList->setObjectIDs($conversationIDs);
284 $conversationList->readObjects();
285
286 foreach ($conversationList as $conversation) {
287 $editor = new self($conversation);
288 $editor->updateParticipantCount();
289 }
290 }
9544b6b4 291}