Commit | Line | Data |
---|---|---|
9544b6b4 | 1 | <?php |
fea86294 | 2 | |
9544b6b4 | 3 | namespace wcf\data\conversation; |
fea86294 | 4 | |
c764783c | 5 | use wcf\data\conversation\message\ConversationMessage; |
9544b6b4 | 6 | use wcf\data\DatabaseObjectEditor; |
363e6c08 | 7 | use wcf\system\database\util\PreparedStatementConditionBuilder; |
9544b6b4 MW |
8 | use 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 |
22 | class 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 | } |