Commit | Line | Data |
---|---|---|
9544b6b4 MW |
1 | <?php |
2 | namespace wcf\data\conversation\message; | |
3 | use wcf\data\conversation\Conversation; | |
3b34d39f | 4 | use wcf\data\conversation\ConversationAction; |
9544b6b4 | 5 | use wcf\data\conversation\ConversationEditor; |
b2de9161 | 6 | use wcf\data\smiley\SmileyCache; |
9544b6b4 | 7 | use wcf\data\AbstractDatabaseObjectAction; |
52971287 | 8 | use wcf\data\DatabaseObject; |
e77f4283 | 9 | use wcf\data\IAttachmentMessageQuickReplyAction; |
4a2ee5bb | 10 | use wcf\data\IMessageInlineEditorAction; |
5fa9d104 | 11 | use wcf\data\IMessageQuoteAction; |
5d7f0df0 | 12 | use wcf\system\attachment\AttachmentHandler; |
a21c8732 | 13 | use wcf\system\bbcode\BBCodeHandler; |
5e52978f AE |
14 | use wcf\system\exception\PermissionDeniedException; |
15 | use wcf\system\exception\UserInputException; | |
5ff95003 | 16 | use wcf\system\html\input\HtmlInputProcessor; |
d8671029 | 17 | use wcf\system\message\censorship\Censorship; |
a0c1a541 | 18 | use wcf\system\message\embedded\object\MessageEmbeddedObjectManager; |
5fa9d104 | 19 | use wcf\system\message\quote\MessageQuoteManager; |
5e52978f | 20 | use wcf\system\message\QuickReplyManager; |
3b37e024 | 21 | use wcf\system\moderation\queue\ModerationQueueManager; |
5e52978f | 22 | use wcf\system\request\LinkHandler; |
80a0761e | 23 | use wcf\system\search\SearchIndexManager; |
b5ffaf76 AE |
24 | use wcf\system\user\notification\object\ConversationMessageUserNotificationObject; |
25 | use wcf\system\user\notification\UserNotificationHandler; | |
df8f8628 | 26 | use wcf\system\user\storage\UserStorageHandler; |
9544b6b4 | 27 | use wcf\system\WCF; |
5e00d333 | 28 | use wcf\util\StringUtil; |
9544b6b4 MW |
29 | |
30 | /** | |
3b37e024 | 31 | * Executes conversation message-related actions. |
9544b6b4 MW |
32 | * |
33 | * @author Marcel Werk | |
4ddaa70e | 34 | * @copyright 2001-2019 WoltLab GmbH |
9544b6b4 | 35 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> |
c032049e | 36 | * @package WoltLabSuite\Core\Data\Conversation\Message |
5def88a8 MS |
37 | * |
38 | * @method ConversationMessageEditor[] getObjects() | |
39 | * @method ConversationMessageEditor getSingleObject() | |
9544b6b4 | 40 | */ |
e77f4283 | 41 | class ConversationMessageAction extends AbstractDatabaseObjectAction implements IAttachmentMessageQuickReplyAction, IMessageInlineEditorAction, IMessageQuoteAction { |
9544b6b4 | 42 | /** |
9c3943b0 | 43 | * @inheritDoc |
9544b6b4 | 44 | */ |
f586b354 | 45 | protected $className = ConversationMessageEditor::class; |
9544b6b4 | 46 | |
5e52978f AE |
47 | /** |
48 | * conversation object | |
1217c56d | 49 | * @var Conversation |
5e52978f | 50 | */ |
1217c56d AE |
51 | public $conversation; |
52 | ||
53 | /** | |
54 | * @var HtmlInputProcessor | |
55 | */ | |
56 | public $htmlInputProcessor; | |
5e52978f | 57 | |
a5bacc02 AE |
58 | /** |
59 | * conversation message object | |
1217c56d | 60 | * @var ConversationMessage |
a5bacc02 | 61 | */ |
1217c56d | 62 | public $message; |
a5bacc02 | 63 | |
9544b6b4 | 64 | /** |
9c3943b0 | 65 | * @inheritDoc |
5def88a8 | 66 | * @return ConversationMessage |
9544b6b4 MW |
67 | */ |
68 | public function create() { | |
2a341b9b AE |
69 | if (!isset($this->parameters['data']['enableHtml'])) $this->parameters['data']['enableHtml'] = 1; |
70 | ||
9544b6b4 MW |
71 | // count attachments |
72 | if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) { | |
73 | $this->parameters['data']['attachments'] = count($this->parameters['attachmentHandler']); | |
74 | } | |
75 | ||
76 | if (LOG_IP_ADDRESS) { | |
77 | // add ip address | |
78 | if (!isset($this->parameters['data']['ipAddress'])) { | |
79 | $this->parameters['data']['ipAddress'] = WCF::getSession()->ipAddress; | |
80 | } | |
81 | } | |
82 | else { | |
83 | // do not track ip address | |
84 | if (isset($this->parameters['data']['ipAddress'])) { | |
85 | unset($this->parameters['data']['ipAddress']); | |
86 | } | |
87 | } | |
88 | ||
5ff95003 | 89 | if (!empty($this->parameters['htmlInputProcessor'])) { |
5887729d AE |
90 | /** @noinspection PhpUndefinedMethodInspection */ |
91 | $this->parameters['data']['message'] = $this->parameters['htmlInputProcessor']->getHtml(); | |
5ff95003 AE |
92 | } |
93 | ||
9544b6b4 | 94 | // create message |
c9ee8de8 | 95 | /** @var ConversationMessage $message */ |
9544b6b4 | 96 | $message = parent::create(); |
a0c1a541 | 97 | $messageEditor = new ConversationMessageEditor($message); |
9544b6b4 | 98 | |
fcf27f27 | 99 | // get conversation |
7eafd933 | 100 | $conversation = (isset($this->parameters['conversation']) ? $this->parameters['conversation'] : new Conversation($message->conversationID)); |
6f1cd040 | 101 | $conversationEditor = new ConversationEditor($conversation); |
61f754e0 | 102 | |
4b541146 | 103 | if (empty($this->parameters['isFirstPost'])) { |
9544b6b4 MW |
104 | // update last message |
105 | $conversationEditor->addMessage($message); | |
64ac54a1 MW |
106 | |
107 | // fire notification event | |
6f1cd040 | 108 | if (!$conversation->isDraft) { |
eaf1c8eb | 109 | $notificationRecipients = array_diff($conversation->getParticipantIDs(true), [$message->userID]); // don't notify message author |
566eb43f | 110 | if (!empty($notificationRecipients)) { |
901d21f2 MS |
111 | UserNotificationHandler::getInstance()->fireEvent( |
112 | 'conversationMessage', | |
113 | 'com.woltlab.wcf.conversation.message.notification', | |
114 | new ConversationMessageUserNotificationObject($message), | |
115 | $notificationRecipients | |
116 | ); | |
566eb43f | 117 | } |
5fa9d104 | 118 | } |
fcf27f27 | 119 | |
ad478273 MW |
120 | $userConversation = Conversation::getUserConversation($conversation->conversationID, $message->userID); |
121 | if ($userConversation !== null && $userConversation->isInvisible) { | |
122 | // make invisible participant visible | |
123 | $sql = "UPDATE wcf".WCF_N."_conversation_to_user | |
124 | SET isInvisible = 0 | |
125 | WHERE participantID = ? | |
126 | AND conversationID = ?"; | |
127 | $statement = WCF::getDB()->prepareStatement($sql); | |
eaf1c8eb | 128 | $statement->execute([$message->userID, $conversation->conversationID]); |
ad478273 MW |
129 | |
130 | $conversationEditor->updateParticipantSummary(); | |
131 | $conversationEditor->updateParticipantCount(); | |
132 | } | |
0ff992a3 AE |
133 | |
134 | // reset visibility if it was hidden but not left | |
135 | $sql = "UPDATE wcf".WCF_N."_conversation_to_user | |
136 | SET hideConversation = ? | |
137 | WHERE conversationID = ? | |
138 | AND hideConversation = ?"; | |
139 | $statement = WCF::getDB()->prepareStatement($sql); | |
eaf1c8eb | 140 | $statement->execute([ |
06695793 | 141 | Conversation::STATE_DEFAULT, |
0ff992a3 | 142 | $conversation->conversationID, |
06695793 | 143 | Conversation::STATE_HIDDEN |
eaf1c8eb | 144 | ]); |
9544b6b4 MW |
145 | } |
146 | ||
df8f8628 | 147 | // reset storage |
462d532a | 148 | UserStorageHandler::getInstance()->reset($conversation->getParticipantIDs(), 'unreadConversationCount'); |
9544b6b4 | 149 | |
80a0761e | 150 | // update search index |
901d21f2 MS |
151 | SearchIndexManager::getInstance()->set( |
152 | 'com.woltlab.wcf.conversation.message', | |
153 | $message->messageID, | |
154 | $message->message, | |
155 | !empty($this->parameters['isFirstPost']) ? $conversation->subject : '', | |
156 | $message->time, | |
157 | $message->userID, | |
158 | $message->username | |
159 | ); | |
9544b6b4 | 160 | |
e3f7a050 MW |
161 | // update attachments |
162 | if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) { | |
b41c9fd6 | 163 | /** @noinspection PhpUndefinedMethodInspection */ |
e3f7a050 MW |
164 | $this->parameters['attachmentHandler']->updateObjectID($message->messageID); |
165 | } | |
166 | ||
a0c1a541 | 167 | // save embedded objects |
5887729d | 168 | if (!empty($this->parameters['htmlInputProcessor'])) { |
2a341b9b AE |
169 | /** @noinspection PhpUndefinedMethodInspection */ |
170 | $this->parameters['htmlInputProcessor']->setObjectID($message->messageID); | |
171 | ||
a94cad7f | 172 | if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->parameters['htmlInputProcessor'])) { |
5887729d AE |
173 | $messageEditor->update(['hasEmbeddedObjects' => 1]); |
174 | } | |
a0c1a541 MW |
175 | } |
176 | ||
5fa9d104 | 177 | // clear quotes |
f1781bd0 AE |
178 | if (isset($this->parameters['removeQuoteIDs']) && !empty($this->parameters['removeQuoteIDs'])) { |
179 | MessageQuoteManager::getInstance()->markQuotesForRemoval($this->parameters['removeQuoteIDs']); | |
180 | } | |
5fa9d104 AE |
181 | MessageQuoteManager::getInstance()->removeMarkedQuotes(); |
182 | ||
9544b6b4 MW |
183 | // return new message |
184 | return $message; | |
185 | } | |
c764783c MW |
186 | |
187 | /** | |
9c3943b0 | 188 | * @inheritDoc |
c764783c MW |
189 | */ |
190 | public function update() { | |
191 | // count attachments | |
192 | if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) { | |
193 | $this->parameters['data']['attachments'] = count($this->parameters['attachmentHandler']); | |
194 | } | |
195 | ||
5887729d AE |
196 | if (!empty($this->parameters['htmlInputProcessor'])) { |
197 | /** @noinspection PhpUndefinedMethodInspection */ | |
198 | $this->parameters['data']['message'] = $this->parameters['htmlInputProcessor']->getHtml(); | |
199 | } | |
200 | ||
c764783c | 201 | parent::update(); |
80a0761e | 202 | |
a0c1a541 | 203 | // update search index / embedded objects |
28bd6cbd | 204 | if (isset($this->parameters['data']) && isset($this->parameters['data']['message'])) { |
c9ee8de8 | 205 | foreach ($this->getObjects() as $message) { |
28bd6cbd | 206 | $conversation = $message->getConversation(); |
901d21f2 MS |
207 | SearchIndexManager::getInstance()->set( |
208 | 'com.woltlab.wcf.conversation.message', | |
209 | $message->messageID, | |
210 | $this->parameters['data']['message'], | |
211 | $conversation->firstMessageID == $message->messageID ? $conversation->subject : '', | |
212 | $message->time, | |
213 | $message->userID, | |
214 | $message->username | |
215 | ); | |
28bd6cbd | 216 | |
5887729d | 217 | if (!empty($this->parameters['htmlInputProcessor'])) { |
2a341b9b AE |
218 | /** @noinspection PhpUndefinedMethodInspection */ |
219 | $this->parameters['htmlInputProcessor']->setObjectID($message->messageID); | |
220 | ||
a94cad7f | 221 | if ($message->hasEmbeddedObjects != MessageEmbeddedObjectManager::getInstance()->registerObjects($this->parameters['htmlInputProcessor'])) { |
8a6ee075 | 222 | $message->update(['hasEmbeddedObjects' => $message->hasEmbeddedObjects ? 0 : 1]); |
5887729d | 223 | } |
28bd6cbd | 224 | } |
a0c1a541 | 225 | } |
fcf27f27 | 226 | } |
c764783c | 227 | } |
5e52978f | 228 | |
db07cb2d | 229 | /** |
9c3943b0 | 230 | * @inheritDoc |
db07cb2d AE |
231 | */ |
232 | public function delete() { | |
233 | $count = parent::delete(); | |
234 | ||
eaf1c8eb | 235 | $attachmentMessageIDs = $conversationIDs = []; |
c9ee8de8 | 236 | foreach ($this->getObjects() as $message) { |
3b34d39f MS |
237 | if (!in_array($message->conversationID, $conversationIDs)) { |
238 | $conversationIDs[] = $message->conversationID; | |
239 | } | |
240 | ||
5d7f0df0 MW |
241 | if ($message->attachments) { |
242 | $attachmentMessageIDs[] = $message->messageID; | |
db07cb2d AE |
243 | } |
244 | } | |
245 | ||
3b34d39f MS |
246 | // rebuild conversations |
247 | if (!empty($conversationIDs)) { | |
248 | $conversationAction = new ConversationAction($conversationIDs, 'rebuild'); | |
249 | $conversationAction->executeAction(); | |
250 | } | |
251 | ||
5d7f0df0 MW |
252 | if (!empty($this->objectIDs)) { |
253 | // delete notifications | |
9888e764 | 254 | UserNotificationHandler::getInstance()->removeNotifications('com.woltlab.wcf.conversation.message.notification', $this->objectIDs); |
3b34d39f | 255 | |
5d7f0df0 MW |
256 | // update search index |
257 | SearchIndexManager::getInstance()->delete('com.woltlab.wcf.conversation.message', $this->objectIDs); | |
3b37e024 | 258 | |
a0c1a541 MW |
259 | // update embedded objects |
260 | MessageEmbeddedObjectManager::getInstance()->removeObjects('com.woltlab.wcf.conversation.message', $this->objectIDs); | |
261 | ||
3b37e024 AE |
262 | // remove moderation queues |
263 | ModerationQueueManager::getInstance()->removeQueues('com.woltlab.wcf.conversation.message', $this->objectIDs); | |
5d7f0df0 MW |
264 | } |
265 | ||
266 | // remove attachments | |
267 | if (!empty($attachmentMessageIDs)) { | |
268 | AttachmentHandler::removeAttachments('com.woltlab.wcf.conversation.message', $attachmentMessageIDs); | |
269 | } | |
270 | ||
db07cb2d AE |
271 | return $count; |
272 | } | |
273 | ||
5e52978f | 274 | /** |
9c3943b0 | 275 | * @inheritDoc |
5e52978f AE |
276 | */ |
277 | public function validateQuickReply() { | |
c2514e3d | 278 | QuickReplyManager::getInstance()->setDisallowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.disallowedBBCodes'))); |
f586b354 | 279 | QuickReplyManager::getInstance()->validateParameters($this, $this->parameters, Conversation::class); |
5e52978f AE |
280 | } |
281 | ||
282 | /** | |
9c3943b0 | 283 | * @inheritDoc |
5e52978f AE |
284 | */ |
285 | public function quickReply() { | |
286 | return QuickReplyManager::getInstance()->createMessage( | |
287 | $this, | |
288 | $this->parameters, | |
f586b354 | 289 | ConversationAction::class, |
9353cd87 AE |
290 | CONVERSATION_LIST_DEFAULT_SORT_ORDER, |
291 | 'conversationMessageList' | |
5e52978f AE |
292 | ); |
293 | } | |
294 | ||
a5bacc02 | 295 | /** |
9c3943b0 | 296 | * @inheritDoc |
a5bacc02 AE |
297 | */ |
298 | public function validateJumpToExtended() { | |
c2b8907c AE |
299 | $this->readInteger('containerID'); |
300 | $this->readString('message', true); | |
a7dd6eef | 301 | $this->readString('tmpHash', true); |
a5bacc02 | 302 | |
c2b8907c AE |
303 | $this->conversation = new Conversation($this->parameters['containerID']); |
304 | if (!$this->conversation->conversationID) { | |
86a5431b | 305 | throw new UserInputException('containerID'); |
a5bacc02 | 306 | } |
eaf1c8eb | 307 | else if ($this->conversation->isClosed || !Conversation::isParticipant([$this->conversation->conversationID])) { |
c2b8907c | 308 | throw new PermissionDeniedException(); |
a5bacc02 AE |
309 | } |
310 | ||
311 | // editing existing message | |
312 | if (isset($this->parameters['messageID'])) { | |
313 | $this->message = new ConversationMessage(intval($this->parameters['messageID'])); | |
314 | if (!$this->message->messageID || ($this->message->conversationID != $this->conversation->conversationID)) { | |
315 | throw new UserInputException('messageID'); | |
316 | } | |
61f754e0 | 317 | |
a5bacc02 AE |
318 | if (!$this->message->canEdit()) { |
319 | throw new PermissionDeniedException(); | |
320 | } | |
321 | } | |
322 | } | |
323 | ||
324 | /** | |
9c3943b0 | 325 | * @inheritDoc |
a5bacc02 AE |
326 | */ |
327 | public function jumpToExtended() { | |
328 | // quick reply | |
329 | if ($this->message === null) { | |
330 | QuickReplyManager::getInstance()->setMessage('conversation', $this->conversation->conversationID, $this->parameters['message']); | |
eaf1c8eb | 331 | $url = LinkHandler::getInstance()->getLink('ConversationMessageAdd', ['id' => $this->conversation->conversationID]); |
a5bacc02 AE |
332 | } |
333 | else { | |
334 | // editing message | |
335 | QuickReplyManager::getInstance()->setMessage('conversationMessage', $this->message->messageID, $this->parameters['message']); | |
eaf1c8eb | 336 | $url = LinkHandler::getInstance()->getLink('ConversationMessageEdit', ['id' => $this->message->messageID]); |
a5bacc02 AE |
337 | } |
338 | ||
a7dd6eef AE |
339 | if (!empty($this->parameters['tmpHash'])) { |
340 | QuickReplyManager::getInstance()->setTmpHash($this->parameters['tmpHash']); | |
341 | } | |
342 | ||
a5bacc02 | 343 | // redirect |
eaf1c8eb | 344 | return [ |
a5bacc02 | 345 | 'url' => $url |
eaf1c8eb | 346 | ]; |
a5bacc02 AE |
347 | } |
348 | ||
b5ffaf76 | 349 | /** |
9c3943b0 | 350 | * @inheritDoc |
b5ffaf76 AE |
351 | */ |
352 | public function validateBeginEdit() { | |
c2b8907c AE |
353 | $this->readInteger('containerID'); |
354 | $this->readInteger('objectID'); | |
355 | ||
356 | $this->conversation = new Conversation($this->parameters['containerID']); | |
357 | if (!$this->conversation->conversationID) { | |
b5ffaf76 AE |
358 | throw new UserInputException('containerID'); |
359 | } | |
c2b8907c | 360 | |
eaf1c8eb | 361 | if ($this->conversation->isClosed || !Conversation::isParticipant([$this->conversation->conversationID])) { |
c2b8907c | 362 | throw new PermissionDeniedException(); |
b5ffaf76 AE |
363 | } |
364 | ||
c2b8907c AE |
365 | $this->message = new ConversationMessage($this->parameters['objectID']); |
366 | if (!$this->message->messageID) { | |
b5ffaf76 AE |
367 | throw new UserInputException('objectID'); |
368 | } | |
c2b8907c AE |
369 | |
370 | if (!$this->message->canEdit()) { | |
371 | throw new PermissionDeniedException(); | |
b5ffaf76 | 372 | } |
c2514e3d AE |
373 | |
374 | BBCodeHandler::getInstance()->setDisallowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.disallowedBBCodes'))); | |
b5ffaf76 AE |
375 | } |
376 | ||
377 | /** | |
9c3943b0 | 378 | * @inheritDoc |
b5ffaf76 AE |
379 | */ |
380 | public function beginEdit() { | |
eaf1c8eb | 381 | WCF::getTPL()->assign([ |
b2de9161 | 382 | 'defaultSmilies' => SmileyCache::getInstance()->getCategorySmilies(), |
b5ffaf76 | 383 | 'message' => $this->message, |
a21c8732 | 384 | 'permissionCanUseSmilies' => 'user.message.canUseSmilies', |
71d51a10 | 385 | 'wysiwygSelector' => 'messageEditor'.$this->message->messageID, |
eaf1c8eb | 386 | ]); |
b5ffaf76 | 387 | |
71d51a10 MS |
388 | $tmpHash = StringUtil::getRandomID(); |
389 | $attachmentHandler = new AttachmentHandler('com.woltlab.wcf.conversation.message', $this->message->messageID, $tmpHash); | |
390 | $attachmentList = $attachmentHandler->getAttachmentList(); | |
391 | ||
392 | WCF::getTPL()->assign([ | |
393 | 'attachmentHandler' => $attachmentHandler, | |
394 | 'attachmentList' => $attachmentList->getObjects(), | |
395 | 'attachmentObjectID' => $this->message->messageID, | |
396 | 'attachmentObjectType' => 'com.woltlab.wcf.conversation.message', | |
397 | 'attachmentParentObjectID' => 0, | |
398 | 'tmpHash' => $tmpHash, | |
399 | ]); | |
5e00d333 | 400 | |
eaf1c8eb | 401 | return [ |
b5ffaf76 | 402 | 'actionName' => 'beginEdit', |
71d51a10 | 403 | 'template' => WCF::getTPL()->fetch('conversationMessageInlineEditor'), |
eaf1c8eb | 404 | ]; |
b5ffaf76 AE |
405 | } |
406 | ||
407 | /** | |
9c3943b0 | 408 | * @inheritDoc |
b5ffaf76 AE |
409 | */ |
410 | public function validateSave() { | |
9101781c MS |
411 | $this->readString('message', true, 'data'); |
412 | ||
413 | if (empty($this->parameters['data']['message'])) { | |
a943eb00 | 414 | throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.global.form.error.empty')); |
9101781c | 415 | } |
b5ffaf76 AE |
416 | |
417 | $this->validateBeginEdit(); | |
5ff95003 | 418 | |
2cccc1b6 | 419 | $this->validateMessage($this->conversation, $this->getHtmlInputProcessor($this->parameters['data']['message'], $this->message->messageID)); |
b5ffaf76 AE |
420 | } |
421 | ||
422 | /** | |
9c3943b0 | 423 | * @inheritDoc |
b5ffaf76 AE |
424 | */ |
425 | public function save() { | |
5887729d | 426 | $data = []; |
5ff95003 | 427 | |
e7ed68e5 MW |
428 | if (!$this->message->getConversation()->isDraft) { |
429 | $data['lastEditTime'] = TIME_NOW; | |
430 | $data['editCount'] = $this->message->editCount + 1; | |
431 | } | |
28bd6cbd | 432 | // execute update action |
5887729d AE |
433 | $action = new ConversationMessageAction([$this->message], 'update', [ |
434 | 'data' => $data, | |
435 | 'htmlInputProcessor' => $this->getHtmlInputProcessor() | |
436 | ]); | |
28bd6cbd | 437 | $action->executeAction(); |
b5ffaf76 AE |
438 | |
439 | // load new message | |
440 | $this->message = new ConversationMessage($this->message->messageID); | |
f7b9b1f3 | 441 | $this->message->getAttachments(); |
b5ffaf76 | 442 | |
71d51a10 MS |
443 | $attachmentList = $this->message->getAttachments(true); |
444 | $count = 0; | |
445 | if ($attachmentList !== null) { | |
446 | // set permissions | |
447 | $attachmentList->setPermissions([ | |
448 | 'canDownload' => true, | |
449 | 'canViewPreview' => true, | |
450 | ]); | |
a91ea2de | 451 | |
71d51a10 MS |
452 | $count = count($attachmentList); |
453 | } | |
454 | ||
455 | // update count to reflect number of attachments after edit | |
456 | if ($count != $this->message->attachments) { | |
457 | $messageEditor = new ConversationMessageEditor($this->message); | |
458 | $messageEditor->update(['attachments' => $count]); | |
5e00d333 MW |
459 | } |
460 | ||
461 | // load embedded objects | |
eaf1c8eb | 462 | MessageEmbeddedObjectManager::getInstance()->loadObjects('com.woltlab.wcf.conversation.message', [$this->message->messageID]); |
5e00d333 | 463 | |
eaf1c8eb | 464 | $data = [ |
b5ffaf76 AE |
465 | 'actionName' => 'save', |
466 | 'message' => $this->message->getFormattedMessage() | |
eaf1c8eb | 467 | ]; |
5e00d333 | 468 | |
71d51a10 MS |
469 | WCF::getTPL()->assign([ |
470 | 'attachmentList' => $attachmentList, | |
471 | 'objectID' => $this->message->messageID | |
472 | ]); | |
473 | $data['attachmentList'] = WCF::getTPL()->fetch('attachments'); | |
5e00d333 MW |
474 | |
475 | return $data; | |
b5ffaf76 AE |
476 | } |
477 | ||
5e52978f | 478 | /** |
9c3943b0 | 479 | * @inheritDoc |
5e52978f | 480 | */ |
52971287 | 481 | public function validateContainer(DatabaseObject $conversation) { |
b41c9fd6 MS |
482 | /** @var Conversation $conversation */ |
483 | ||
5e52978f AE |
484 | if (!$conversation->conversationID) { |
485 | throw new UserInputException('objectID'); | |
486 | } | |
962207b7 MW |
487 | if ($conversation->isClosed) { |
488 | throw new PermissionDeniedException(); | |
489 | } | |
490 | $conversation->loadUserParticipation(); | |
0e2a5b3e | 491 | if (!$conversation->canRead() || !$conversation->canReply()) { |
5e52978f AE |
492 | throw new PermissionDeniedException(); |
493 | } | |
494 | } | |
495 | ||
b6c2b36c | 496 | /** |
9c3943b0 | 497 | * @inheritDoc |
b6c2b36c | 498 | */ |
5ff95003 | 499 | public function validateMessage(DatabaseObject $container, HtmlInputProcessor $htmlInputProcessor) { |
c2514e3d AE |
500 | $message = $htmlInputProcessor->getTextContent(); |
501 | if (mb_strlen($message) > WCF::getSession()->getPermission('user.conversation.maxLength')) { | |
eaf1c8eb | 502 | throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.tooLong', ['maxTextLength' => WCF::getSession()->getPermission('user.conversation.maxLength')])); |
84cebd68 MW |
503 | } |
504 | ||
027c57f4 | 505 | // search for disallowed bbcodes |
c2514e3d | 506 | $disallowedBBCodes = $htmlInputProcessor->validate(); |
027c57f4 | 507 | if (!empty($disallowedBBCodes)) { |
eaf1c8eb | 508 | throw new UserInputException('text', WCF::getLanguage()->getDynamicVariable('wcf.message.error.disallowedBBCodes', ['disallowedBBCodes' => $disallowedBBCodes])); |
027c57f4 MS |
509 | } |
510 | ||
d8671029 MW |
511 | // search for censored words |
512 | if (ENABLE_CENSORSHIP) { | |
513 | $result = Censorship::getInstance()->test($message); | |
514 | if ($result) { | |
eaf1c8eb | 515 | throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.censoredWordsFound', ['censoredWords' => $result])); |
d8671029 | 516 | } |
c2514e3d | 517 | } |
d8671029 | 518 | } |
b6c2b36c | 519 | |
9353cd87 | 520 | /** |
9c3943b0 | 521 | * @inheritDoc |
9353cd87 AE |
522 | */ |
523 | public function getMessageList(DatabaseObject $conversation, $lastMessageTime) { | |
5acf7f80 MS |
524 | /** @var Conversation $conversation */ |
525 | ||
648456e0 | 526 | $messageList = new ViewableConversationMessageList(); |
a0c1a541 | 527 | $messageList->setConversation($conversation); |
eaf1c8eb MS |
528 | $messageList->getConditionBuilder()->add("conversation_message.conversationID = ?", [$conversation->conversationID]); |
529 | $messageList->getConditionBuilder()->add("conversation_message.time > ?", [$lastMessageTime]); | |
9353cd87 AE |
530 | $messageList->sqlOrderBy = "conversation_message.time ".CONVERSATION_LIST_DEFAULT_SORT_ORDER; |
531 | $messageList->readObjects(); | |
a480521b | 532 | |
9353cd87 AE |
533 | return $messageList; |
534 | } | |
535 | ||
5e52978f | 536 | /** |
9c3943b0 | 537 | * @inheritDoc |
5e52978f | 538 | */ |
52971287 | 539 | public function getPageNo(DatabaseObject $conversation) { |
b41c9fd6 MS |
540 | /** @var Conversation $conversation */ |
541 | ||
5e52978f AE |
542 | $sql = "SELECT COUNT(*) AS count |
543 | FROM wcf".WCF_N."_conversation_message | |
544 | WHERE conversationID = ?"; | |
545 | $statement = WCF::getDB()->prepareStatement($sql); | |
eaf1c8eb | 546 | $statement->execute([$conversation->conversationID]); |
5e52978f AE |
547 | $count = $statement->fetchArray(); |
548 | ||
eaf1c8eb | 549 | return [intval(ceil($count['count'] / CONVERSATION_MESSAGES_PER_PAGE)), $count['count']]; |
5e52978f AE |
550 | } |
551 | ||
552 | /** | |
9c3943b0 | 553 | * @inheritDoc |
5e52978f | 554 | */ |
52971287 | 555 | public function getRedirectUrl(DatabaseObject $conversation, DatabaseObject $message) { |
b41c9fd6 | 556 | /** @var ConversationMessage $message */ |
1743db5a | 557 | return $message->getLink(); |
5e52978f | 558 | } |
5fa9d104 | 559 | |
42335f61 | 560 | /** |
9c3943b0 | 561 | * @inheritDoc |
42335f61 | 562 | */ |
09f53f03 | 563 | public function validateSaveFullQuote() { |
c2b8907c | 564 | $this->message = $this->getSingleObject(); |
61f754e0 | 565 | |
eaf1c8eb | 566 | if (!Conversation::isParticipant([$this->message->conversationID])) { |
42335f61 AE |
567 | throw new PermissionDeniedException(); |
568 | } | |
569 | } | |
570 | ||
571 | /** | |
9c3943b0 | 572 | * @inheritDoc |
42335f61 AE |
573 | */ |
574 | public function saveFullQuote() { | |
2aa7b942 AE |
575 | $quoteID = MessageQuoteManager::getInstance()->addQuote( |
576 | 'com.woltlab.wcf.conversation.message', | |
577 | $this->message->conversationID, | |
578 | $this->message->messageID, | |
579 | $this->message->getExcerpt(), | |
580 | $this->message->getMessage() | |
581 | ); | |
582 | ||
583 | if ($quoteID === false) { | |
901d21f2 MS |
584 | $removeQuoteID = MessageQuoteManager::getInstance()->getQuoteID( |
585 | 'com.woltlab.wcf.conversation.message', | |
586 | $this->message->messageID, | |
587 | $this->message->getExcerpt(), | |
588 | $this->message->getMessage() | |
589 | ); | |
2aa7b942 | 590 | MessageQuoteManager::getInstance()->removeQuote($removeQuoteID); |
42335f61 | 591 | } |
db864366 | 592 | |
eaf1c8eb | 593 | $returnValues = [ |
ce6fa919 | 594 | 'count' => MessageQuoteManager::getInstance()->countQuotes(), |
eaf1c8eb MS |
595 | 'fullQuoteMessageIDs' => MessageQuoteManager::getInstance()->getFullQuoteObjectIDs(['com.woltlab.wcf.conversation.message']) |
596 | ]; | |
2aa7b942 AE |
597 | |
598 | if ($quoteID) { | |
599 | $returnValues['renderedQuote'] = MessageQuoteManager::getInstance()->getQuoteComponents($quoteID); | |
600 | } | |
601 | ||
602 | return $returnValues; | |
42335f61 AE |
603 | } |
604 | ||
5fa9d104 | 605 | /** |
9c3943b0 | 606 | * @inheritDoc |
5fa9d104 AE |
607 | */ |
608 | public function validateSaveQuote() { | |
c2b8907c | 609 | $this->readString('message'); |
97266c6a | 610 | $this->readBoolean('renderQuote', true); |
c2b8907c | 611 | $this->message = $this->getSingleObject(); |
5fa9d104 | 612 | |
eaf1c8eb | 613 | if (!Conversation::isParticipant([$this->message->conversationID])) { |
5fa9d104 AE |
614 | throw new PermissionDeniedException(); |
615 | } | |
616 | } | |
617 | ||
618 | /** | |
9c3943b0 | 619 | * @inheritDoc |
5fa9d104 AE |
620 | */ |
621 | public function saveQuote() { | |
901d21f2 MS |
622 | $quoteID = MessageQuoteManager::getInstance()->addQuote( |
623 | 'com.woltlab.wcf.conversation.message', | |
624 | $this->message->conversationID, | |
625 | $this->message->messageID, | |
626 | $this->parameters['message'], | |
627 | false | |
628 | ); | |
5fa9d104 | 629 | |
eaf1c8eb | 630 | $returnValues = [ |
ce6fa919 | 631 | 'count' => MessageQuoteManager::getInstance()->countQuotes(), |
eaf1c8eb MS |
632 | 'fullQuoteMessageIDs' => MessageQuoteManager::getInstance()->getFullQuoteObjectIDs(['com.woltlab.wcf.conversation.message']) |
633 | ]; | |
9ac36595 AE |
634 | |
635 | if ($this->parameters['renderQuote']) { | |
5d9e720d | 636 | $returnValues['renderedQuote'] = MessageQuoteManager::getInstance()->getQuoteComponents($quoteID); |
9ac36595 AE |
637 | } |
638 | ||
639 | return $returnValues; | |
5fa9d104 | 640 | } |
1ffd7648 AE |
641 | |
642 | /** | |
9c3943b0 | 643 | * @inheritDoc |
1ffd7648 AE |
644 | */ |
645 | public function validateGetRenderedQuotes() { | |
646 | $this->readInteger('parentObjectID'); | |
647 | ||
648 | $this->conversation = new Conversation($this->parameters['parentObjectID']); | |
649 | if (!$this->conversation->conversationID) { | |
650 | throw new UserInputException('parentObjectID'); | |
651 | } | |
652 | } | |
653 | ||
654 | /** | |
9c3943b0 | 655 | * @inheritDoc |
1ffd7648 AE |
656 | */ |
657 | public function getRenderedQuotes() { | |
3c427544 | 658 | $quotes = MessageQuoteManager::getInstance()->getQuotesByParentObjectID('com.woltlab.wcf.conversation.message', $this->conversation->conversationID); |
ba1ab5e5 | 659 | |
eaf1c8eb | 660 | return [ |
1ffd7648 | 661 | 'template' => implode("\n\n", $quotes) |
eaf1c8eb | 662 | ]; |
1ffd7648 | 663 | } |
e77f4283 AE |
664 | |
665 | /** | |
9c3943b0 | 666 | * @inheritDoc |
e77f4283 AE |
667 | */ |
668 | public function getAttachmentHandler(DatabaseObject $conversation) { | |
669 | return new AttachmentHandler('com.woltlab.wcf.conversation.message', 0, $this->parameters['tmpHash']); | |
670 | } | |
5ff95003 AE |
671 | |
672 | /** | |
673 | * @inheritDoc | |
674 | */ | |
2cccc1b6 | 675 | public function getHtmlInputProcessor($message = null, $objectID = 0) { |
5ff95003 AE |
676 | if ($message === null) { |
677 | return $this->htmlInputProcessor; | |
678 | } | |
679 | ||
680 | $this->htmlInputProcessor = new HtmlInputProcessor(); | |
2cccc1b6 | 681 | $this->htmlInputProcessor->process($message, 'com.woltlab.wcf.conversation.message', $objectID); |
5ff95003 AE |
682 | |
683 | return $this->htmlInputProcessor; | |
684 | } | |
9544b6b4 | 685 | } |